From 5eb3bc6d5594fccfff26329a26225f999e971652 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Mon, 16 Apr 2007 19:08:42 +0000 Subject: first step forward to merge conntrackd and conntrack into the same building chain --- src/stats-mode.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 src/stats-mode.c (limited to 'src/stats-mode.c') diff --git a/src/stats-mode.c b/src/stats-mode.c new file mode 100644 index 0000000..9647bbf --- /dev/null +++ b/src/stats-mode.c @@ -0,0 +1,151 @@ +/* + * (C) 2006 by Pablo Neira Ayuso + * + * 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 +#include "cache.h" +#include "conntrackd.h" +#include +#include +#include +#include "us-conntrack.h" +#include +#include + +static int init_stats(void) +{ + int ret; + + state.stats = malloc(sizeof(struct ct_stats_state)); + if (!state.stats) { + dlog(STATE(log), "[FAIL] can't allocate memory for stats sync"); + return -1; + } + memset(state.stats, 0, sizeof(struct ct_stats_state)); + + STATE_STATS(cache) = cache_create("stats", + LIFETIME, + CONFIG(family), + NULL); + if (!STATE_STATS(cache)) { + dlog(STATE(log), "[FAIL] can't allocate memory for the " + "external cache"); + return -1; + } + + return 0; +} + +static void kill_stats() +{ + cache_destroy(STATE_STATS(cache)); +} + +/* handler for requests coming via UNIX socket */ +static int local_handler_stats(int fd, int type, void *data) +{ + int ret = 1; + + switch(type) { + case DUMP_INTERNAL: + cache_dump(STATE_STATS(cache), fd, NFCT_O_PLAIN); + break; + case DUMP_INT_XML: + cache_dump(STATE_SYNC(internal), fd, NFCT_O_XML); + break; + case FLUSH_CACHE: + dlog(STATE(log), "[REQ] flushing caches"); + cache_flush(STATE_STATS(cache)); + break; + case KILL: + killer(); + break; + case STATS: + cache_stats(STATE_STATS(cache), fd); + dump_traffic_stats(fd); + break; + default: + ret = 0; + break; + } + + return ret; +} + +static void dump_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) +{ + if (cache_update_force(STATE_STATS(cache), ct)) + debug_ct(ct, "resync entry"); +} + +static void event_new_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) +{ + debug_ct(ct, "debug event"); + if (cache_add(STATE_STATS(cache), ct)) { + debug_ct(ct, "cache new"); + } else { + dlog(STATE(log), "can't add to cache cache: " + "%s\n", strerror(errno)); + debug_ct(ct, "can't add"); + } +} + +static void event_update_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) +{ + debug_ct(ct, "update"); + + if (!cache_update(STATE_STATS(cache), ct)) { + /* + * Perhaps we are losing events. If we are working + * in relax mode then add a new entry to the cache. + * + * FIXME: relax transitions not implemented yet + */ + if ((CONFIG(flags) & RELAX_TRANSITIONS) + && cache_add(STATE_STATS(cache), ct)) { + debug_ct(ct, "forcing cache update"); + } else { + debug_ct(ct, "can't update"); + return; + } + } + debug_ct(ct, "update"); +} + +static int event_destroy_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) +{ + if (cache_del(STATE_STATS(cache), ct)) { + debug_ct(ct, "cache destroy"); + return 1; + } else { + debug_ct(ct, "can't destroy!"); + return 0; + } +} + +struct ct_mode stats_mode = { + .init = init_stats, + .add_fds_to_set = NULL, + .step = NULL, + .local = local_handler_stats, + .kill = kill_stats, + .dump = dump_stats, + .overrun = dump_stats, + .event_new = event_new_stats, + .event_upd = event_update_stats, + .event_dst = event_destroy_stats +}; -- cgit v1.2.3 From 9f1b4b2d028129966f7e6f23cec6ac0712c2b1b6 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Sun, 20 May 2007 21:13:06 +0000 Subject: - introduce cache_iterate - empty debug_ct function if DEBUG_CT is not set - revisit overrun handler: this is a hard battle, just try to do our best here, call Patrick :) - explicit warning message when netlink_buffer_max_growth is reached - fix silly bug in stats-mode when dumping in XML format - fix UDP handler for conntrack --- extensions/libct_proto_udp.c | 54 +++++++++++++++++----------- include/cache.h | 1 + include/conntrackd.h | 4 +-- include/debug.h | 4 +++ src/cache.c | 9 +++++ src/cache_iterators.c | 6 ++-- src/netlink.c | 73 ++++++------------------------------- src/run.c | 11 +----- src/stats-mode.c | 48 +++++++++++++++++++++++-- src/sync-mode.c | 85 ++++++++++++++++++++++++++++++++++++++++++-- 10 files changed, 190 insertions(+), 105 deletions(-) (limited to 'src/stats-mode.c') diff --git a/extensions/libct_proto_udp.c b/extensions/libct_proto_udp.c index 6e8d13c..bae9bf8 100644 --- a/extensions/libct_proto_udp.c +++ b/extensions/libct_proto_udp.c @@ -43,12 +43,10 @@ static void help() static int parse_options(char c, char *argv[], struct nf_conntrack *ct, - struct nfct_tuple *exptuple, - struct nfct_tuple *mask, + struct nf_conntrack *exptuple, + struct nf_conntrack *mask, unsigned int *flags) { - int i; - switch(c) { case '1': if (!optarg) @@ -91,28 +89,44 @@ static int parse_options(char c, char *argv[], *flags |= UDP_REPL_DPORT; break; case '5': - if (optarg) { - mask->l4src.udp.port = htons(atoi(optarg)); - *flags |= UDP_MASK_SPORT; - } + if (!optarg) + break; + + nfct_set_attr_u16(mask, + ATTR_ORIG_PORT_SRC, + htons(atoi(optarg))); + + *flags |= UDP_MASK_SPORT; break; case '6': - if (optarg) { - mask->l4dst.udp.port = htons(atoi(optarg)); - *flags |= UDP_MASK_DPORT; - } + if (!optarg) + break; + + nfct_set_attr_u16(mask, + ATTR_ORIG_PORT_DST, + htons(atoi(optarg))); + + *flags |= UDP_MASK_DPORT; break; case '7': - if (optarg) { - exptuple->l4src.udp.port = htons(atoi(optarg)); - *flags |= UDP_EXPTUPLE_SPORT; - } + if (!optarg) + break; + + nfct_set_attr_u16(exptuple, + ATTR_ORIG_PORT_SRC, + htons(atoi(optarg))); + + *flags |= UDP_EXPTUPLE_SPORT; break; case '8': - if (optarg) { - exptuple->l4dst.udp.port = htons(atoi(optarg)); - *flags |= UDP_EXPTUPLE_DPORT; - } + if (!optarg) + break; + + nfct_set_attr_u16(exptuple, + ATTR_ORIG_PORT_DST, + htons(atoi(optarg))); + + *flags |= UDP_EXPTUPLE_DPORT; break; } return 1; diff --git a/include/cache.h b/include/cache.h index 7d9559a..e755dbe 100644 --- a/include/cache.h +++ b/include/cache.h @@ -82,6 +82,7 @@ int cache_test(struct cache *c, struct nf_conntrack *ct); void cache_stats(struct cache *c, int fd); struct us_conntrack *cache_get_conntrack(struct cache *, void *); void *cache_get_extra(struct cache *, void *); +void cache_iterate(struct cache *c, void *data, int (*iterate)(void *data1, void *data2)); /* iterators */ void cache_dump(struct cache *c, int fd, int type); diff --git a/include/conntrackd.h b/include/conntrackd.h index a5f7a3a..76b9747 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -102,11 +102,9 @@ struct ct_general_state { struct ignore_pool *ignore_pool; struct nfnl_handle *event; /* event handler */ - struct nfnl_handle *sync; /* sync handler */ struct nfnl_handle *dump; /* dump handler */ struct nfnl_subsys_handle *subsys_event; /* events */ - struct nfnl_subsys_handle *subsys_sync; /* resync */ struct nfnl_subsys_handle *subsys_dump; /* dump */ /* statistics */ @@ -159,7 +157,7 @@ struct ct_mode { int (*local)(int fd, int type, void *data); void (*kill)(void); void (*dump)(struct nf_conntrack *ct, struct nlmsghdr *nlh); - void (*overrun)(struct nf_conntrack *ct, struct nlmsghdr *nlh); + void (*overrun)(void); void (*event_new)(struct nf_conntrack *ct, struct nlmsghdr *nlh); void (*event_upd)(struct nf_conntrack *ct, struct nlmsghdr *nlh); int (*event_dst)(struct nf_conntrack *ct, struct nlmsghdr *nlh); diff --git a/include/debug.h b/include/debug.h index 67f2c71..4d1f44f 100644 --- a/include/debug.h +++ b/include/debug.h @@ -11,8 +11,11 @@ #include #include +#undef DEBUG_CT + static inline void debug_ct(struct nf_conntrack *ct, char *msg) { +#ifdef DEBUG_CT struct in_addr addr, addr2, addr3, addr4; debug("----%s (%p) ----\n", msg, ct); @@ -48,6 +51,7 @@ static inline void debug_ct(struct nf_conntrack *ct, char *msg) inet_ntoa(addr4), ntohs(nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST))); debug("-------------------------\n"); +#endif } #endif diff --git a/src/cache.c b/src/cache.c index 32caee5..1b130c8 100644 --- a/src/cache.c +++ b/src/cache.c @@ -445,3 +445,12 @@ void cache_stats(struct cache *c, int fd) unlock(); send(fd, buf, size, 0); } + +void cache_iterate(struct cache *c, + void *data, + int (*iterate)(void *data1, void *data2)) +{ + lock(); + hashtable_iterate(c->h, data, iterate); + unlock(); +} diff --git a/src/cache_iterators.c b/src/cache_iterators.c index e1f3798..1c03fef 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -111,7 +111,7 @@ static int do_commit(void *data1, void *data2) */ nfct_set_attr_u32(ct, ATTR_TIMEOUT, CONFIG(commit_timeout)); - ret = nfct_build_query(STATE(subsys_sync), + ret = nfct_build_query(STATE(subsys_dump), NFCT_Q_CREATE, ct, nlh, @@ -125,7 +125,7 @@ static int do_commit(void *data1, void *data2) return 0; } - ret = nfnl_query(STATE(sync), nlh); + ret = nfnl_query(STATE(dump), nlh); if (ret == -1) { switch(errno) { case EEXIST: @@ -211,7 +211,7 @@ static int do_bulk(void *data1, void *data2) struct nlnetwork *net = (struct nlnetwork *) buf; ret = build_network_msg(NFCT_Q_UPDATE, - STATE(subsys_sync), + STATE(subsys_dump), u->ct, buf, sizeof(buf)); diff --git a/src/netlink.c b/src/netlink.c index 0bde632..94200b9 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -207,66 +207,6 @@ int nl_init_dump_handler(void) return 0; } -static int nl_overrun_handler(struct nlmsghdr *nlh, - struct nfattr *nfa[], - void *data) -{ - char buf[1024]; - struct nf_conntrack *ct = (struct nf_conntrack *) buf; - int type; - - memset(buf, 0, sizeof(buf)); - - if ((type = nfct_parse_conntrack(NFCT_T_ALL, nlh, ct)) == NFCT_T_ERROR) - return NFCT_CB_CONTINUE; - - /* - * Ignore this conntrack: it talks about a - * connection that is not interesting for us. - */ - if (ignore_conntrack(ct)) - return NFCT_CB_CONTINUE; - - switch(type) { - case NFCT_T_UPDATE: - if (STATE(mode)->overrun) - STATE(mode)->overrun(ct, nlh); - break; - default: - dlog(STATE(log), "received unknown msg from ctnetlink"); - break; - } - return NFCT_CB_CONTINUE; -} - -int nl_init_overrun_handler(void) -{ - struct nfnl_callback cb_sync = { - .call = nl_overrun_handler, - .attr_count = CTA_MAX - }; - - /* open sync netlink socket */ - STATE(sync) = nfnl_open(); - if (!STATE(sync)) - return -1; - - /* open synchronizer subsystem */ - STATE(subsys_sync) = nfnl_subsys_open(STATE(sync), - NFNL_SUBSYS_CTNETLINK, - IPCTNL_MSG_MAX, - 0); - if (STATE(subsys_sync) == NULL) - return -1; - - /* register callback for dumped entries */ - nfnl_callback_register(STATE(subsys_sync), - IPCTNL_MSG_CT_NEW, - &cb_sync); - - return 0; -} - static int warned = 0; void nl_resize_socket_buffer(struct nfnl_handle *h) @@ -278,7 +218,14 @@ void nl_resize_socket_buffer(struct nfnl_handle *h) return; if (s > CONFIG(netlink_buffer_size_max_grown)) { - dlog(STATE(log), "maximum netlink socket buffer size reached"); + dlog(STATE(log), "WARNING: maximum netlink socket buffer " + "size has been reached. We are likely to " + "be losing events, this may lead to " + "unsynchronized replicas. Please, consider " + "increasing netlink socket buffer size via " + "SocketBufferSize and " + "SocketBufferSizeMaxGrown clauses in " + "conntrackd.conf"); s = CONFIG(netlink_buffer_size_max_grown); warned = 1; } @@ -313,13 +260,13 @@ int nl_flush_master_conntrack_table(void) struct nfnlhdr req; memset(&req, 0, sizeof(req)); - nfct_build_query(STATE(subsys_sync), + nfct_build_query(STATE(subsys_dump), NFCT_Q_FLUSH, &CONFIG(family), &req, sizeof(req)); - if (nfnl_query(STATE(sync), &req.nlh) == -1) + if (nfnl_query(STATE(dump), &req.nlh) == -1) return -1; return 0; diff --git a/src/run.c b/src/run.c index 67437d8..b7dc543 100644 --- a/src/run.c +++ b/src/run.c @@ -32,10 +32,8 @@ void killer(int foo) nfnl_subsys_close(STATE(subsys_event)); nfnl_subsys_close(STATE(subsys_dump)); - nfnl_subsys_close(STATE(subsys_sync)); nfnl_close(STATE(event)); nfnl_close(STATE(dump)); - nfnl_close(STATE(sync)); ignore_pool_destroy(STATE(ignore_pool)); local_server_destroy(STATE(local)); @@ -120,12 +118,6 @@ int init(int mode) return -1; } - if (nl_init_overrun_handler() == -1) { - dlog(STATE(log), "[FAIL] can't open netlink handler! " - "no ctnetlink kernel support?"); - return -1; - } - /* Signals handling */ sigemptyset(&STATE(block)); sigaddset(&STATE(block), SIGTERM); @@ -196,8 +188,7 @@ static void __run(void) * size and resync with master conntrack table. */ nl_resize_socket_buffer(STATE(event)); - nl_dump_conntrack_table(STATE(sync), - STATE(subsys_sync)); + STATE(mode)->overrun(); break; case ENOENT: /* diff --git a/src/stats-mode.c b/src/stats-mode.c index 9647bbf..581c07d 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -1,5 +1,5 @@ /* - * (C) 2006 by Pablo Neira Ayuso + * (C) 2006-2007 by Pablo Neira Ayuso * * 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 @@ -65,7 +65,7 @@ static int local_handler_stats(int fd, int type, void *data) cache_dump(STATE_STATS(cache), fd, NFCT_O_PLAIN); break; case DUMP_INT_XML: - cache_dump(STATE_SYNC(internal), fd, NFCT_O_XML); + cache_dump(STATE_STATS(cache), fd, NFCT_O_XML); break; case FLUSH_CACHE: dlog(STATE(log), "[REQ] flushing caches"); @@ -92,6 +92,48 @@ static void dump_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) debug_ct(ct, "resync entry"); } +static int overrun_cb(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data) +{ + /* This is required by kernels < 2.6.20 */ + nfct_attr_unset(ct, ATTR_TIMEOUT); + nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES); + nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS); + nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES); + nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); + nfct_attr_unset(ct, ATTR_USE); + + if (!cache_test(STATE_STATS(cache), ct)) + if (!cache_update_force(STATE_STATS(cache), ct)) + debug_ct(ct, "overrun stats resync"); + + return NFCT_CB_CONTINUE; +} + +static void overrun_stats() +{ + int ret; + struct nfct_handle *h; + int family = CONFIG(family); + + h = nfct_open(CONNTRACK, 0); + if (!h) { + dlog(STATE(log), "can't open overrun handler"); + return; + } + + nfct_callback_register(h, NFCT_T_ALL, overrun_cb, NULL); + + cache_flush(STATE_STATS(cache)); + + ret = nfct_query(h, NFCT_Q_DUMP, &family); + if (ret == -1) + dlog(STATE(log), "overrun query error %s", strerror(errno)); + + nfct_close(h); +} + static void event_new_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) { debug_ct(ct, "debug event"); @@ -144,7 +186,7 @@ struct ct_mode stats_mode = { .local = local_handler_stats, .kill = kill_stats, .dump = dump_stats, - .overrun = dump_stats, + .overrun = overrun_stats, .event_new = event_new_stats, .event_upd = event_update_stats, .event_dst = event_destroy_stats diff --git a/src/sync-mode.c b/src/sync-mode.c index 0a195d7..65a3c5b 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -1,5 +1,5 @@ /* - * (C) 2006 by Pablo Neira Ayuso + * (C) 2006-2007 by Pablo Neira Ayuso * * 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 @@ -293,7 +293,9 @@ static void mcast_send_sync(struct nlmsghdr *nlh, STATE_SYNC(mcast_sync)->post_send(type, net, u); } -static void overrun_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) +static int overrun_cb(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data) { struct us_conntrack *u; @@ -307,10 +309,87 @@ static void overrun_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) if (!cache_test(STATE_SYNC(internal), ct)) { if ((u = cache_update_force(STATE_SYNC(internal), ct))) { - debug_ct(ct, "overrun resync"); + int ret; + char buf[4096]; + struct nlnetwork *net = (struct nlnetwork *) buf; + unsigned int size = sizeof(struct nlnetwork); + struct nlmsghdr *nlh = (struct nlmsghdr *) (buf + size); + + debug_ct(u->ct, "overrun resync"); + + ret = build_network_msg(NFCT_Q_UPDATE, + STATE(subsys_dump), + u->ct, + buf, + sizeof(buf)); + + if (ret == -1) { + dlog(STATE(log), "can't build overrun"); + return NFCT_CB_CONTINUE; + } + mcast_send_sync(nlh, u, ct, NFCT_T_UPDATE); } } + + return NFCT_CB_CONTINUE; +} + +static int overrun_purge_step(void *data1, void *data2) +{ + int ret; + struct nfct_handle *h = data1; + struct us_conntrack *u = data2; + + ret = nfct_query(h, NFCT_Q_GET, u->ct); + if (ret == -1 && errno == ENOENT) { + char buf[4096]; + struct nlnetwork *net = (struct nlnetwork *) buf; + unsigned int size = sizeof(struct nlnetwork); + struct nlmsghdr *nlh = (struct nlmsghdr *) (buf + size); + + debug_ct(u->ct, "overrun purge resync"); + + ret = build_network_msg(NFCT_Q_DESTROY, + STATE(subsys_dump), + u->ct, + buf, + sizeof(buf)); + + if (ret == -1) + dlog(STATE(log), "failed to build network message"); + + mcast_send_sync(nlh, NULL, u->ct, NFCT_T_DESTROY); + __cache_del(STATE_SYNC(internal), u->ct); + } + + return 0; +} + +/* it's likely that we're losing events, just try to do our best here */ +static void overrun_sync() +{ + int ret; + struct nfct_handle *h; + int family = CONFIG(family); + + h = nfct_open(CONNTRACK, 0); + if (!h) { + dlog(STATE(log), "can't open overrun handler"); + return; + } + + nfct_callback_register(h, NFCT_T_ALL, overrun_cb, NULL); + + ret = nfct_query(h, NFCT_Q_DUMP, &family); + if (ret == -1) + dlog(STATE(log), "overrun query error %s", strerror(errno)); + + nfct_callback_unregister(h); + + cache_iterate(STATE_SYNC(internal), h, overrun_purge_step); + + nfct_close(h); } static void event_new_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) -- cgit v1.2.3 From 1af6ff8f04bf4db0a9d9207797bca8eaf660cbe2 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Mon, 21 May 2007 15:18:58 +0000 Subject: add missing ignore_conntrack in the overrun handler --- src/netlink.c | 2 +- src/stats-mode.c | 3 +++ src/sync-mode.c | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src/stats-mode.c') diff --git a/src/netlink.c b/src/netlink.c index 94200b9..b1f9fd7 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -25,7 +25,7 @@ #include #include "network.h" -static int ignore_conntrack(struct nf_conntrack *ct) +int ignore_conntrack(struct nf_conntrack *ct) { /* ignore a certain protocol */ if (CONFIG(ignore_protocol)[nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)]) diff --git a/src/stats-mode.c b/src/stats-mode.c index 581c07d..22474e2 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -96,6 +96,9 @@ static int overrun_cb(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data) { + if (ignore_conntrack(ct)) + return NFCT_CB_CONTINUE; + /* This is required by kernels < 2.6.20 */ nfct_attr_unset(ct, ATTR_TIMEOUT); nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES); diff --git a/src/sync-mode.c b/src/sync-mode.c index 65a3c5b..d7bee9d 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -299,6 +299,9 @@ static int overrun_cb(enum nf_conntrack_msg_type type, { struct us_conntrack *u; + if (ignore_conntrack(ct)) + return NFCT_CB_CONTINUE; + /* This is required by kernels < 2.6.20 */ nfct_attr_unset(ct, ATTR_TIMEOUT); nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES); -- cgit v1.2.3 From cea33148e4ccf108f587e5796c026600aba35ab1 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Mon, 4 Jun 2007 15:19:42 +0000 Subject: o remove useless backlog parameter in multicast sockets o remove reminiscents of delay destroy message and relax transitions o remove confusing StripNAT parameter: NAT support enabled by default o relax event tracking: *_update callbacks use cache_update_force o use wraparound-aware functions after/before/between o lots of cleanups --- ChangeLog | 6 ++ configure.in | 2 +- examples/sync/nack/node1/conntrackd.conf | 6 -- examples/sync/nack/node2/conntrackd.conf | 6 -- examples/sync/persistent/node1/conntrackd.conf | 6 -- examples/sync/persistent/node2/conntrackd.conf | 6 -- include/conntrackd.h | 17 +--- include/mcast.h | 1 - include/network.h | 19 +++++ include/sync.h | 8 +- src/cache_iterators.c | 3 +- src/netlink.c | 6 +- src/network.c | 27 ++----- src/read_config_yy.y | 12 ++- src/stats-mode.c | 20 +---- src/sync-mode.c | 104 +++++++++++-------------- src/sync-nack.c | 27 ++++--- src/sync-notrack.c | 44 +++-------- 18 files changed, 122 insertions(+), 198 deletions(-) (limited to 'src/stats-mode.c') diff --git a/ChangeLog b/ChangeLog index 396d3a4..05348e1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,12 @@ version 0.9.4 (yet unreleased) o simplify checksum code: use UDP/multicast checksum facilities o fix silly bug in build_network_message: out of bound memset o fix error message in configure.in (Eric Leblond) +o remove useless backlog parameter in multicast sockets +o remove reminiscents of delay destroy message and relax transitions +o remove confusing StripNAT parameter: NAT support enabled by default +o relax event tracking: *_update callbacks use cache_update_force +o use wraparound-aware functions after/before/between +o lots of cleanups = conntrack = o fix segfault with conntrack --output (Krzysztof Oledzky) diff --git a/configure.in b/configure.in index 7a1445d..37e7a9c 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -AC_INIT(conntrack-tools, 0.9.3, pablo@netfilter.org) +AC_INIT(conntrack-tools, 0.9.4, pablo@netfilter.org) AC_CANONICAL_SYSTEM diff --git a/examples/sync/nack/node1/conntrackd.conf b/examples/sync/nack/node1/conntrackd.conf index f24fa7e..edec9cf 100644 --- a/examples/sync/nack/node1/conntrackd.conf +++ b/examples/sync/nack/node1/conntrackd.conf @@ -33,7 +33,6 @@ Sync { IPv4_address 225.0.0.50 IPv4_interface 192.168.100.100 # IP of dedicated link Group 3780 - Backlog 20 } # Enable/Disable message checksumming @@ -118,8 +117,3 @@ IgnoreProtocol { VRRP # numeric numbers also valid } - -# -# Strip NAT traffic -# -StripNAT diff --git a/examples/sync/nack/node2/conntrackd.conf b/examples/sync/nack/node2/conntrackd.conf index 4f15773..de5f4d2 100644 --- a/examples/sync/nack/node2/conntrackd.conf +++ b/examples/sync/nack/node2/conntrackd.conf @@ -32,7 +32,6 @@ Sync { IPv4_address 225.0.0.50 IPv4_interface 192.168.100.200 # IP of dedicated link Group 3780 - Backlog 20 } # Enable/Disable message checksumming @@ -117,8 +116,3 @@ IgnoreProtocol { VRRP # numeric numbers also valid } - -# -# Strip NAT traffic -# -StripNAT diff --git a/examples/sync/persistent/node1/conntrackd.conf b/examples/sync/persistent/node1/conntrackd.conf index 90afeb7..60f264b 100644 --- a/examples/sync/persistent/node1/conntrackd.conf +++ b/examples/sync/persistent/node1/conntrackd.conf @@ -38,7 +38,6 @@ Sync { IPv4_address 225.0.0.50 IPv4_interface 192.168.100.100 # IP of dedicated link Group 3780 - Backlog 20 } # Enable/Disable message checksumming @@ -123,8 +122,3 @@ IgnoreProtocol { VRRP # numeric numbers also valid } - -# -# Strip NAT traffic -# -StripNAT diff --git a/examples/sync/persistent/node2/conntrackd.conf b/examples/sync/persistent/node2/conntrackd.conf index aee4a29..6a1806b 100644 --- a/examples/sync/persistent/node2/conntrackd.conf +++ b/examples/sync/persistent/node2/conntrackd.conf @@ -38,7 +38,6 @@ Sync { IPv4_address 225.0.0.50 IPv4_interface 192.168.100.200 # IP of dedicated link Group 3780 - Backlog 20 } # Enable/Disable message checksumming @@ -123,8 +122,3 @@ IgnoreProtocol { VRRP # numeric numbers also valid } - -# -# Strip NAT traffic -# -StripNAT diff --git a/include/conntrackd.h b/include/conntrackd.h index 76b9747..a620400 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -30,22 +30,13 @@ #define DEFAULT_LOCKFILE "/var/lock/conntrackd.lock" enum { - STRIP_NAT_BIT = 0, - STRIP_NAT = (1 << STRIP_NAT_BIT), - - DELAY_DESTROY_MSG_BIT = 1, - DELAY_DESTROY_MSG = (1 << DELAY_DESTROY_MSG_BIT), - - RELAX_TRANSITIONS_BIT = 2, - RELAX_TRANSITIONS = (1 << RELAX_TRANSITIONS_BIT), - - SYNC_MODE_PERSISTENT_BIT = 3, + SYNC_MODE_PERSISTENT_BIT = 0, SYNC_MODE_PERSISTENT = (1 << SYNC_MODE_PERSISTENT_BIT), - SYNC_MODE_NACK_BIT = 4, + SYNC_MODE_NACK_BIT = 1, SYNC_MODE_NACK = (1 << SYNC_MODE_NACK_BIT), - DONT_CHECKSUM_BIT = 5, + DONT_CHECKSUM_BIT = 2, DONT_CHECKSUM = (1 << DONT_CHECKSUM_BIT), }; @@ -122,7 +113,7 @@ struct ct_sync_state { struct mcast_sock *mcast_server; /* multicast socket: incoming */ struct mcast_sock *mcast_client; /* multicast socket: outgoing */ - struct sync_mode *mcast_sync; + struct sync_mode *sync; /* sync mode */ struct buffer *buffer; u_int32_t last_seq_sent; /* last sequence number sent */ diff --git a/include/mcast.h b/include/mcast.h index be1d0cd..66676dc 100644 --- a/include/mcast.h +++ b/include/mcast.h @@ -5,7 +5,6 @@ struct mcast_conf { int ipproto; - int backlog; int reuseaddr; int checksum; unsigned short port; diff --git a/include/network.h b/include/network.h index 176274e..5ba808a 100644 --- a/include/network.h +++ b/include/network.h @@ -30,4 +30,23 @@ enum { NET_ACK = (1 << NET_ACK_BIT), }; +/* extracted from net/tcp.h */ + +/* + * The next routines deal with comparing 32 bit unsigned ints + * and worry about wraparound (automatic with unsigned arithmetic). + */ + +static inline int before(__u32 seq1, __u32 seq2) +{ + return (__s32)(seq1-seq2) < 0; +} +#define after(seq2, seq1) before(seq1, seq2) + +/* is s2<=s1<=s3 ? */ +static inline int between(__u32 seq1, __u32 seq2, __u32 seq3) +{ + return seq3 - seq2 >= seq1 - seq2; +} + #endif diff --git a/include/sync.h b/include/sync.h index d8f1bca..72f6313 100644 --- a/include/sync.h +++ b/include/sync.h @@ -13,10 +13,10 @@ struct sync_mode { int (*init)(void); void (*kill)(void); int (*local)(int fd, int type, void *data); - int (*pre_recv)(const struct nlnetwork *net); - void (*post_send)(int type, - const struct nlnetwork *net, - struct us_conntrack *u); + int (*recv)(const struct nlnetwork *net); /* recv callback */ + void (*send)(int type, /* send callback */ + const struct nlnetwork *net, + struct us_conntrack *u); }; extern struct sync_mode notrack; diff --git a/src/cache_iterators.c b/src/cache_iterators.c index 1c03fef..fd6694a 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -219,7 +219,8 @@ static int do_bulk(void *data1, void *data2) debug_ct(u->ct, "failed to build"); mcast_send_netmsg(STATE_SYNC(mcast_client), net); - STATE_SYNC(mcast_sync)->post_send(NFCT_T_UPDATE, net, u); + if (STATE_SYNC(sync)->send) + STATE_SYNC(sync)->send(NFCT_T_UPDATE, net, u); /* keep iterating even if we have found errors */ return 0; diff --git a/src/netlink.c b/src/netlink.c index b1f9fd7..5f7cbeb 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -32,15 +32,13 @@ int ignore_conntrack(struct nf_conntrack *ct) return 1; /* Accept DNAT'ed traffic: not really coming to the local machine */ - if ((CONFIG(flags) & STRIP_NAT) && - nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT)) { + if (nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT)) { debug_ct(ct, "DNAT"); return 0; } /* Accept SNAT'ed traffic: not really coming to the local machine */ - if ((CONFIG(flags) & STRIP_NAT) && - nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT)) { + if (nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT)) { debug_ct(ct, "SNAT"); return 0; } diff --git a/src/network.c b/src/network.c index abd30fe..a7ce740 100644 --- a/src/network.c +++ b/src/network.c @@ -205,33 +205,16 @@ int mcast_track_seq(u_int32_t seq, u_int32_t *exp_seq) goto out; /* out of sequence: some messages got lost */ - if (seq > STATE_SYNC(last_seq_recv)+1) { + if (after(seq, STATE_SYNC(last_seq_recv)+1)) { STATE_SYNC(packets_lost) += seq-STATE_SYNC(last_seq_recv)+1; ret = 0; goto out; } - /* out of sequence: replayed or sequence wrapped around issues */ - if (seq < STATE_SYNC(last_seq_recv)+1) { - /* - * Check if the sequence has wrapped around. - * Perhaps it can be a replayed packet. - */ - if (STATE_SYNC(last_seq_recv)+1-seq > ~0U/2) { - /* - * Indeed, it is a wrapped around - */ - STATE_SYNC(packets_lost) += - ~0U-STATE_SYNC(last_seq_recv)+1+seq; - } else { - /* - * It is a delayed packet - */ - dlog(STATE(log), "delayed packet? exp=%u rcv=%u", - STATE_SYNC(last_seq_recv)+1, seq); - } - ret = 0; - } + /* out of sequence: replayed/delayed packet? */ + if (before(seq, STATE_SYNC(last_seq_recv)+1)) + dlog(STATE(log), "delayed packet? exp=%u rcv=%u", + STATE_SYNC(last_seq_recv)+1, seq); out: *exp_seq = STATE_SYNC(last_seq_recv)+1; diff --git a/src/read_config_yy.y b/src/read_config_yy.y index 988b540..57250b4 100644 --- a/src/read_config_yy.y +++ b/src/read_config_yy.y @@ -84,7 +84,8 @@ lock : T_LOCK T_PATH_VAL strip_nat: T_STRIP_NAT { - conf.flags |= STRIP_NAT; + fprintf(stderr, "Notice: StripNAT clause is obsolete. " + "Please, remove it from conntrackd.conf\n"); }; refreshtime : T_REFRESH T_NUMBER @@ -228,7 +229,8 @@ multicast_option : T_IPV6_IFACE T_IP multicast_option : T_BACKLOG T_NUMBER { - conf.mcast.backlog = $2; + fprintf(stderr, "Notice: Backlog option inside Multicast clause is " + "obsolete. Please, remove it from conntrackd.conf.\n"); }; multicast_option : T_GROUP T_NUMBER @@ -354,12 +356,14 @@ window_size: T_WINDOWSIZE T_NUMBER relax_transitions: T_RELAX_TRANSITIONS { - conf.flags |= RELAX_TRANSITIONS; + fprintf(stderr, "Notice: RelaxTransitions clause is obsolete. " + "Please, remove it from conntrackd.conf\n"); }; delay_destroy_msgs: T_DELAY { - conf.flags |= DELAY_DESTROY_MSG; + fprintf(stderr, "Notice: DelayDestroyMessages clause is obsolete. " + "Please, remove it from conntrackd.conf\n"); }; listen_to: T_LISTEN_TO T_IP diff --git a/src/stats-mode.c b/src/stats-mode.c index 22474e2..f65fbdb 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -139,7 +139,6 @@ static void overrun_stats() static void event_new_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) { - debug_ct(ct, "debug event"); if (cache_add(STATE_STATS(cache), ct)) { debug_ct(ct, "cache new"); } else { @@ -151,22 +150,9 @@ static void event_new_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) static void event_update_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) { - debug_ct(ct, "update"); - - if (!cache_update(STATE_STATS(cache), ct)) { - /* - * Perhaps we are losing events. If we are working - * in relax mode then add a new entry to the cache. - * - * FIXME: relax transitions not implemented yet - */ - if ((CONFIG(flags) & RELAX_TRANSITIONS) - && cache_add(STATE_STATS(cache), ct)) { - debug_ct(ct, "forcing cache update"); - } else { - debug_ct(ct, "can't update"); - return; - } + if (!cache_update_force(STATE_STATS(cache), ct)) { + debug_ct(ct, "can't update"); + return; } debug_ct(ct, "update"); } diff --git a/src/sync-mode.c b/src/sync-mode.c index d7bee9d..cb95392 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -32,26 +32,25 @@ static void mcast_handler() { int ret; - char buf[4096], tmp[256]; - struct mcast_sock *m = STATE_SYNC(mcast_server); - unsigned int type; - struct nlnetwork *net = (struct nlnetwork *) buf; - unsigned int size = sizeof(struct nlnetwork); - struct nlmsghdr *nlh = (struct nlmsghdr *) (buf + size); - struct nf_conntrack *ct = (struct nf_conntrack *) tmp; + unsigned int type, size = sizeof(struct nlnetwork); + char __net[4096]; + struct nlnetwork *net = (struct nlnetwork *) __net; + struct nlmsghdr *nlh = (struct nlmsghdr *) (__net + size); + char __ct[nfct_maxsize()]; + struct nf_conntrack *ct = (struct nf_conntrack *) __ct; struct us_conntrack *u = NULL; - memset(tmp, 0, sizeof(tmp)); - - ret = mcast_recv_netmsg(m, buf, sizeof(buf)); + ret = mcast_recv_netmsg(STATE_SYNC(mcast_server), net, sizeof(__net)); if (ret <= 0) { STATE(malformed)++; return; } - if (STATE_SYNC(mcast_sync)->pre_recv(net)) + if (STATE_SYNC(sync)->recv(net)) return; + memset(ct, 0, sizeof(__ct)); + if ((type = parse_network_msg(ct, nlh)) == NFCT_T_ERROR) { STATE(malformed)++; return; @@ -111,19 +110,19 @@ static int init_sync(void) memset(state.sync, 0, sizeof(struct ct_sync_state)); if (CONFIG(flags) & SYNC_MODE_NACK) - STATE_SYNC(mcast_sync) = &nack; + STATE_SYNC(sync) = &nack; else /* default to persistent mode */ - STATE_SYNC(mcast_sync) = ¬rack; + STATE_SYNC(sync) = ¬rack; - if (STATE_SYNC(mcast_sync)->init) - STATE_SYNC(mcast_sync)->init(); + if (STATE_SYNC(sync)->init) + STATE_SYNC(sync)->init(); STATE_SYNC(internal) = cache_create("internal", - STATE_SYNC(mcast_sync)->internal_cache_flags, + STATE_SYNC(sync)->internal_cache_flags, CONFIG(family), - STATE_SYNC(mcast_sync)->internal_cache_extra); + STATE_SYNC(sync)->internal_cache_extra); if (!STATE_SYNC(internal)) { dlog(STATE(log), "[FAIL] can't allocate memory for " @@ -133,7 +132,7 @@ static int init_sync(void) STATE_SYNC(external) = cache_create("external", - STATE_SYNC(mcast_sync)->external_cache_flags, + STATE_SYNC(sync)->external_cache_flags, CONFIG(family), NULL); @@ -192,8 +191,8 @@ static void kill_sync() destroy_alarm_thread(); - if (STATE_SYNC(mcast_sync)->kill) - STATE_SYNC(mcast_sync)->kill(); + if (STATE_SYNC(sync)->kill) + STATE_SYNC(sync)->kill(); } static dump_stats_sync(int fd) @@ -253,8 +252,8 @@ static int local_handler_sync(int fd, int type, void *data) cache_bulk(STATE_SYNC(internal)); break; default: - if (STATE_SYNC(mcast_sync)->local) - ret = STATE_SYNC(mcast_sync)->local(fd, type, data); + if (STATE_SYNC(sync)->local) + ret = STATE_SYNC(sync)->local(fd, type, data); break; } @@ -280,17 +279,18 @@ static void mcast_send_sync(struct nlmsghdr *nlh, struct nf_conntrack *ct, int type) { - char buf[4096]; - struct nlnetwork *net = (struct nlnetwork *) buf; + char __net[4096]; + struct nlnetwork *net = (struct nlnetwork *) __net; - memset(buf, 0, sizeof(buf)); + memset(__net, 0, sizeof(__net)); if (!state_helper_verdict(type, ct)) return; - memcpy(buf + sizeof(struct nlnetwork), nlh, nlh->nlmsg_len); - mcast_send_netmsg(STATE_SYNC(mcast_client), net); - STATE_SYNC(mcast_sync)->post_send(type, net, u); + memcpy(__net + sizeof(struct nlnetwork), nlh, nlh->nlmsg_len); + mcast_send_netmsg(STATE_SYNC(mcast_client), net); + if (STATE_SYNC(sync)->send) + STATE_SYNC(sync)->send(type, net, u); } static int overrun_cb(enum nf_conntrack_msg_type type, @@ -313,18 +313,16 @@ static int overrun_cb(enum nf_conntrack_msg_type type, if (!cache_test(STATE_SYNC(internal), ct)) { if ((u = cache_update_force(STATE_SYNC(internal), ct))) { int ret; - char buf[4096]; - struct nlnetwork *net = (struct nlnetwork *) buf; - unsigned int size = sizeof(struct nlnetwork); - struct nlmsghdr *nlh = (struct nlmsghdr *) (buf + size); + char __nlh[4096]; + struct nlmsghdr *nlh = (struct nlmsghdr *) __nlh; debug_ct(u->ct, "overrun resync"); - ret = build_network_msg(NFCT_Q_UPDATE, - STATE(subsys_dump), - u->ct, - buf, - sizeof(buf)); + ret = nfct_build_query(STATE(subsys_dump), + NFCT_Q_UPDATE, + u->ct, + __nlh, + sizeof(__nlh)); if (ret == -1) { dlog(STATE(log), "can't build overrun"); @@ -346,18 +344,16 @@ static int overrun_purge_step(void *data1, void *data2) ret = nfct_query(h, NFCT_Q_GET, u->ct); if (ret == -1 && errno == ENOENT) { - char buf[4096]; - struct nlnetwork *net = (struct nlnetwork *) buf; - unsigned int size = sizeof(struct nlnetwork); - struct nlmsghdr *nlh = (struct nlmsghdr *) (buf + size); + char __nlh[4096]; + struct nlmsghdr *nlh = (struct nlmsghdr *) (__nlh); debug_ct(u->ct, "overrun purge resync"); - - ret = build_network_msg(NFCT_Q_DESTROY, - STATE(subsys_dump), - u->ct, - buf, - sizeof(buf)); + + ret = nfct_build_query(STATE(subsys_dump), + NFCT_Q_DESTROY, + u->ct, + __nlh, + sizeof(__nlh)); if (ret == -1) dlog(STATE(log), "failed to build network message"); @@ -411,18 +407,6 @@ retry: debug_ct(u->ct, "internal new"); } else { if (errno == EEXIST) { - char buf[4096]; - unsigned int size = sizeof(struct nlnetwork); - struct nlmsghdr *nlh = (struct nlmsghdr *) (buf + size); - - int ret = build_network_msg(NFCT_Q_DESTROY, - STATE(subsys_event), - ct, - buf, - sizeof(buf)); - if (ret == -1) - return; - cache_del(STATE_SYNC(internal), ct); mcast_send_sync(nlh, NULL, ct, NFCT_T_DESTROY); goto retry; @@ -440,7 +424,7 @@ static void event_update_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) nfct_attr_unset(ct, ATTR_TIMEOUT); - if ((u = cache_update(STATE_SYNC(internal), ct)) == NULL) { + if ((u = cache_update_force(STATE_SYNC(internal), ct)) == NULL) { debug_ct(ct, "can't update"); return; } diff --git a/src/sync-nack.c b/src/sync-nack.c index 73f6dc2..e435b09 100644 --- a/src/sync-nack.c +++ b/src/sync-nack.c @@ -136,7 +136,7 @@ static int buffer_compare(void *data1, void *data2) unsigned old_seq = ntohl(net->seq); - if (ntohl(net->seq) >= nack->from && ntohl(net->seq) <= nack->to) { + if (between(ntohl(net->seq), nack->from, nack->to)) { if (mcast_resend_netmsg(STATE_SYNC(mcast_client), net)) dp("resend destroy (old seq=%u) (seq=%u)\n", old_seq, ntohl(net->seq)); @@ -149,7 +149,7 @@ static int buffer_remove(void *data1, void *data2) struct nlnetwork *net = data1; struct nlnetwork_ack *h = data2; - if (ntohl(net->seq) >= h->from && ntohl(net->seq) <= h->to) { + if (between(ntohl(net->seq), h->from, h->to)) { dp("remove from buffer (seq=%u)\n", ntohl(net->seq)); __buffer_del(STATE_SYNC(buffer), data1); } @@ -169,7 +169,7 @@ static void queue_resend(struct cache *c, unsigned int from, unsigned int to) u = cache_get_conntrack(STATE_SYNC(internal), cn); - if (cn->seq >= from && cn->seq <= to) { + if (between(cn->seq, from, to)) { debug_ct(u->ct, "resend nack"); dp("resending nack'ed (oldseq=%u) ", cn->seq); @@ -186,10 +186,9 @@ static void queue_resend(struct cache *c, unsigned int from, unsigned int to) break; } - mcast_send_netmsg(STATE_SYNC(mcast_client), buf); - STATE_SYNC(mcast_sync)->post_send(NFCT_T_UPDATE, - net, - u); + mcast_send_netmsg(STATE_SYNC(mcast_client), buf); + if (STATE_SYNC(sync)->send) + STATE_SYNC(sync)->send(NFCT_T_UPDATE, net, u); dp("(newseq=%u)\n", *seq); } } @@ -208,7 +207,7 @@ static void queue_empty(struct cache *c, unsigned int from, unsigned int to) struct cache_nack *cn = (struct cache_nack *) n; u = cache_get_conntrack(STATE_SYNC(internal), cn); - if (cn->seq >= from && cn->seq <= to) { + if (between(cn->seq, from, to)) { dp("remove %u\n", cn->seq); debug_ct(u->ct, "ack received: empty queue"); dp("queue: deleting from queue (seq=%u)\n", cn->seq); @@ -219,7 +218,7 @@ static void queue_empty(struct cache *c, unsigned int from, unsigned int to) unlock(); } -static int nack_pre_recv(const struct nlnetwork *net) +static int nack_recv(const struct nlnetwork *net) { static unsigned int window = 0; unsigned int exp_seq; @@ -262,9 +261,9 @@ static int nack_pre_recv(const struct nlnetwork *net) return 0; } -static void nack_post_send(int type, - const struct nlnetwork *net, - struct us_conntrack *u) +static void nack_send(int type, + const struct nlnetwork *net, + struct us_conntrack *u) { unsigned int size = sizeof(struct nlnetwork); struct nlmsghdr *nlh = (struct nlmsghdr *) ((void *) net + size); @@ -301,6 +300,6 @@ struct sync_mode nack = { .init = nack_init, .kill = nack_kill, .local = nack_local, - .pre_recv = nack_pre_recv, - .post_send = nack_post_send, + .recv = nack_recv, + .send = nack_send, }; diff --git a/src/sync-notrack.c b/src/sync-notrack.c index cc56436..4a470f9 100644 --- a/src/sync-notrack.c +++ b/src/sync-notrack.c @@ -25,33 +25,18 @@ static void refresher(struct alarm_list *a, void *data) { struct us_conntrack *u = data; - char buf[8192]; + char __net[4096]; int size; - if (nfct_get_attr_u32(u->ct, ATTR_STATUS) & IPS_DYING) { - - debug_ct(u->ct, "persistence destroy"); + debug_ct(u->ct, "persistence update"); - size = build_network_msg(NFCT_Q_DESTROY, - STATE(subsys_event), - u->ct, - buf, - sizeof(buf)); - - __cache_del(u->cache, u->ct); - mcast_send_netmsg(STATE_SYNC(mcast_client), buf); - } else { - - debug_ct(u->ct, "persistence update"); - - a->expires = random() % CONFIG(refresh) + 1; - size = build_network_msg(NFCT_Q_UPDATE, - STATE(subsys_event), - u->ct, - buf, - sizeof(buf)); - mcast_send_netmsg(STATE_SYNC(mcast_client), buf); - } + a->expires = random() % CONFIG(refresh) + 1; + size = build_network_msg(NFCT_Q_UPDATE, + STATE(subsys_event), + u->ct, + __net, + sizeof(__net)); + mcast_send_netmsg(STATE_SYNC(mcast_client), __net); } static void cache_notrack_add(struct us_conntrack *u, void *data) @@ -84,7 +69,7 @@ static struct cache_extra cache_notrack_extra = { .destroy = cache_notrack_destroy }; -static int notrack_pre_recv(const struct nlnetwork *net) +static int notrack_recv(const struct nlnetwork *net) { unsigned int exp_seq; @@ -114,16 +99,9 @@ static int notrack_pre_recv(const struct nlnetwork *net) return 0; } -static void notrack_post_send(int type, - const struct nlnetwork *n, - struct us_conntrack *u) -{ -} - struct sync_mode notrack = { .internal_cache_flags = LIFETIME, .external_cache_flags = TIMER | LIFETIME, .internal_cache_extra = &cache_notrack_extra, - .pre_recv = notrack_pre_recv, - .post_send = notrack_post_send, + .recv = notrack_recv, }; -- cgit v1.2.3 From 3f3a6701978df8ca16ebb5988eb7a46771deb964 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Tue, 19 Jun 2007 17:00:44 +0000 Subject: - more cleanups and code refactorization - remove several debug calls - create a child to dispatch dump requests: this will help to simplify the current locking schema. Later. --- ChangeLog | 2 ++ include/network.h | 22 +++++++------ include/sync.h | 6 ++-- src/cache.c | 1 - src/cache_iterators.c | 22 ++----------- src/ignore_pool.c | 1 - src/local.c | 19 +++-------- src/network.c | 89 ++++++++++++++++++++++++++++++++++++--------------- src/run.c | 13 ++++++-- src/stats-mode.c | 8 +++-- src/sync-mode.c | 69 ++++++++++++++++----------------------- src/sync-nack.c | 63 +++++++++++++----------------------- src/sync-notrack.c | 13 ++------ 13 files changed, 156 insertions(+), 172 deletions(-) (limited to 'src/stats-mode.c') diff --git a/ChangeLog b/ChangeLog index f1ae81f..aa93d4c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,8 @@ o relax event tracking: *_update callbacks use cache_update_force o use wraparound-aware functions after/before/between o commit phase: if conntrack exists, update it o local requests return EXIT_FAILURE if it can't connect to the daemon +o remove several debug statements +o fork when internal/external dump cache requests are received o lots of cleanups = conntrack = diff --git a/include/network.h b/include/network.h index 243815a..31903a5 100644 --- a/include/network.h +++ b/include/network.h @@ -3,32 +3,34 @@ #include -struct nlnetwork { +struct nethdr { u_int16_t flags; u_int16_t padding; u_int32_t seq; }; +#define NETHDR_SIZ sizeof(struct nethdr) -struct nlnetwork_ack { +struct nethdr_ack { u_int16_t flags; u_int16_t padding; u_int32_t seq; u_int32_t from; u_int32_t to; }; +#define NETHDR_ACK_SIZ sizeof(struct nethdr_ack) enum { - NET_HELLO_BIT = 0, - NET_HELLO = (1 << NET_HELLO_BIT), + NET_F_HELLO_BIT = 0, + NET_F_HELLO = (1 << NET_F_HELLO_BIT), - NET_RESYNC_BIT = 1, - NET_RESYNC = (1 << NET_RESYNC_BIT), + NET_F_RESYNC_BIT = 1, + NET_F_RESYNC = (1 << NET_F_RESYNC_BIT), - NET_NACK_BIT = 2, - NET_NACK = (1 << NET_NACK_BIT), + NET_F_NACK_BIT = 2, + NET_F_NACK = (1 << NET_F_NACK_BIT), - NET_ACK_BIT = 3, - NET_ACK = (1 << NET_ACK_BIT), + NET_F_ACK_BIT = 3, + NET_F_ACK = (1 << NET_F_ACK_BIT), }; /* extracted from net/tcp.h */ diff --git a/include/sync.h b/include/sync.h index 72f6313..a737e81 100644 --- a/include/sync.h +++ b/include/sync.h @@ -1,7 +1,7 @@ #ifndef _SYNC_HOOKS_H_ #define _SYNC_HOOKS_H_ -struct nlnetwork; +struct nethdr; struct us_conntrack; struct sync_mode { @@ -13,9 +13,9 @@ struct sync_mode { int (*init)(void); void (*kill)(void); int (*local)(int fd, int type, void *data); - int (*recv)(const struct nlnetwork *net); /* recv callback */ + int (*recv)(const struct nethdr *net); /* recv callback */ void (*send)(int type, /* send callback */ - const struct nlnetwork *net, + const struct nethdr *net, struct us_conntrack *u); }; diff --git a/src/cache.c b/src/cache.c index 1b130c8..3bf331c 100644 --- a/src/cache.c +++ b/src/cache.c @@ -23,7 +23,6 @@ #include #include "us-conntrack.h" #include "cache.h" -#include "debug.h" static u_int32_t hash(const void *data, struct hashtable *table) { diff --git a/src/cache_iterators.c b/src/cache_iterators.c index 279ddab..7ae25fa 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -23,7 +23,6 @@ #include #include #include "us-conntrack.h" -#include "debug.h" struct __dump_container { int fd; @@ -120,8 +119,7 @@ static int do_commit(void *data1, void *data2) free(ct); if (ret == -1) { - /* XXX: Please cleanup this debug crap, default in logfile */ - debug("--- failed to build: %s --- \n", strerror(errno)); + dlog(STATE(log), "failed to build: %s", strerror(errno)); return 0; } @@ -135,10 +133,8 @@ static int do_commit(void *data1, void *data2) c->commit_fail++; break; } - debug("--- failed to commit: %s --- \n", strerror(errno)); } else { c->commit_ok++; - debug("----- commit -----\n"); } /* keep iterating even if we have found errors */ @@ -207,20 +203,8 @@ static int do_bulk(void *data1, void *data2) { int ret; struct us_conntrack *u = data2; - char buf[4096]; - struct nlnetwork *net = (struct nlnetwork *) buf; - - ret = build_network_msg(NFCT_Q_UPDATE, - STATE(subsys_dump), - u->ct, - buf, - sizeof(buf)); - if (ret == -1) - debug_ct(u->ct, "failed to build"); - - mcast_send_netmsg(STATE_SYNC(mcast_client), net); - if (STATE_SYNC(sync)->send) - STATE_SYNC(sync)->send(NFCT_T_UPDATE, net, u); + + mcast_build_send_update(u); /* keep iterating even if we have found errors */ return 0; diff --git a/src/ignore_pool.c b/src/ignore_pool.c index 5946617..d6f0e93 100644 --- a/src/ignore_pool.c +++ b/src/ignore_pool.c @@ -20,7 +20,6 @@ #include "hash.h" #include "conntrackd.h" #include "ignore.h" -#include "debug.h" #include #define IGNORE_POOL_SIZE 32 diff --git a/src/local.c b/src/local.c index eef70ad..be51b9e 100644 --- a/src/local.c +++ b/src/local.c @@ -1,5 +1,5 @@ /* - * (C) 2006 by Pablo Neira Ayuso + * (C) 2006-2007 by Pablo Neira Ayuso * * 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 @@ -22,7 +22,6 @@ #include #include #include -#include "debug.h" #include "local.h" @@ -32,14 +31,11 @@ int local_server_create(struct local_conf *conf) int len; struct sockaddr_un local; - if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - debug("local_server_create:socket"); + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) return -1; - } if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &conf->reuseaddr, sizeof(conf->reuseaddr)) == -1) { - debug("local_server_create:setsockopt"); close(fd); return -1; } @@ -50,14 +46,12 @@ int local_server_create(struct local_conf *conf) unlink(conf->path); if (bind(fd, (struct sockaddr *) &local, len) == -1) { - debug("local_server_create:bind"); close(fd); return -1; } if (listen(fd, conf->backlog) == -1) { close(fd); - debug("local_server_create:listen"); return -1; } @@ -76,10 +70,8 @@ int do_local_server_step(int fd, void *data, struct sockaddr_un local; size_t sin_size = sizeof(struct sockaddr_un); - if ((rfd = accept(fd, (struct sockaddr *)&local, &sin_size)) == -1) { - debug("do_local_server_step:accept"); + if ((rfd = accept(fd, (struct sockaddr *)&local, &sin_size)) == -1) return -1; - } process(rfd, data); close(rfd); @@ -102,7 +94,6 @@ int local_client_create(struct local_conf *conf) if (connect(fd, (struct sockaddr *) &local, len) == -1) { close(fd); - debug("local_client_create: connect: "); return -1; } @@ -146,10 +137,8 @@ int do_local_request(int request, return -1; ret = send(fd, &request, sizeof(int), 0); - if (ret == -1) { - debug("send:"); + if (ret == -1) return -1; - } do_local_client_step(fd, step); diff --git a/src/network.c b/src/network.c index 37f437e..159bdf3 100644 --- a/src/network.c +++ b/src/network.c @@ -23,12 +23,12 @@ static unsigned int seq_set, cur_seq; static int send_netmsg(struct mcast_sock *m, void *data, unsigned int len) { - struct nlnetwork *net = data; + struct nethdr *net = data; if (!seq_set) { seq_set = 1; cur_seq = time(NULL); - net->flags |= NET_HELLO; + net->flags |= NET_F_HELLO; } net->flags = htons(net->flags); @@ -49,9 +49,9 @@ static int send_netmsg(struct mcast_sock *m, void *data, unsigned int len) int mcast_send_netmsg(struct mcast_sock *m, void *data) { - struct nlmsghdr *nlh = data + sizeof(struct nlnetwork); - unsigned int len = nlh->nlmsg_len + sizeof(struct nlnetwork); - struct nlnetwork *net = data; + struct nlmsghdr *nlh = data + NETHDR_SIZ; + unsigned int len = nlh->nlmsg_len + NETHDR_SIZ; + struct nethdr *net = data; if (nlh_host2network(nlh) == -1) return -1; @@ -61,40 +61,77 @@ int mcast_send_netmsg(struct mcast_sock *m, void *data) int mcast_resend_netmsg(struct mcast_sock *m, void *data) { - struct nlnetwork *net = data; - struct nlmsghdr *nlh = data + sizeof(struct nlnetwork); + struct nethdr *net = data; + struct nlmsghdr *nlh = data + NETHDR_SIZ; unsigned int len; net->flags = ntohs(net->flags); - if (net->flags & NET_NACK || net->flags & NET_ACK) - len = sizeof(struct nlnetwork_ack); + if (net->flags & NET_F_NACK || net->flags & NET_F_ACK) + len = NETHDR_ACK_SIZ; else - len = sizeof(struct nlnetwork) + ntohl(nlh->nlmsg_len); + len = ntohl(nlh->nlmsg_len) + NETHDR_SIZ; return send_netmsg(m, data, len); } int mcast_send_error(struct mcast_sock *m, void *data) { - struct nlnetwork *net = data; - unsigned int len = sizeof(struct nlnetwork); + struct nethdr *net = data; + unsigned int len = NETHDR_SIZ; - if (net->flags & NET_NACK || net->flags & NET_ACK) { - struct nlnetwork_ack *nack = (struct nlnetwork_ack *) net; + if (net->flags & NET_F_NACK || net->flags & NET_F_ACK) { + struct nethdr_ack *nack = (struct nethdr_ack *) net; nack->from = htonl(nack->from); nack->to = htonl(nack->to); - len = sizeof(struct nlnetwork_ack); + len = NETHDR_ACK_SIZ; } return send_netmsg(m, data, len); } +#include "us-conntrack.h" +#include "sync.h" + +static int __build_send(struct us_conntrack *u, int type, int query) +{ + char __net[4096]; + struct nethdr *net = (struct nethdr *) __net; + + if (!state_helper_verdict(type, u->ct)) + return 0; + + int ret = build_network_msg(query, + STATE(subsys_event), + u->ct, + __net, + sizeof(__net)); + + if (ret == -1) + return -1; + + mcast_send_netmsg(STATE_SYNC(mcast_client), __net); + if (STATE_SYNC(sync)->send) + STATE_SYNC(sync)->send(type, net, u); + + return 0; +} + +int mcast_build_send_update(struct us_conntrack *u) +{ + return __build_send(u, NFCT_T_UPDATE, NFCT_Q_UPDATE); +} + +int mcast_build_send_destroy(struct us_conntrack *u) +{ + return __build_send(u, NFCT_T_DESTROY, NFCT_Q_DESTROY); +} + int mcast_recv_netmsg(struct mcast_sock *m, void *data, int len) { int ret; - struct nlnetwork *net = data; - struct nlmsghdr *nlh = data + sizeof(struct nlnetwork); + struct nethdr *net = data; + struct nlmsghdr *nlh = data + NETHDR_SIZ; struct nfgenmsg *nfhdr; ret = mcast_recv(m, net, len); @@ -102,17 +139,17 @@ int mcast_recv_netmsg(struct mcast_sock *m, void *data, int len) return ret; /* message too small: no room for the header */ - if (ret < sizeof(struct nlnetwork)) + if (ret < NETHDR_SIZ) return -1; - if (ntohs(net->flags) & NET_HELLO) + if (ntohs(net->flags) & NET_F_HELLO) STATE_SYNC(last_seq_recv) = ntohl(net->seq) - 1; - if (ntohs(net->flags) & NET_NACK || ntohs(net->flags) & NET_ACK) { - struct nlnetwork_ack *nack = (struct nlnetwork_ack *) net; + if (ntohs(net->flags) & NET_F_NACK || ntohs(net->flags) & NET_F_ACK) { + struct nethdr_ack *nack = (struct nethdr_ack *) net; /* message too small: no room for the header */ - if (ret < sizeof(struct nlnetwork_ack)) + if (ret < NETHDR_ACK_SIZ) return -1; /* host byte order conversion */ @@ -126,7 +163,7 @@ int mcast_recv_netmsg(struct mcast_sock *m, void *data, int len) return ret; } - if (ntohs(net->flags) & NET_RESYNC) { + if (ntohs(net->flags) & NET_F_RESYNC) { /* host byte order conversion */ net->flags = ntohs(net->flags); net->seq = ntohl(net->seq); @@ -139,7 +176,7 @@ int mcast_recv_netmsg(struct mcast_sock *m, void *data, int len) return -1; /* information received and message length does not match */ - if (ret != ntohl(nlh->nlmsg_len) + sizeof(struct nlnetwork)) + if (ret != ntohl(nlh->nlmsg_len) + NETHDR_SIZ) return -1; /* this message does not come from ctnetlink */ @@ -209,8 +246,8 @@ int build_network_msg(const int msg_type, unsigned int size) { memset(buffer, 0, size); - buffer += sizeof(struct nlnetwork); - size -= sizeof(struct nlnetwork); + buffer += NETHDR_SIZ; + size -= NETHDR_SIZ; return nfct_build_query(ssh, msg_type, ct, buffer, size); } diff --git a/src/run.c b/src/run.c index b7dc543..0173c9f 100644 --- a/src/run.c +++ b/src/run.c @@ -47,6 +47,11 @@ void killer(int foo) exit(0); } +static void child(int foo) +{ + while(wait(NULL) > 0); +} + void local_handler(int fd, void *data) { int ret; @@ -54,11 +59,11 @@ void local_handler(int fd, void *data) ret = read(fd, &type, sizeof(type)); if (ret == -1) { - dlog(STATE(log), "can't read from unix socket\n"); + dlog(STATE(log), "can't read from unix socket"); return; } if (ret == 0) { - debug("nothing to process\n"); + dlog(STATE(log), "local request: nothing to process?"); return; } @@ -122,6 +127,7 @@ int init(int mode) sigemptyset(&STATE(block)); sigaddset(&STATE(block), SIGTERM); sigaddset(&STATE(block), SIGINT); + sigaddset(&STATE(block), SIGCHLD); if (signal(SIGINT, killer) == SIG_ERR) return -1; @@ -133,6 +139,9 @@ int init(int mode) if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) return -1; + if (signal(SIGCHLD, child) == SIG_ERR) + return -1; + dlog(STATE(log), "[OK] initialization completed"); return 0; diff --git a/src/stats-mode.c b/src/stats-mode.c index f65fbdb..92794cd 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -142,9 +142,11 @@ static void event_new_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) if (cache_add(STATE_STATS(cache), ct)) { debug_ct(ct, "cache new"); } else { - dlog(STATE(log), "can't add to cache cache: " - "%s\n", strerror(errno)); - debug_ct(ct, "can't add"); + if (errno != EEXIST) { + dlog(STATE(log), "can't add to cache cache: " + "%s\n", strerror(errno)); + debug_ct(ct, "can't add"); + } } } diff --git a/src/sync-mode.c b/src/sync-mode.c index cb95392..8433532 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -32,10 +32,10 @@ static void mcast_handler() { int ret; - unsigned int type, size = sizeof(struct nlnetwork); + unsigned int type; char __net[4096]; - struct nlnetwork *net = (struct nlnetwork *) __net; - struct nlmsghdr *nlh = (struct nlmsghdr *) (__net + size); + struct nethdr *net = (struct nethdr *) __net; + struct nlmsghdr *nlh = (struct nlmsghdr *) (__net + NETHDR_SIZ); char __ct[nfct_maxsize()]; struct nf_conntrack *ct = (struct nf_conntrack *) __ct; struct us_conntrack *u = NULL; @@ -93,7 +93,7 @@ retry: debug_ct(ct, "can't destroy"); break; default: - debug("unknown type %d\n", type); + dlog(STATE(log), "mcast received unknown msg type %d\n", type); break; } } @@ -216,16 +216,32 @@ static int local_handler_sync(int fd, int type, void *data) switch(type) { case DUMP_INTERNAL: - cache_dump(STATE_SYNC(internal), fd, NFCT_O_PLAIN); + ret = fork(); + if (ret == 0) { + cache_dump(STATE_SYNC(internal), fd, NFCT_O_PLAIN); + exit(EXIT_SUCCESS); + } break; case DUMP_EXTERNAL: - cache_dump(STATE_SYNC(external), fd, NFCT_O_PLAIN); + ret = fork(); + if (ret == 0) { + cache_dump(STATE_SYNC(external), fd, NFCT_O_PLAIN); + exit(EXIT_SUCCESS); + } break; case DUMP_INT_XML: - cache_dump(STATE_SYNC(internal), fd, NFCT_O_XML); + ret = fork(); + if (ret == 0) { + cache_dump(STATE_SYNC(internal), fd, NFCT_O_XML); + exit(EXIT_SUCCESS); + } break; case DUMP_EXT_XML: - cache_dump(STATE_SYNC(external), fd, NFCT_O_XML); + ret = fork(); + if (ret == 0) { + cache_dump(STATE_SYNC(external), fd, NFCT_O_XML); + exit(EXIT_SUCCESS); + } break; case COMMIT: dlog(STATE(log), "[REQ] commit external cache to master table"); @@ -280,14 +296,14 @@ static void mcast_send_sync(struct nlmsghdr *nlh, int type) { char __net[4096]; - struct nlnetwork *net = (struct nlnetwork *) __net; + struct nethdr *net = (struct nethdr *) __net; memset(__net, 0, sizeof(__net)); if (!state_helper_verdict(type, ct)) return; - memcpy(__net + sizeof(struct nlnetwork), nlh, nlh->nlmsg_len); + memcpy(__net + NETHDR_SIZ, nlh, nlh->nlmsg_len); mcast_send_netmsg(STATE_SYNC(mcast_client), net); if (STATE_SYNC(sync)->send) STATE_SYNC(sync)->send(type, net, u); @@ -312,24 +328,8 @@ static int overrun_cb(enum nf_conntrack_msg_type type, if (!cache_test(STATE_SYNC(internal), ct)) { if ((u = cache_update_force(STATE_SYNC(internal), ct))) { - int ret; - char __nlh[4096]; - struct nlmsghdr *nlh = (struct nlmsghdr *) __nlh; - debug_ct(u->ct, "overrun resync"); - - ret = nfct_build_query(STATE(subsys_dump), - NFCT_Q_UPDATE, - u->ct, - __nlh, - sizeof(__nlh)); - - if (ret == -1) { - dlog(STATE(log), "can't build overrun"); - return NFCT_CB_CONTINUE; - } - - mcast_send_sync(nlh, u, ct, NFCT_T_UPDATE); + mcast_build_send_update(u); } } @@ -344,21 +344,8 @@ static int overrun_purge_step(void *data1, void *data2) ret = nfct_query(h, NFCT_Q_GET, u->ct); if (ret == -1 && errno == ENOENT) { - char __nlh[4096]; - struct nlmsghdr *nlh = (struct nlmsghdr *) (__nlh); - debug_ct(u->ct, "overrun purge resync"); - - ret = nfct_build_query(STATE(subsys_dump), - NFCT_Q_DESTROY, - u->ct, - __nlh, - sizeof(__nlh)); - - if (ret == -1) - dlog(STATE(log), "failed to build network message"); - - mcast_send_sync(nlh, NULL, u->ct, NFCT_T_DESTROY); + mcast_build_send_destroy(u); __cache_del(STATE_SYNC(internal), u->ct); } diff --git a/src/sync-nack.c b/src/sync-nack.c index 1f62294..20ad1f4 100644 --- a/src/sync-nack.c +++ b/src/sync-nack.c @@ -79,14 +79,14 @@ static void nack_kill() static void mcast_send_control(u_int32_t flags, u_int32_t from, u_int32_t to) { - struct nlnetwork_ack ack = { + struct nethdr_ack ack = { .flags = flags, .from = from, .to = to, }; mcast_send_error(STATE_SYNC(mcast_client), &ack); - buffer_add(STATE_SYNC(buffer), &ack, sizeof(struct nlnetwork_ack)); + buffer_add(STATE_SYNC(buffer), &ack, NETHDR_ACK_SIZ); } static int nack_local(int fd, int type, void *data) @@ -95,7 +95,7 @@ static int nack_local(int fd, int type, void *data) switch(type) { case REQUEST_DUMP: - mcast_send_control(NET_RESYNC, 0, 0); + mcast_send_control(NET_F_RESYNC, 0, 0); dlog(STATE(log), "[REQ] request resync"); break; default: @@ -108,9 +108,9 @@ static int nack_local(int fd, int type, void *data) static int buffer_compare(void *data1, void *data2) { - struct nlnetwork *net = data1; - struct nlnetwork_ack *nack = data2; - struct nlmsghdr *nlh = data1 + sizeof(struct nlnetwork); + struct nethdr *net = data1; + struct nethdr_ack *nack = data2; + struct nlmsghdr *nlh = data1 + NETHDR_SIZ; unsigned old_seq = ntohl(net->seq); @@ -124,8 +124,8 @@ static int buffer_compare(void *data1, void *data2) static int buffer_remove(void *data1, void *data2) { - struct nlnetwork *net = data1; - struct nlnetwork_ack *h = data2; + struct nethdr *net = data1; + struct nethdr_ack *h = data2; if (between(ntohl(net->seq), h->from, h->to)) { dp("remove from buffer (seq=%u)\n", ntohl(net->seq)); @@ -138,9 +138,7 @@ static void queue_resend(struct cache *c, unsigned int from, unsigned int to) { struct list_head *n; struct us_conntrack *u; - unsigned int *seq; - lock(); list_for_each(n, &queue) { struct cache_nack *cn = (struct cache_nack *) n; struct us_conntrack *u; @@ -151,35 +149,19 @@ static void queue_resend(struct cache *c, unsigned int from, unsigned int to) debug_ct(u->ct, "resend nack"); dp("resending nack'ed (oldseq=%u) ", cn->seq); - char buf[4096]; - struct nlnetwork *net = (struct nlnetwork *) buf; - - int ret = build_network_msg(NFCT_Q_UPDATE, - STATE(subsys_event), - u->ct, - buf, - sizeof(buf)); - if (ret == -1) { - unlock(); - break; - } - - mcast_send_netmsg(STATE_SYNC(mcast_client), buf); - if (STATE_SYNC(sync)->send) - STATE_SYNC(sync)->send(NFCT_T_UPDATE, net, u); - dp("(newseq=%u)\n", *seq); + if (mcast_build_send_update(u) == -1) + continue; + + dp("(newseq=%u)\n", cn->seq); } } - unlock(); } static void queue_empty(struct cache *c, unsigned int from, unsigned int to) { struct list_head *n, *tmp; struct us_conntrack *u; - unsigned int *seq; - lock(); dp("ACK from %u to %u\n", from, to); list_for_each_safe(n, tmp, &queue) { struct cache_nack *cn = (struct cache_nack *) n; @@ -193,10 +175,9 @@ static void queue_empty(struct cache *c, unsigned int from, unsigned int to) INIT_LIST_HEAD(&cn->head); } } - unlock(); } -static int nack_recv(const struct nlnetwork *net) +static int nack_recv(const struct nethdr *net) { static unsigned int window = 0; unsigned int exp_seq; @@ -206,31 +187,31 @@ static int nack_recv(const struct nlnetwork *net) if (!mcast_track_seq(net->seq, &exp_seq)) { dp("OOS: sending nack (seq=%u)\n", exp_seq); - mcast_send_control(NET_NACK, exp_seq, net->seq - 1); + mcast_send_control(NET_F_NACK, exp_seq, net->seq - 1); window = CONFIG(window_size); } else { /* received a window, send an acknowledgement */ if (--window == 0) { dp("sending ack (seq=%u)\n", net->seq); - mcast_send_control(NET_ACK, + mcast_send_control(NET_F_ACK, net->seq - CONFIG(window_size), net->seq); } } - if (net->flags & NET_NACK) { - struct nlnetwork_ack *nack = (struct nlnetwork_ack *) net; + if (net->flags & NET_F_NACK) { + struct nethdr_ack *nack = (struct nethdr_ack *) net; dp("NACK: from seq=%u to seq=%u\n", nack->from, nack->to); queue_resend(STATE_SYNC(internal), nack->from, nack->to); buffer_iterate(STATE_SYNC(buffer), nack, buffer_compare); return 1; - } else if (net->flags & NET_RESYNC) { + } else if (net->flags & NET_F_RESYNC) { dp("RESYNC ALL\n"); cache_bulk(STATE_SYNC(internal)); return 1; - } else if (net->flags & NET_ACK) { - struct nlnetwork_ack *h = (struct nlnetwork_ack *) net; + } else if (net->flags & NET_F_ACK) { + struct nethdr_ack *h = (struct nethdr_ack *) net; dp("ACK: from seq=%u to seq=%u\n", h->from, h->to); queue_empty(STATE_SYNC(internal), h->from, h->to); @@ -242,10 +223,10 @@ static int nack_recv(const struct nlnetwork *net) } static void nack_send(int type, - const struct nlnetwork *net, + const struct nethdr *net, struct us_conntrack *u) { - unsigned int size = sizeof(struct nlnetwork); + int size = NETHDR_SIZ; struct nlmsghdr *nlh = (struct nlmsghdr *) ((void *) net + size); struct cache_nack *cn; diff --git a/src/sync-notrack.c b/src/sync-notrack.c index 4a470f9..1d6eba8 100644 --- a/src/sync-notrack.c +++ b/src/sync-notrack.c @@ -25,18 +25,11 @@ static void refresher(struct alarm_list *a, void *data) { struct us_conntrack *u = data; - char __net[4096]; - int size; debug_ct(u->ct, "persistence update"); a->expires = random() % CONFIG(refresh) + 1; - size = build_network_msg(NFCT_Q_UPDATE, - STATE(subsys_event), - u->ct, - __net, - sizeof(__net)); - mcast_send_netmsg(STATE_SYNC(mcast_client), __net); + mcast_build_send_update(u); } static void cache_notrack_add(struct us_conntrack *u, void *data) @@ -69,7 +62,7 @@ static struct cache_extra cache_notrack_extra = { .destroy = cache_notrack_destroy }; -static int notrack_recv(const struct nlnetwork *net) +static int notrack_recv(const struct nethdr *net) { unsigned int exp_seq; @@ -78,7 +71,7 @@ static int notrack_recv(const struct nlnetwork *net) * generated in notrack mode, we don't want to crash the daemon * if someone nuts mixes nack and notrack. */ - if (net->flags & (NET_RESYNC | NET_NACK)) + if (net->flags) return 1; /* -- cgit v1.2.3 From 96084e1a1f2e0a49c961bbddb9fffd2e03bfae3f Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Mon, 9 Jul 2007 19:11:53 +0000 Subject: - conntrack-tools requires libnetfilter_conntrack >= 0.0.81 - add len field to nethdr - implement buffered send/recv to batch messages - stop using netlink format for network messages: use similar TLV-based format - reduce synchronization messages size up to 60% - introduce periodic alive messages for sync-nack protocol - timeslice alarm implementation: remove alarm pthread, remove locking - simplify debugging functions: use nfct_snprintf instead - remove major use of libnfnetlink functions: use libnetfilter_conntrack API - deprecate conntrackd -F, use conntrack -F instead - major rework of the network infrastructure: much simple, less messy --- ChangeLog | 16 ++++ configure.in | 4 +- include/Makefile.am | 2 +- include/buffer.h | 5 +- include/conntrackd.h | 21 ++-- include/debug.h | 56 ++--------- include/network.h | 106 +++++++++++++++++++- include/sync.h | 7 +- include/timer.h | 17 ++++ src/Makefile.am | 7 +- src/alarm.c | 37 ++----- src/buffer.c | 26 ++--- src/build.c | 113 ++++++++++++++++++++++ src/cache.c | 40 +------- src/cache_iterators.c | 54 +---------- src/cache_timer.c | 2 +- src/lock.c | 32 ------- src/main.c | 1 + src/mcast.c | 1 - src/netlink.c | 137 ++++++-------------------- src/network.c | 238 +++++++++++++++++---------------------------- src/parse.c | 76 +++++++++++++++ src/proxy.c | 124 ------------------------ src/run.c | 72 ++++++++++---- src/state_helper.c | 2 +- src/stats-mode.c | 10 +- src/sync-mode.c | 152 +++++++++++++++++------------ src/sync-nack.c | 260 ++++++++++++++++++++++++++++++++++---------------- src/sync-notrack.c | 6 +- src/timer.c | 75 +++++++++++++++ 30 files changed, 909 insertions(+), 790 deletions(-) create mode 100644 include/timer.h create mode 100644 src/build.c create mode 100644 src/parse.c delete mode 100644 src/proxy.c create mode 100644 src/timer.c (limited to 'src/stats-mode.c') diff --git a/ChangeLog b/ChangeLog index 0166c97..b65966b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +version 0.9.5 (yet unreleased) +------------------------------ + += conntrackd = +o conntrack-tools requires libnetfilter_conntrack >= 0.0.81 +o add len field to nethdr +o implement buffered send/recv to batch messages +o stop using netlink format for network messages: use similar TLV-based format +o reduce synchronization messages size up to 60% +o introduce periodic alive messages for sync-nack protocol +o timeslice alarm implementation: remove alarm pthread, remove locking +o simplify debugging functions: use nfct_snprintf instead +o remove major use of libnfnetlink functions: use libnetfilter_conntrack API +o deprecate conntrackd -F, use conntrack -F instead +o major rework of the network infrastructure: much simple, less messy + version 0.9.4 (2007/07/02) ------------------------------ diff --git a/configure.in b/configure.in index 41a001c..7e1cd20 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -AC_INIT(conntrack-tools, 0.9.4, pablo@netfilter.org) +AC_INIT(conntrack-tools, 0.9.5, pablo@netfilter.org) AC_CANONICAL_SYSTEM @@ -18,7 +18,7 @@ esac dnl Dependencies LIBNFNETLINK_REQUIRED=0.0.25 -LIBNETFILTER_CONNTRACK_REQUIRED=0.0.80 +LIBNETFILTER_CONNTRACK_REQUIRED=0.0.81 PKG_CHECK_MODULES(LIBNFNETLINK, libnfnetlink >= $LIBNFNETLINK_REQUIRED,, AC_MSG_ERROR(Cannot find libnfnetlink >= $LIBNFNETLINK_REQUIRED)) diff --git a/include/Makefile.am b/include/Makefile.am index a7716d9..7b6bc14 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -2,5 +2,5 @@ noinst_HEADERS = alarm.h jhash.h slist.h cache.h linux_list.h \ sync.h conntrackd.h local.h us-conntrack.h \ debug.h log.h hash.h mcast.h buffer.h conntrack.h \ - state_helper.h network.h ignore.h + state_helper.h network.h ignore.h timer.h diff --git a/include/buffer.h b/include/buffer.h index 8d72dfb..cb42f51 100644 --- a/include/buffer.h +++ b/include/buffer.h @@ -4,13 +4,12 @@ #include #include #include -#include #include "linux_list.h" struct buffer { - pthread_mutex_t lock; size_t max_size; size_t cur_size; + unsigned int num_elems; struct list_head head; }; @@ -22,9 +21,9 @@ struct buffer_node { struct buffer *buffer_create(size_t max_size); void buffer_destroy(struct buffer *b); +unsigned int buffer_len(struct buffer *b); int buffer_add(struct buffer *b, const void *data, size_t size); void buffer_del(struct buffer *b, void *data); -void __buffer_del(struct buffer *b, void *data); void buffer_iterate(struct buffer *b, void *data, int (*iterate)(void *data1, void *data2)); diff --git a/include/conntrackd.h b/include/conntrackd.h index a620400..e89fc79 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -10,6 +10,7 @@ #include "debug.h" #include #include "state_helper.h" +#include "linux_list.h" #include /* UNIX facilities */ @@ -92,11 +93,8 @@ struct ct_general_state { struct ct_mode *mode; struct ignore_pool *ignore_pool; - struct nfnl_handle *event; /* event handler */ - struct nfnl_handle *dump; /* dump handler */ - - struct nfnl_subsys_handle *subsys_event; /* events */ - struct nfnl_subsys_handle *subsys_dump; /* dump */ + struct nfct_handle *event; /* event handler */ + struct nfct_handle *dump; /* dump handler */ /* statistics */ u_int64_t malformed; @@ -114,7 +112,6 @@ struct ct_sync_state { struct mcast_sock *mcast_client; /* multicast socket: outgoing */ struct sync_mode *sync; /* sync mode */ - struct buffer *buffer; u_int32_t last_seq_sent; /* last sequence number sent */ u_int32_t last_seq_recv; /* last sequence number recv */ @@ -141,17 +138,19 @@ extern struct ct_general_state st; #define IPPROTO_VRRP 112 #endif +#define STEPS_PER_SECONDS 5 + struct ct_mode { int (*init)(void); int (*add_fds_to_set)(fd_set *readfds); - void (*step)(fd_set *readfds); + void (*run)(fd_set *readfds, int step); int (*local)(int fd, int type, void *data); void (*kill)(void); - void (*dump)(struct nf_conntrack *ct, struct nlmsghdr *nlh); + void (*dump)(struct nf_conntrack *ct); void (*overrun)(void); - void (*event_new)(struct nf_conntrack *ct, struct nlmsghdr *nlh); - void (*event_upd)(struct nf_conntrack *ct, struct nlmsghdr *nlh); - int (*event_dst)(struct nf_conntrack *ct, struct nlmsghdr *nlh); + void (*event_new)(struct nf_conntrack *ct); + void (*event_upd)(struct nf_conntrack *ct); + int (*event_dst)(struct nf_conntrack *ct); }; /* conntrackd modes */ diff --git a/include/debug.h b/include/debug.h index 4d1f44f..1ffd9ac 100644 --- a/include/debug.h +++ b/include/debug.h @@ -1,57 +1,21 @@ #ifndef _DEBUG_H #define _DEBUG_H -#if 0 -#define debug printf -#else -#define debug -#endif - -#include -#include #include #undef DEBUG_CT -static inline void debug_ct(struct nf_conntrack *ct, char *msg) -{ #ifdef DEBUG_CT - struct in_addr addr, addr2, addr3, addr4; - - debug("----%s (%p) ----\n", msg, ct); - memcpy(&addr, - nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC), - sizeof(u_int32_t)); - memcpy(&addr2, - nfct_get_attr(ct, ATTR_ORIG_IPV4_DST), - sizeof(u_int32_t)); - memcpy(&addr3, - nfct_get_attr(ct, ATTR_REPL_IPV4_SRC), - sizeof(u_int32_t)); - memcpy(&addr4, - nfct_get_attr(ct, ATTR_REPL_IPV4_DST), - sizeof(u_int32_t)); - - debug("status: %x\n", nfct_get_attr_u32(ct, ATTR_STATUS)); - debug("l3:%d l4:%d ", - nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO), - nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)); - debug("%s:%hu ->", inet_ntoa(addr), - ntohs(nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC))); - debug("%s:%hu\n", - inet_ntoa(addr2), - ntohs(nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST))); - debug("l3:%d l4:%d ", - nfct_get_attr_u8(ct, ATTR_REPL_L3PROTO), - nfct_get_attr_u8(ct, ATTR_REPL_L4PROTO)); - debug("%s:%hu ->", - inet_ntoa(addr3), - ntohs(nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC))); - debug("%s:%hu\n", - inet_ntoa(addr4), - ntohs(nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST))); - debug("-------------------------\n"); +#define debug_ct(ct, msg) \ +({ \ + char buf[1024]; \ + nfct_snprintf(buf, 1024, ct, NFCT_T_ALL, 0, 0); \ + printf("[%s]: %s\n", msg, buf); \ +}) +#define debug printf +#else +#define debug_ct(ct, msg) +#define debug #endif -} #endif diff --git a/include/network.h b/include/network.h index 31903a5..bc9431d 100644 --- a/include/network.h +++ b/include/network.h @@ -5,14 +5,17 @@ struct nethdr { u_int16_t flags; - u_int16_t padding; + u_int16_t len; u_int32_t seq; }; #define NETHDR_SIZ sizeof(struct nethdr) +#define NETHDR_DATA(x) \ + (struct netpld *)(((char *)x) + sizeof(struct nethdr)) + struct nethdr_ack { u_int16_t flags; - u_int16_t padding; + u_int16_t len; u_int32_t seq; u_int32_t from; u_int32_t to; @@ -31,8 +34,59 @@ enum { NET_F_ACK_BIT = 3, NET_F_ACK = (1 << NET_F_ACK_BIT), + + NET_F_ALIVE_BIT = 4, + NET_F_ALIVE = (1 << NET_F_ALIVE_BIT), }; +#define BUILD_NETMSG(ct, query) \ +({ \ + char __net[4096]; \ + memset(__net, 0, sizeof(__net)); \ + build_netmsg(ct, query, (struct nethdr *) __net); \ + (struct nethdr *) __net; \ +}) + +struct us_conntrack; +struct mcast_sock; + +void build_netmsg(struct nf_conntrack *ct, int query, struct nethdr *net); +int prepare_send_netmsg(struct mcast_sock *m, void *data); +int mcast_send_netmsg(struct mcast_sock *m, void *data); +int mcast_recv_netmsg(struct mcast_sock *m, void *data, int len); + +#define IS_DATA(x) ((x->flags & ~NET_F_HELLO) == 0) +#define IS_ACK(x) (x->flags & NET_F_ACK) +#define IS_NACK(x) (x->flags & NET_F_NACK) +#define IS_RESYNC(x) (x->flags & NET_F_RESYNC) +#define IS_ALIVE(x) (x->flags & NET_F_ALIVE) +#define IS_CTL(x) IS_ACK(x) || IS_NACK(x) || IS_RESYNC(x) || IS_ALIVE(x) +#define IS_HELLO(x) (x->flags & NET_F_HELLO) + +#define HDR_NETWORK2HOST(x) \ +({ \ + x->flags = ntohs(x->flags); \ + x->len = ntohs(x->len); \ + x->seq = ntohl(x->seq); \ + if (IS_CTL(x)) { \ + struct nethdr_ack *__ack = (struct nethdr_ack *) x; \ + __ack->from = ntohl(__ack->from); \ + __ack->to = ntohl(__ack->to); \ + } \ +}) + +#define HDR_HOST2NETWORK(x) \ +({ \ + if (IS_CTL(x)) { \ + struct nethdr_ack *__ack = (struct nethdr_ack *) x; \ + __ack->from = htonl(__ack->from); \ + __ack->to = htonl(__ack->to); \ + } \ + x->flags = htons(x->flags); \ + x->len = htons(x->len); \ + x->seq = htonl(x->seq); \ +}) + /* extracted from net/tcp.h */ /* @@ -52,4 +106,52 @@ static inline int between(__u32 seq1, __u32 seq2, __u32 seq3) return seq3 - seq2 >= seq1 - seq2; } +struct netpld { + u_int16_t len; + u_int16_t query; +}; +#define NETPLD_SIZ sizeof(struct netpld) + +#define PLD_NETWORK2HOST(x) \ +({ \ + x->len = ntohs(x->len); \ + x->query = ntohs(x->query); \ +}) + +#define PLD_HOST2NETWORK(x) \ +({ \ + x->len = htons(x->len); \ + x->query = htons(x->query); \ +}) + +struct netattr { + u_int16_t nta_len; + u_int16_t nta_attr; +}; + +#define ATTR_NETWORK2HOST(x) \ +({ \ + x->nta_len = ntohs(x->nta_len); \ + x->nta_attr = ntohs(x->nta_attr); \ +}) + +#define PLD_DATA(x) \ + (struct netattr *)(((char *)x) + sizeof(struct netpld)) + +#define PLD_TAIL(x) \ + (struct netattr *)(((char *)x) + sizeof(struct netpld) + x->len) + +#define NTA_DATA(x) \ + (void *)(((char *)x) + sizeof(struct netattr)) + +#define NTA_NEXT(x, len) \ +({ \ + len -= NTA_ALIGN(NTA_LENGTH(x->nta_len)); \ + (struct netattr *)(((char *)x) + NTA_ALIGN(NTA_LENGTH(x->nta_len))); \ +}) + +#define NTA_ALIGNTO 4 +#define NTA_ALIGN(len) (((len) + NTA_ALIGNTO - 1) & ~(NTA_ALIGNTO - 1)) +#define NTA_LENGTH(len) (NTA_ALIGN(sizeof(struct netattr)) + (len)) + #endif diff --git a/include/sync.h b/include/sync.h index a737e81..6345513 100644 --- a/include/sync.h +++ b/include/sync.h @@ -13,10 +13,9 @@ struct sync_mode { int (*init)(void); void (*kill)(void); int (*local)(int fd, int type, void *data); - int (*recv)(const struct nethdr *net); /* recv callback */ - void (*send)(int type, /* send callback */ - const struct nethdr *net, - struct us_conntrack *u); + int (*recv)(const struct nethdr *net); + void (*send)(struct nethdr *net, struct us_conntrack *u); + void (*run)(int step); }; extern struct sync_mode notrack; diff --git a/include/timer.h b/include/timer.h new file mode 100644 index 0000000..37b0fc9 --- /dev/null +++ b/include/timer.h @@ -0,0 +1,17 @@ +#ifndef _TIMER_H_ +#define _TIMER_H_ + +#include + +struct timer { + long credits; + struct timeval start; + struct timeval stop; + struct timeval diff; +}; + +#define GET_CREDITS(x) x.credits +#define GET_STARTTIME(x) x.start +#define GET_STOPTIME(x) x.stop + +#endif diff --git a/src/Makefile.am b/src/Makefile.am index 8647d04..d71e23c 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 conntrackd_SOURCES = alarm.c main.c run.c hash.c buffer.c \ - local.c log.c mcast.c netlink.c proxy.c lock.c \ + local.c log.c mcast.c netlink.c \ ignore_pool.c \ cache.c cache_iterators.c \ cache_lifetime.c cache_timer.c \ @@ -18,9 +18,10 @@ conntrackd_SOURCES = alarm.c main.c run.c hash.c buffer.c \ traffic_stats.c stats-mode.c \ network.c \ state_helper.c state_helper_tcp.c \ + timer.c \ + build.c parse.c \ read_config_yy.y read_config_lex.l -conntrackd_LDFLAGS = $(all_libraries) -lnfnetlink -lnetfilter_conntrack \ - -lpthread +conntrackd_LDFLAGS = $(all_libraries) -lnfnetlink -lnetfilter_conntrack EXTRA_DIST = read_config_yy.h diff --git a/src/alarm.c b/src/alarm.c index 1a465c2..b4db167 100644 --- a/src/alarm.c +++ b/src/alarm.c @@ -22,17 +22,13 @@ #include "conntrackd.h" #include "alarm.h" #include "jhash.h" -#include #include #include /* alarm cascade */ -#define ALARM_CASCADE_SIZE 10 +#define ALARM_CASCADE_SIZE STEPS_PER_SECONDS static struct list_head *alarm_cascade; -/* thread stuff */ -static pthread_t alarm_thread; - struct alarm_list *create_alarm() { return (struct alarm_list *) malloc(sizeof(struct alarm_list)); @@ -86,24 +82,11 @@ int mod_alarm(struct alarm_list *alarm, unsigned long expires) return 0; } -void __run_alarms() +void do_alarm_run(int step) { struct list_head *i, *tmp; struct alarm_list *t; - struct timespec req = {0, 1000000000 / ALARM_CASCADE_SIZE}; - struct timespec rem; - static int step = 0; - -retry: - if (nanosleep(&req, &rem) == -1) { - /* interrupted syscall: retry with remaining time */ - if (errno == EINTR) { - memcpy(&req, &rem, sizeof(struct timespec)); - goto retry; - } - } - lock(); list_for_each_safe(i, tmp, &alarm_cascade[step]) { t = (struct alarm_list *) i; @@ -111,17 +94,9 @@ retry: if (t->expires == 0) t->function(t, t->data); } - step = (step + 1) < ALARM_CASCADE_SIZE ? step + 1 : 0; - unlock(); -} - -void *run_alarms(void *foo) -{ - while(1) - __run_alarms(); } -int create_alarm_thread() +int init_alarm_scheduler() { int i; @@ -132,10 +107,10 @@ int create_alarm_thread() for (i=0; imax_size = max_size; INIT_LIST_HEAD(&b->head); - pthread_mutex_init(&b->lock, NULL); return b; } @@ -39,14 +38,12 @@ void buffer_destroy(struct buffer *b) struct list_head *i, *tmp; struct buffer_node *node; - pthread_mutex_lock(&b->lock); + /* XXX: set cur_size and num_elems */ list_for_each_safe(i, tmp, &b->head) { node = (struct buffer_node *) i; list_del(i); free(node); } - pthread_mutex_unlock(&b->lock); - pthread_mutex_destroy(&b->lock); free(b); } @@ -70,8 +67,6 @@ int buffer_add(struct buffer *b, const void *data, size_t size) int ret = 0; struct buffer_node *n; - pthread_mutex_lock(&b->lock); - /* does it fit this buffer? */ if (size > b->max_size) { errno = ENOSPC; @@ -97,28 +92,22 @@ retry: list_add(&n->head, &b->head); b->cur_size += size; + b->num_elems++; err: - pthread_mutex_unlock(&b->lock); return ret; } -void __buffer_del(struct buffer *b, void *data) +void buffer_del(struct buffer *b, void *data) { struct buffer_node *n = container_of(data, struct buffer_node, data); list_del(&n->head); b->cur_size -= n->size; + b->num_elems--; free(n); } -void buffer_del(struct buffer *b, void *data) -{ - pthread_mutex_lock(&b->lock); - buffer_del(b, data); - pthread_mutex_unlock(&b->lock); -} - void buffer_iterate(struct buffer *b, void *data, int (*iterate)(void *data1, void *data2)) @@ -126,11 +115,14 @@ void buffer_iterate(struct buffer *b, struct list_head *i, *tmp; struct buffer_node *n; - pthread_mutex_lock(&b->lock); list_for_each_safe(i, tmp, &b->head) { n = (struct buffer_node *) i; if (iterate(n->data, data)) break; } - pthread_mutex_unlock(&b->lock); +} + +unsigned int buffer_len(struct buffer *b) +{ + return b->num_elems; } diff --git a/src/build.c b/src/build.c new file mode 100644 index 0000000..b77dbc2 --- /dev/null +++ b/src/build.c @@ -0,0 +1,113 @@ +/* + * (C) 2006-2007 by Pablo Neira Ayuso + * + * 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 +#include +#include "network.h" + +static void addattr(struct netpld *pld, int attr, const void *data, int len) +{ + struct netattr *nta; + int tlen = NTA_LENGTH(len); + + nta = PLD_TAIL(pld); + nta->nta_attr = htons(attr); + nta->nta_len = htons(len); + memcpy(NTA_DATA(nta), data, len); + pld->len += NTA_ALIGN(tlen); +} + +static void __build_u8(const struct nf_conntrack *ct, + struct netpld *pld, + int attr) +{ + u_int8_t data = nfct_get_attr_u8(ct, attr); + addattr(pld, attr, &data, sizeof(u_int8_t)); +} + +static void __build_u16(const struct nf_conntrack *ct, + struct netpld *pld, + int attr) +{ + u_int16_t data = nfct_get_attr_u16(ct, attr); + data = htons(data); + addattr(pld, attr, &data, sizeof(u_int16_t)); +} + +static void __build_u32(const struct nf_conntrack *ct, + struct netpld *pld, + int attr) +{ + u_int32_t data = nfct_get_attr_u32(ct, attr); + data = htonl(data); + addattr(pld, attr, &data, sizeof(u_int32_t)); +} + +/* XXX: IPv6 and ICMP not supported */ +void build_netpld(struct nf_conntrack *ct, struct netpld *pld, int query) +{ + /* undo NAT */ + if (nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT)) + nfct_setobjopt(ct, NFCT_SOPT_UNDO_SNAT); + if (nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT)) + nfct_setobjopt(ct, NFCT_SOPT_UNDO_DNAT); + if (nfct_getobjopt(ct, NFCT_GOPT_IS_SPAT)) + nfct_setobjopt(ct, NFCT_SOPT_UNDO_SPAT); + if (nfct_getobjopt(ct, NFCT_GOPT_IS_DPAT)) + nfct_setobjopt(ct, NFCT_SOPT_UNDO_DPAT); + + /* build message */ + if (nfct_attr_is_set(ct, ATTR_IPV4_SRC)) + __build_u32(ct, pld, ATTR_IPV4_SRC); + if (nfct_attr_is_set(ct, ATTR_IPV4_DST)) + __build_u32(ct, pld, ATTR_IPV4_DST); + if (nfct_attr_is_set(ct, ATTR_L3PROTO)) + __build_u8(ct, pld, ATTR_L3PROTO); + if (nfct_attr_is_set(ct, ATTR_PORT_SRC)) + __build_u16(ct, pld, ATTR_PORT_SRC); + if (nfct_attr_is_set(ct, ATTR_PORT_DST)) + __build_u16(ct, pld, ATTR_PORT_DST); + if (nfct_attr_is_set(ct, ATTR_L4PROTO)) { + u_int8_t proto; + + __build_u8(ct, pld, ATTR_L4PROTO); + proto = nfct_get_attr_u8(ct, ATTR_L4PROTO); + if (proto == IPPROTO_TCP) { + if (nfct_attr_is_set(ct, ATTR_TCP_STATE)) + __build_u8(ct, pld, ATTR_TCP_STATE); + } + } + if (nfct_attr_is_set(ct, ATTR_SNAT_IPV4)) + __build_u32(ct, pld, ATTR_SNAT_IPV4); + if (nfct_attr_is_set(ct, ATTR_DNAT_IPV4)) + __build_u32(ct, pld, ATTR_DNAT_IPV4); + if (nfct_attr_is_set(ct, ATTR_SNAT_PORT)) + __build_u16(ct, pld, ATTR_SNAT_PORT); + if (nfct_attr_is_set(ct, ATTR_DNAT_PORT)) + __build_u16(ct, pld, ATTR_DNAT_PORT); + if (nfct_attr_is_set(ct, ATTR_TIMEOUT)) + __build_u32(ct, pld, ATTR_TIMEOUT); + if (nfct_attr_is_set(ct, ATTR_MARK)) + __build_u32(ct, pld, ATTR_MARK); + if (nfct_attr_is_set(ct, ATTR_STATUS)) + __build_u32(ct, pld, ATTR_STATUS); + + pld->query = query; + + PLD_HOST2NETWORK(pld); +} diff --git a/src/cache.c b/src/cache.c index 3bf331c..1e20d95 100644 --- a/src/cache.c +++ b/src/cache.c @@ -193,9 +193,7 @@ struct cache *cache_create(char *name, void cache_destroy(struct cache *c) { - lock(); hashtable_destroy(c->h); - unlock(); free(c->features); free(c->feature_offset); free(c); @@ -237,7 +235,7 @@ static struct us_conntrack *__add(struct cache *c, struct nf_conntrack *ct) return NULL; } -struct us_conntrack *__cache_add(struct cache *c, struct nf_conntrack *ct) +struct us_conntrack *cache_add(struct cache *c, struct nf_conntrack *ct) { struct us_conntrack *u; @@ -252,17 +250,6 @@ struct us_conntrack *__cache_add(struct cache *c, struct nf_conntrack *ct) return NULL; } -struct us_conntrack *cache_add(struct cache *c, struct nf_conntrack *ct) -{ - struct us_conntrack *u; - - lock(); - u = __cache_add(c, ct); - unlock(); - - return u; -} - static struct us_conntrack *__update(struct cache *c, struct nf_conntrack *ct) { size_t size = c->h->datasize; @@ -317,9 +304,7 @@ struct us_conntrack *cache_update(struct cache *c, struct nf_conntrack *ct) { struct us_conntrack *u; - lock(); u = __cache_update(c, ct); - unlock(); return u; } @@ -329,19 +314,15 @@ struct us_conntrack *cache_update_force(struct cache *c, { struct us_conntrack *u; - lock(); if ((u = __update(c, ct)) != NULL) { c->upd_ok++; - unlock(); return u; } if ((u = __add(c, ct)) != NULL) { c->add_ok++; - unlock(); return u; } c->add_fail++; - unlock(); return NULL; } @@ -354,9 +335,7 @@ int cache_test(struct cache *c, struct nf_conntrack *ct) u->ct = ct; - lock(); ret = hashtable_test(c->h, u); - unlock(); return ret != NULL; } @@ -390,7 +369,7 @@ static int __del(struct cache *c, struct nf_conntrack *ct) return 0; } -int __cache_del(struct cache *c, struct nf_conntrack *ct) +int cache_del(struct cache *c, struct nf_conntrack *ct) { if (__del(c, ct)) { c->del_ok++; @@ -401,17 +380,6 @@ int __cache_del(struct cache *c, struct nf_conntrack *ct) return 0; } -int cache_del(struct cache *c, struct nf_conntrack *ct) -{ - int ret; - - lock(); - ret = __cache_del(c, ct); - unlock(); - - return ret; -} - struct us_conntrack *cache_get_conntrack(struct cache *c, void *data) { return data - c->extra_offset; @@ -427,7 +395,6 @@ void cache_stats(struct cache *c, int fd) char buf[512]; int size; - lock(); size = sprintf(buf, "cache %s:\n" "current active connections:\t%12u\n" "connections created:\t\t%12u\tfailed:\t%12u\n" @@ -441,7 +408,6 @@ void cache_stats(struct cache *c, int fd) c->upd_fail, c->del_ok, c->del_fail); - unlock(); send(fd, buf, size, 0); } @@ -449,7 +415,5 @@ void cache_iterate(struct cache *c, void *data, int (*iterate)(void *data1, void *data2)) { - lock(); hashtable_iterate(c->h, data, iterate); - unlock(); } diff --git a/src/cache_iterators.c b/src/cache_iterators.c index 446cac8..1d1b2e8 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -71,37 +71,25 @@ void cache_dump(struct cache *c, int fd, int type) .type = type }; - /* does not require locking: called inside fork() */ hashtable_iterate(c->h, (void *) &tmp, do_dump); } +/* no need to clone, called from child process */ static int do_commit(void *data1, void *data2) { int ret; struct cache *c = data1; struct us_conntrack *u = data2; - struct nf_conntrack *ct; - char buf[4096]; - struct nlmsghdr *nlh = (struct nlmsghdr *)buf; - - ct = nfct_clone(u->ct); - if (ct == NULL) - return 0; + struct nf_conntrack *ct = u->ct; + /* XXX: related connections */ if (nfct_attr_is_set(ct, ATTR_STATUS)) { u_int32_t status = nfct_get_attr_u32(ct, ATTR_STATUS); status &= ~IPS_EXPECTED; nfct_set_attr_u32(ct, ATTR_STATUS, status); } - if (nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT)) - nfct_setobjopt(ct, NFCT_SOPT_UNDO_SNAT); - if (nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT)) - nfct_setobjopt(ct, NFCT_SOPT_UNDO_DNAT); - if (nfct_getobjopt(ct, NFCT_GOPT_IS_SPAT)) - nfct_setobjopt(ct, NFCT_SOPT_UNDO_SPAT); - if (nfct_getobjopt(ct, NFCT_GOPT_IS_DPAT)) - nfct_setobjopt(ct, NFCT_SOPT_UNDO_DPAT); + nfct_setobjopt(ct, NFCT_SOPT_SETUP_REPLY); /* * Set a reduced timeout for candidate-to-be-committed @@ -109,20 +97,12 @@ static int do_commit(void *data1, void *data2) */ nfct_set_attr_u32(ct, ATTR_TIMEOUT, CONFIG(commit_timeout)); - ret = nfct_build_query(STATE(subsys_dump), - NFCT_Q_CREATE_UPDATE, - ct, - nlh, - sizeof(buf)); - - free(ct); - if (ret == -1) { dlog(STATE(log), "failed to build: %s", strerror(errno)); return 0; } - ret = nfnl_query(STATE(dump), nlh); + ret = nfct_query(STATE(dump), NFCT_Q_CREATE_UPDATE, ct); if (ret == -1) { switch(errno) { case EEXIST: @@ -146,7 +126,6 @@ void cache_commit(struct cache *c) unsigned int commit_exist = c->commit_exist; unsigned int commit_fail = c->commit_fail; - /* does not require locking: called inside fork() */ hashtable_iterate(c->h, c, do_commit); /* calculate new entries committed */ @@ -187,30 +166,7 @@ static int do_flush(void *data1, void *data2) void cache_flush(struct cache *c) { - lock(); hashtable_iterate(c->h, c, do_flush); hashtable_flush(c->h); c->flush++; - unlock(); -} - -#include "sync.h" -#include "network.h" - -static int do_bulk(void *data1, void *data2) -{ - int ret; - struct us_conntrack *u = data2; - - mcast_build_send_update(u); - - /* keep iterating even if we have found errors */ - return 0; -} - -void cache_bulk(struct cache *c) -{ - lock(); - hashtable_iterate(c->h, NULL, do_bulk); - unlock(); } diff --git a/src/cache_timer.c b/src/cache_timer.c index 213b59a..f3940f3 100644 --- a/src/cache_timer.c +++ b/src/cache_timer.c @@ -27,7 +27,7 @@ static void timeout(struct alarm_list *a, void *data) struct us_conntrack *u = data; debug_ct(u->ct, "expired timeout"); - __cache_del(u->cache, u->ct); + cache_del(u->cache, u->ct); } static void timer_add(struct us_conntrack *u, void *data) diff --git a/src/lock.c b/src/lock.c index cd68baf..e69de29 100644 --- a/src/lock.c +++ b/src/lock.c @@ -1,32 +0,0 @@ -/* - * (C) 2006 by Pablo Neira Ayuso - * - * 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 -#include - -static pthread_mutex_t global_lock = PTHREAD_MUTEX_INITIALIZER; - -void lock() -{ - pthread_mutex_lock(&global_lock); -} - -void unlock() -{ - pthread_mutex_unlock(&global_lock); -} diff --git a/src/main.c b/src/main.c index a039793..007b76e 100644 --- a/src/main.c +++ b/src/main.c @@ -187,6 +187,7 @@ int main(int argc, char *argv[]) case 'F': set_operation_mode(&type, REQUEST, argv); action = FLUSH_MASTER; + break; case 'f': set_operation_mode(&type, REQUEST, argv); action = FLUSH_CACHE; diff --git a/src/mcast.c b/src/mcast.c index 85992fb..6193a59 100644 --- a/src/mcast.c +++ b/src/mcast.c @@ -87,7 +87,6 @@ struct mcast_sock *mcast_server_create(struct mcast_conf *conf) return NULL; } - switch(conf->ipproto) { case AF_INET: if (setsockopt(m->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, diff --git a/src/netlink.c b/src/netlink.c index 5f7cbeb..be5f82e 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -52,19 +52,10 @@ int ignore_conntrack(struct nf_conntrack *ct) return 0; } -static int nl_event_handler(struct nlmsghdr *nlh, - struct nfattr *nfa[], - void *data) +static int event_handler(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data) { - char tmp[1024]; - struct nf_conntrack *ct = (struct nf_conntrack *) tmp; - int type; - - memset(tmp, 0, sizeof(tmp)); - - if ((type = nfct_parse_conntrack(NFCT_T_ALL, nlh, ct)) == NFCT_T_ERROR) - return NFCT_CB_STOP; - /* * Ignore this conntrack: it talks about a * connection that is not interesting for us. @@ -74,13 +65,13 @@ static int nl_event_handler(struct nlmsghdr *nlh, switch(type) { case NFCT_T_NEW: - STATE(mode)->event_new(ct, nlh); + STATE(mode)->event_new(ct); break; case NFCT_T_UPDATE: - STATE(mode)->event_upd(ct, nlh); + STATE(mode)->event_upd(ct); break; case NFCT_T_DESTROY: - if (STATE(mode)->event_dst(ct, nlh)) + if (STATE(mode)->event_dst(ct)) update_traffic_stats(ct); break; default: @@ -88,30 +79,31 @@ static int nl_event_handler(struct nlmsghdr *nlh, break; } - return NFCT_CB_STOP; + return NFCT_CB_CONTINUE; } +#include +#include +#include + int nl_init_event_handler(void) { - struct nfnl_callback cb_events = { - .call = nl_event_handler, - .attr_count = CTA_MAX - }; - - /* open event netlink socket */ - STATE(event) = nfnl_open(); + STATE(event) = nfct_open(CONNTRACK, NFCT_ALL_CT_GROUPS); if (!STATE(event)) return -1; + fcntl(nfct_fd(STATE(event)), F_SETFL, O_NONBLOCK); + /* set up socket buffer size */ if (CONFIG(netlink_buffer_size)) - nfnl_rcvbufsiz(STATE(event), CONFIG(netlink_buffer_size)); + nfnl_rcvbufsiz(nfct_nfnlh(STATE(event)), + CONFIG(netlink_buffer_size)); else { socklen_t socklen = sizeof(unsigned int); unsigned int read_size; /* get current buffer size */ - getsockopt(nfnl_fd(STATE(event)), SOL_SOCKET, + getsockopt(nfct_fd(STATE(event)), SOL_SOCKET, SO_RCVBUF, &read_size, &socklen); CONFIG(netlink_buffer_size) = read_size; @@ -122,40 +114,16 @@ int nl_init_event_handler(void) CONFIG(netlink_buffer_size_max_grown) = CONFIG(netlink_buffer_size); - /* open event subsystem */ - STATE(subsys_event) = nfnl_subsys_open(STATE(event), - NFNL_SUBSYS_CTNETLINK, - IPCTNL_MSG_MAX, - NFCT_ALL_CT_GROUPS); - if (STATE(subsys_event) == NULL) - return -1; - - /* register callback for new and update events */ - nfnl_callback_register(STATE(subsys_event), - IPCTNL_MSG_CT_NEW, - &cb_events); - - /* register callback for delete events */ - nfnl_callback_register(STATE(subsys_event), - IPCTNL_MSG_CT_DELETE, - &cb_events); + /* register callback for events */ + nfct_callback_register(STATE(event), NFCT_T_ALL, event_handler, NULL); return 0; } -static int nl_dump_handler(struct nlmsghdr *nlh, - struct nfattr *nfa[], - void *data) +static int dump_handler(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data) { - char buf[1024]; - struct nf_conntrack *ct = (struct nf_conntrack *) buf; - int type; - - memset(buf, 0, sizeof(buf)); - - if ((type = nfct_parse_conntrack(NFCT_T_ALL, nlh, ct)) == NFCT_T_ERROR) - return NFCT_CB_CONTINUE; - /* * Ignore this conntrack: it talks about a * connection that is not interesting for us. @@ -165,7 +133,7 @@ static int nl_dump_handler(struct nlmsghdr *nlh, switch(type) { case NFCT_T_UPDATE: - STATE(mode)->dump(ct, nlh); + STATE(mode)->dump(ct); break; default: dlog(STATE(log), "received unknown msg from ctnetlink"); @@ -176,30 +144,15 @@ static int nl_dump_handler(struct nlmsghdr *nlh, int nl_init_dump_handler(void) { - struct nfnl_callback cb_dump = { - .call = nl_dump_handler, - .attr_count = CTA_MAX - }; - /* open dump netlink socket */ - STATE(dump) = nfnl_open(); + STATE(dump) = nfct_open(CONNTRACK, 0); if (!STATE(dump)) return -1; - /* open dump subsystem */ - STATE(subsys_dump) = nfnl_subsys_open(STATE(dump), - NFNL_SUBSYS_CTNETLINK, - IPCTNL_MSG_MAX, - 0); - if (STATE(subsys_dump) == NULL) - return -1; - /* register callback for dumped entries */ - nfnl_callback_register(STATE(subsys_dump), - IPCTNL_MSG_CT_NEW, - &cb_dump); + nfct_callback_register(STATE(dump), NFCT_T_ALL, dump_handler, NULL); - if (nl_dump_conntrack_table(STATE(dump), STATE(subsys_dump)) == -1) + if (nl_dump_conntrack_table() == -1) return -1; return 0; @@ -207,7 +160,7 @@ int nl_init_dump_handler(void) static int warned = 0; -void nl_resize_socket_buffer(struct nfnl_handle *h) +void nl_resize_socket_buffer(struct nfct_handle *h) { unsigned int s = CONFIG(netlink_buffer_size) * 2; @@ -228,44 +181,14 @@ void nl_resize_socket_buffer(struct nfnl_handle *h) warned = 1; } - CONFIG(netlink_buffer_size) = nfnl_rcvbufsiz(h, s); + CONFIG(netlink_buffer_size) = nfnl_rcvbufsiz(nfct_nfnlh(h), s); /* notify the sysadmin */ dlog(STATE(log), "netlink socket buffer size has been set to %u bytes", CONFIG(netlink_buffer_size)); } -int nl_dump_conntrack_table(struct nfnl_handle *h, - struct nfnl_subsys_handle *subsys) +int nl_dump_conntrack_table(void) { - struct nfnlhdr req; - - memset(&req, 0, sizeof(req)); - nfct_build_query(subsys, - NFCT_Q_DUMP, - &CONFIG(family), - &req, - sizeof(req)); - - if (nfnl_query(h, &req.nlh) == -1) - return -1; - - return 0; -} - -int nl_flush_master_conntrack_table(void) -{ - struct nfnlhdr req; - - memset(&req, 0, sizeof(req)); - nfct_build_query(STATE(subsys_dump), - NFCT_Q_FLUSH, - &CONFIG(family), - &req, - sizeof(req)); - - if (nfnl_query(STATE(dump), &req.nlh) == -1) - return -1; - - return 0; + return nfct_query(STATE(dump), NFCT_Q_DUMP, &CONFIG(family)); } diff --git a/src/network.c b/src/network.c index 159bdf3..d162839 100644 --- a/src/network.c +++ b/src/network.c @@ -18,190 +18,159 @@ #include "conntrackd.h" #include "network.h" +#include "us-conntrack.h" +#include "sync.h" static unsigned int seq_set, cur_seq; -static int send_netmsg(struct mcast_sock *m, void *data, unsigned int len) +static int __do_send(struct mcast_sock *m, void *data, int len) { struct nethdr *net = data; - if (!seq_set) { - seq_set = 1; - cur_seq = time(NULL); - net->flags |= NET_F_HELLO; - } - - net->flags = htons(net->flags); - net->seq = htonl(cur_seq++); - #undef _TEST_DROP #ifdef _TEST_DROP static int drop = 0; - if (++drop > 10) { + if (++drop >= 10) { + printf("drop sq: %u fl:%u len:%u\n", + ntohl(net->seq), ntohs(net->flags), + ntohs(net->len)); drop = 0; - printf("dropping resend (seq=%u)\n", ntohl(net->seq)); return 0; } #endif + debug("send sq: %u fl:%u len:%u\n", + ntohl(net->seq), ntohs(net->flags), + ntohs(net->len)); + return mcast_send(m, net, len); } -int mcast_send_netmsg(struct mcast_sock *m, void *data) +static int __do_prepare(struct mcast_sock *m, void *data, int len) { - struct nlmsghdr *nlh = data + NETHDR_SIZ; - unsigned int len = nlh->nlmsg_len + NETHDR_SIZ; struct nethdr *net = data; - if (nlh_host2network(nlh) == -1) - return -1; + if (!seq_set) { + seq_set = 1; + cur_seq = time(NULL); + net->flags |= NET_F_HELLO; + } + net->len = len; + net->seq = cur_seq++; + HDR_HOST2NETWORK(net); - return send_netmsg(m, data, len); + return len; } -int mcast_resend_netmsg(struct mcast_sock *m, void *data) +static int __prepare_ctl(struct mcast_sock *m, void *data) { - struct nethdr *net = data; - struct nlmsghdr *nlh = data + NETHDR_SIZ; - unsigned int len; + struct nethdr_ack *nack = (struct nethdr_ack *) data; - net->flags = ntohs(net->flags); + return __do_prepare(m, data, NETHDR_ACK_SIZ); +} - if (net->flags & NET_F_NACK || net->flags & NET_F_ACK) - len = NETHDR_ACK_SIZ; - else - len = ntohl(nlh->nlmsg_len) + NETHDR_SIZ; +static int __prepare_data(struct mcast_sock *m, void *data) +{ + struct nethdr *net = (struct nethdr *) data; + struct netpld *pld = NETHDR_DATA(net); - return send_netmsg(m, data, len); + return __do_prepare(m, data, ntohs(pld->len) + NETPLD_SIZ + NETHDR_SIZ); } -int mcast_send_error(struct mcast_sock *m, void *data) +int prepare_send_netmsg(struct mcast_sock *m, void *data) { - struct nethdr *net = data; - unsigned int len = NETHDR_SIZ; + int ret = 0; + struct nethdr *net = (struct nethdr *) data; - if (net->flags & NET_F_NACK || net->flags & NET_F_ACK) { - struct nethdr_ack *nack = (struct nethdr_ack *) net; - nack->from = htonl(nack->from); - nack->to = htonl(nack->to); - len = NETHDR_ACK_SIZ; - } + if (IS_DATA(net)) + ret = __prepare_data(m, data); + else if (IS_CTL(net)) + ret = __prepare_ctl(m, data); - return send_netmsg(m, data, len); + return ret; } -#include "us-conntrack.h" -#include "sync.h" +static int tx_buflen = 0; +/* XXX: use buffer size of interface MTU */ +static char __tx_buf[1460], *tx_buf = __tx_buf; -static int __build_send(struct us_conntrack *u, int type, int query) +/* return 0 if it is not sent, otherwise return 1 */ +int mcast_buffered_send_netmsg(struct mcast_sock *m, void *data, int len) { - char __net[4096]; - struct nethdr *net = (struct nethdr *) __net; + int ret = 0; + struct nethdr *net = data; - if (!state_helper_verdict(type, u->ct)) - return 0; +retry: + if (tx_buflen + len < sizeof(__tx_buf)) { + memcpy(__tx_buf + tx_buflen, net, len); + tx_buflen += len; + } else { + __do_send(m, tx_buf, tx_buflen); + ret = 1; + tx_buflen = 0; + goto retry; + } - int ret = build_network_msg(query, - STATE(subsys_event), - u->ct, - __net, - sizeof(__net)); + return ret; +} - if (ret == -1) - return -1; +int mcast_buffered_pending_netmsg(struct mcast_sock *m) +{ + int ret; + + if (tx_buflen == 0) + return 0; - mcast_send_netmsg(STATE_SYNC(mcast_client), __net); - if (STATE_SYNC(sync)->send) - STATE_SYNC(sync)->send(type, net, u); + ret = __do_send(m, tx_buf, tx_buflen); + tx_buflen = 0; - return 0; + return ret; } -int mcast_build_send_update(struct us_conntrack *u) +int mcast_send_netmsg(struct mcast_sock *m, void *data) { - return __build_send(u, NFCT_T_UPDATE, NFCT_Q_UPDATE); + int ret; + int len = prepare_send_netmsg(m, data); + + ret = mcast_buffered_send_netmsg(m, data, len); + mcast_buffered_pending_netmsg(m); + + return ret; } -int mcast_build_send_destroy(struct us_conntrack *u) +void build_netmsg(struct nf_conntrack *ct, int query, struct nethdr *net) { - return __build_send(u, NFCT_T_DESTROY, NFCT_Q_DESTROY); + struct netpld *pld = NETHDR_DATA(net); + + build_netpld(ct, pld, query); } -int mcast_recv_netmsg(struct mcast_sock *m, void *data, int len) +int handle_netmsg(struct nethdr *net) { int ret; - struct nethdr *net = data; - struct nlmsghdr *nlh = data + NETHDR_SIZ; - struct nfgenmsg *nfhdr; - - ret = mcast_recv(m, net, len); - if (ret <= 0) - return ret; + struct netpld *pld = NETHDR_DATA(net); /* message too small: no room for the header */ - if (ret < NETHDR_SIZ) + if (ntohs(net->len) < NETHDR_ACK_SIZ) return -1; - if (ntohs(net->flags) & NET_F_HELLO) - STATE_SYNC(last_seq_recv) = ntohl(net->seq) - 1; + HDR_NETWORK2HOST(net); - if (ntohs(net->flags) & NET_F_NACK || ntohs(net->flags) & NET_F_ACK) { - struct nethdr_ack *nack = (struct nethdr_ack *) net; + if (IS_HELLO(net)) + STATE_SYNC(last_seq_recv) = net->seq - 1; - /* message too small: no room for the header */ - if (ret < NETHDR_ACK_SIZ) - return -1; - - /* host byte order conversion */ - net->flags = ntohs(net->flags); - net->seq = ntohl(net->seq); - - /* acknowledgement conversion */ - nack->from = ntohl(nack->from); - nack->to = ntohl(nack->to); - - return ret; - } - - if (ntohs(net->flags) & NET_F_RESYNC) { - /* host byte order conversion */ - net->flags = ntohs(net->flags); - net->seq = ntohl(net->seq); - - return ret; - } + if (IS_CTL(net)) + return 0; /* information received is too small */ - if (ret < NLMSG_SPACE(sizeof(struct nfgenmsg))) - return -1; - - /* information received and message length does not match */ - if (ret != ntohl(nlh->nlmsg_len) + NETHDR_SIZ) - return -1; - - /* this message does not come from ctnetlink */ - if (NFNL_SUBSYS_ID(ntohs(nlh->nlmsg_type)) != NFNL_SUBSYS_CTNETLINK) + if (net->len < sizeof(struct netpld)) return -1; - nfhdr = NLMSG_DATA(nlh); - - /* only AF_INET and AF_INET6 are supported */ - if (nfhdr->nfgen_family != AF_INET && - nfhdr->nfgen_family != AF_INET6) - return -1; - - /* only process message coming from nfnetlink v0 */ - if (nfhdr->version != NFNETLINK_V0) - return -1; - - /* host byte order conversion */ - net->flags = ntohs(net->flags); - net->seq = ntohl(net->seq); - - if (nlh_network2host(nlh) == -1) + /* size mismatch! */ + if (net->len < ntohs(pld->len) + NETHDR_SIZ) return -1; - return ret; + return 0; } int mcast_track_seq(u_int32_t seq, u_int32_t *exp_seq) @@ -238,30 +207,3 @@ out: return ret; } - -int build_network_msg(const int msg_type, - struct nfnl_subsys_handle *ssh, - struct nf_conntrack *ct, - void *buffer, - unsigned int size) -{ - memset(buffer, 0, size); - buffer += NETHDR_SIZ; - size -= NETHDR_SIZ; - return nfct_build_query(ssh, msg_type, ct, buffer, size); -} - -unsigned int parse_network_msg(struct nf_conntrack *ct, - const struct nlmsghdr *nlh) -{ - /* - * The parsing of netlink messages going through network is - * similar to the one that is done for messages coming from - * kernel, therefore do not replicate more code and use the - * function provided in the libraries. - * - * Yup, this is a hack 8) - */ - return nfct_parse_conntrack(NFCT_T_ALL, nlh, ct); -} - diff --git a/src/parse.c b/src/parse.c new file mode 100644 index 0000000..81b70c4 --- /dev/null +++ b/src/parse.c @@ -0,0 +1,76 @@ +/* + * (C) 2006-2007 by Pablo Neira Ayuso + * + * 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 +#include +#include "network.h" + +static int parse_u8(struct nf_conntrack *ct, int attr, void *data) +{ + u_int8_t *value = (u_int8_t *) data; + nfct_set_attr_u8(ct, attr, *value); +} + +static int parse_u16(struct nf_conntrack *ct, int attr, void *data) +{ + u_int16_t *value = (u_int16_t *) data; + nfct_set_attr_u16(ct, attr, ntohs(*value)); +} + +static int parse_u32(struct nf_conntrack *ct, int attr, void *data) +{ + u_int32_t *value = (u_int32_t *) data; + nfct_set_attr_u32(ct, attr, ntohl(*value)); +} + +typedef int (*parse)(struct nf_conntrack *ct, int attr, void *data); + +parse h[ATTR_MAX] = { + [ATTR_IPV4_SRC] = parse_u32, + [ATTR_IPV4_DST] = parse_u32, + [ATTR_L3PROTO] = parse_u8, + [ATTR_PORT_SRC] = parse_u16, + [ATTR_PORT_DST] = parse_u16, + [ATTR_L4PROTO] = parse_u8, + [ATTR_TCP_STATE] = parse_u8, + [ATTR_SNAT_IPV4] = parse_u32, + [ATTR_DNAT_IPV4] = parse_u32, + [ATTR_SNAT_PORT] = parse_u16, + [ATTR_DNAT_PORT] = parse_u16, + [ATTR_TIMEOUT] = parse_u32, + [ATTR_MARK] = parse_u32, + [ATTR_STATUS] = parse_u32, +}; + +void parse_netpld(struct nf_conntrack *ct, struct netpld *pld, int *query) +{ + int len; + struct netattr *attr; + + PLD_NETWORK2HOST(pld); + len = pld->len; + attr = PLD_DATA(pld); + + while (len > 0) { + ATTR_NETWORK2HOST(attr); + h[attr->nta_attr](ct, attr->nta_attr, NTA_DATA(attr)); + attr = NTA_NEXT(attr, len); + } + + *query = pld->query; +} diff --git a/src/proxy.c b/src/proxy.c deleted file mode 100644 index b9bb04e..0000000 --- a/src/proxy.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * (C) 2006 by Pablo Neira Ayuso - * - * 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 -#include - -#if 0 -#define dprintf printf -#else -#define dprintf -#endif - -int nlh_payload_host2network(struct nfattr *nfa, int len) -{ - struct nfattr *__nfa; - - while (NFA_OK(nfa, len)) { - - dprintf("type=%d nfalen=%d len=%d [%s]\n", - nfa->nfa_type & 0x7fff, - nfa->nfa_len, len, - nfa->nfa_type & NFNL_NFA_NEST ? "NEST":""); - - if (nfa->nfa_type & NFNL_NFA_NEST) { - if (NFA_PAYLOAD(nfa) > len) - return -1; - - if (nlh_payload_host2network(NFA_DATA(nfa), - NFA_PAYLOAD(nfa)) == -1) - return -1; - } - - __nfa = NFA_NEXT(nfa, len); - - nfa->nfa_type = htons(nfa->nfa_type); - nfa->nfa_len = htons(nfa->nfa_len); - - nfa = __nfa; - } - return 0; -} - -int nlh_host2network(struct nlmsghdr *nlh) -{ - struct nfgenmsg *nfhdr = NLMSG_DATA(nlh); - struct nfattr *cda[CTA_MAX]; - unsigned int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); - unsigned int len = nlh->nlmsg_len - NLMSG_ALIGN(min_len); - - nlh->nlmsg_len = htonl(nlh->nlmsg_len); - nlh->nlmsg_type = htons(nlh->nlmsg_type); - nlh->nlmsg_flags = htons(nlh->nlmsg_flags); - nlh->nlmsg_seq = htonl(nlh->nlmsg_seq); - nlh->nlmsg_pid = htonl(nlh->nlmsg_pid); - - nfhdr->res_id = htons(nfhdr->res_id); - - return nlh_payload_host2network(NFM_NFA(NLMSG_DATA(nlh)), len); -} - -int nlh_payload_network2host(struct nfattr *nfa, int len) -{ - nfa->nfa_type = ntohs(nfa->nfa_type); - nfa->nfa_len = ntohs(nfa->nfa_len); - - while(NFA_OK(nfa, len)) { - - dprintf("type=%d nfalen=%d len=%d [%s]\n", - nfa->nfa_type & 0x7fff, - nfa->nfa_len, len, - nfa->nfa_type & NFNL_NFA_NEST ? "NEST":""); - - if (nfa->nfa_type & NFNL_NFA_NEST) { - if (NFA_PAYLOAD(nfa) > len) - return -1; - - if (nlh_payload_network2host(NFA_DATA(nfa), - NFA_PAYLOAD(nfa)) == -1) - return -1; - } - - nfa = NFA_NEXT(nfa,len); - - if (len < NFA_LENGTH(0)) - break; - - nfa->nfa_type = ntohs(nfa->nfa_type); - nfa->nfa_len = ntohs(nfa->nfa_len); - } - return 0; -} - -int nlh_network2host(struct nlmsghdr *nlh) -{ - struct nfgenmsg *nfhdr = NLMSG_DATA(nlh); - struct nfattr *cda[CTA_MAX]; - unsigned int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); - unsigned int len = ntohl(nlh->nlmsg_len) - NLMSG_ALIGN(min_len); - - nlh->nlmsg_len = ntohl(nlh->nlmsg_len); - nlh->nlmsg_type = ntohs(nlh->nlmsg_type); - nlh->nlmsg_flags = ntohs(nlh->nlmsg_flags); - nlh->nlmsg_seq = ntohl(nlh->nlmsg_seq); - nlh->nlmsg_pid = ntohl(nlh->nlmsg_pid); - - nfhdr->res_id = ntohs(nfhdr->res_id); - - return nlh_payload_network2host(NFM_NFA(NLMSG_DATA(nlh)), len); -} diff --git a/src/run.c b/src/run.c index 0173c9f..644f82e 100644 --- a/src/run.c +++ b/src/run.c @@ -24,20 +24,21 @@ #include "us-conntrack.h" #include #include +#include +#include "timer.h" void killer(int foo) { /* no signals while handling signals */ sigprocmask(SIG_BLOCK, &STATE(block), NULL); - nfnl_subsys_close(STATE(subsys_event)); - nfnl_subsys_close(STATE(subsys_dump)); - nfnl_close(STATE(event)); - nfnl_close(STATE(dump)); + nfct_close(STATE(event)); + nfct_close(STATE(dump)); ignore_pool_destroy(STATE(ignore_pool)); local_server_destroy(STATE(local)); STATE(mode)->kill(); + destroy_alarm_scheduler(); unlink(CONFIG(lockfile)); dlog(STATE(log), "------- shutdown received ----"); close_log(STATE(log)); @@ -69,12 +70,16 @@ void local_handler(int fd, void *data) switch(type) { case FLUSH_MASTER: - dlog(STATE(log), "[REQ] flushing master table"); - nl_flush_master_conntrack_table(); + dlog(STATE(log), "[DEPRECATED] `conntrackd -F' is deprecated. " + "Use conntrack -F instead."); + if (fork() == 0) { + execlp("conntrack", "conntrack", "-F", NULL); + exit(EXIT_SUCCESS); + } return; case RESYNC_MASTER: dlog(STATE(log), "[REQ] resync with master table"); - nl_dump_conntrack_table(STATE(dump), STATE(subsys_dump)); + nl_dump_conntrack_table(); return; } @@ -104,6 +109,11 @@ int init(int mode) return -1; } + if (init_alarm_scheduler() == -1) { + dlog(STATE(log), "[FAIL] can't initialize alarm scheduler"); + return -1; + } + /* local UNIX socket */ STATE(local) = local_server_create(&CONFIG(local)); if (!STATE(local)) { @@ -147,22 +157,20 @@ int init(int mode) return 0; } -#define POLL_NSECS 1 - -static void __run(void) +static void __run(long credit, int step) { int max, ret; fd_set readfds; struct timeval tv = { - .tv_sec = POLL_NSECS, - .tv_usec = 0 + .tv_sec = 0, + .tv_usec = credit, }; FD_ZERO(&readfds); FD_SET(STATE(local), &readfds); - FD_SET(nfnl_fd(STATE(event)), &readfds); + FD_SET(nfct_fd(STATE(event)), &readfds); - max = MAX(STATE(local), nfnl_fd(STATE(event))); + max = MAX(STATE(local), nfct_fd(STATE(event))); if (STATE(mode)->add_fds_to_set) max = MAX(max, STATE(mode)->add_fds_to_set(&readfds)); @@ -185,8 +193,8 @@ static void __run(void) do_local_server_step(STATE(local), NULL, local_handler); /* conntrack event has happened */ - if (FD_ISSET(nfnl_fd(STATE(event)), &readfds)) { - ret = nfnl_catch(STATE(event)); + if (FD_ISSET(nfct_fd(STATE(event)), &readfds)) { + while ((ret = nfct_catch(STATE(event))) != -1); if (ret == -1) { switch(errno) { case ENOBUFS: @@ -197,6 +205,7 @@ static void __run(void) * size and resync with master conntrack table. */ nl_resize_socket_buffer(STATE(event)); + /* XXX: schedule overrun call via alarm */ STATE(mode)->overrun(); break; case ENOENT: @@ -206,6 +215,8 @@ static void __run(void) * interested in. Just ignore it. */ break; + case EAGAIN: + break; default: dlog(STATE(log), "event catch says: %s", strerror(errno)); @@ -214,14 +225,35 @@ static void __run(void) } } - if (STATE(mode)->step) - STATE(mode)->step(&readfds); + if (STATE(mode)->run) + STATE(mode)->run(&readfds, step); sigprocmask(SIG_UNBLOCK, &STATE(block), NULL); } void run(void) { - while(1) - __run(); + int step = 0; + struct timer timer; + + timer_init(&timer); + + while(1) { + timer_start(&timer); + __run(GET_CREDITS(timer), step); + timer_stop(&timer); + + if (timer_adjust_credit(&timer)) { + timer_start(&timer); + sigprocmask(SIG_BLOCK, &STATE(block), NULL); + do_alarm_run(step); + sigprocmask(SIG_UNBLOCK, &STATE(block), NULL); + timer_stop(&timer); + + if (timer_adjust_credit(&timer)) + dlog(STATE(log), "alarm run takes too long!"); + + step = (step + 1) < STEPS_PER_SECONDS ? step + 1 : 0; + } + } } diff --git a/src/state_helper.c b/src/state_helper.c index 81b0d09..eba9d8f 100644 --- a/src/state_helper.c +++ b/src/state_helper.c @@ -25,7 +25,7 @@ int state_helper_verdict(int type, struct nf_conntrack *ct) { u_int8_t l4proto; - if (type == NFCT_T_DESTROY) + if (type == NFCT_Q_DESTROY) return ST_H_REPLICATE; l4proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO); diff --git a/src/stats-mode.c b/src/stats-mode.c index 92794cd..65bab1b 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -86,7 +86,7 @@ static int local_handler_stats(int fd, int type, void *data) return ret; } -static void dump_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) +static void dump_stats(struct nf_conntrack *ct) { if (cache_update_force(STATE_STATS(cache), ct)) debug_ct(ct, "resync entry"); @@ -137,7 +137,7 @@ static void overrun_stats() nfct_close(h); } -static void event_new_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) +static void event_new_stats(struct nf_conntrack *ct) { if (cache_add(STATE_STATS(cache), ct)) { debug_ct(ct, "cache new"); @@ -150,7 +150,7 @@ static void event_new_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) } } -static void event_update_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) +static void event_update_stats(struct nf_conntrack *ct) { if (!cache_update_force(STATE_STATS(cache), ct)) { debug_ct(ct, "can't update"); @@ -159,7 +159,7 @@ static void event_update_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) debug_ct(ct, "update"); } -static int event_destroy_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) +static int event_destroy_stats(struct nf_conntrack *ct) { if (cache_del(STATE_STATS(cache), ct)) { debug_ct(ct, "cache destroy"); @@ -173,7 +173,7 @@ static int event_destroy_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) struct ct_mode stats_mode = { .init = init_stats, .add_fds_to_set = NULL, - .step = NULL, + .run = NULL, .local = local_handler_stats, .kill = kill_stats, .dump = dump_stats, diff --git a/src/sync-mode.c b/src/sync-mode.c index 38ab016..f30cb95 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -27,43 +27,27 @@ #include #include "sync.h" #include "network.h" +#include "buffer.h" +#include "debug.h" -/* handler for multicast messages received */ -static void mcast_handler() +static void do_mcast_handler_step(struct nethdr *net) { - int ret; - unsigned int type; - char __net[4096]; - struct nethdr *net = (struct nethdr *) __net; - struct nlmsghdr *nlh = (struct nlmsghdr *) (__net + NETHDR_SIZ); + unsigned int query; + struct netpld *pld = NETHDR_DATA(net); char __ct[nfct_maxsize()]; struct nf_conntrack *ct = (struct nf_conntrack *) __ct; struct us_conntrack *u = NULL; - ret = mcast_recv_netmsg(STATE_SYNC(mcast_server), net, sizeof(__net)); - if (ret <= 0) { - STATE(malformed)++; - return; - } - if (STATE_SYNC(sync)->recv(net)) return; memset(ct, 0, sizeof(__ct)); - if ((type = parse_network_msg(ct, nlh)) == NFCT_T_ERROR) { - STATE(malformed)++; - return; - } + /* XXX: check for malformed */ + parse_netpld(ct, pld, &query); - nfct_attr_unset(ct, ATTR_TIMEOUT); - nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES); - nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS); - nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES); - nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); - - switch(type) { - case NFCT_T_NEW: + switch(query) { + case NFCT_Q_CREATE: retry: if ((u = cache_add(STATE_SYNC(external), ct))) { debug_ct(u->ct, "external new"); @@ -80,24 +64,57 @@ retry: debug_ct(ct, "can't add"); } break; - case NFCT_T_UPDATE: + case NFCT_Q_UPDATE: if ((u = cache_update_force(STATE_SYNC(external), ct))) { debug_ct(u->ct, "external update"); } else debug_ct(ct, "can't update"); break; - case NFCT_T_DESTROY: + case NFCT_Q_DESTROY: if (cache_del(STATE_SYNC(external), ct)) debug_ct(ct, "external destroy"); else debug_ct(ct, "can't destroy"); break; default: - dlog(STATE(log), "mcast received unknown msg type %d\n", type); + dlog(STATE(log), "mcast received unknown query %d\n", query); break; } } +/* handler for multicast messages received */ +static void mcast_handler() +{ + int numbytes, remain; + char __net[4096], *ptr = __net; + + numbytes = mcast_recv(STATE_SYNC(mcast_server), __net, sizeof(__net)); + if (numbytes <= 0) + return; + + remain = numbytes; + while (remain > 0) { + struct nethdr *net = (struct nethdr *) ptr; + + if (ntohs(net->len) > remain) { + dlog(STATE(log), "fragmented messages"); + break; + } + + debug("recv sq: %u fl:%u len:%u (rem:%d)\n", + ntohl(net->seq), ntohs(net->flags), + ntohs(net->len), remain); + + if (handle_netmsg(net) == -1) { + STATE(malformed)++; + return; + } + do_mcast_handler_step(net); + ptr += net->len; + remain -= net->len; + } +} + static int init_sync(void) { int ret; @@ -159,11 +176,6 @@ static int init_sync(void) /* initialization of multicast sequence generation */ STATE_SYNC(last_seq_sent) = time(NULL); - if (create_alarm_thread() == -1) { - dlog(STATE(log), "[FAIL] can't initialize alarm thread"); - return -1; - } - return 0; } @@ -174,11 +186,17 @@ static int add_fds_to_set_sync(fd_set *readfds) return STATE_SYNC(mcast_server->fd); } -static void step_sync(fd_set *readfds) +static void run_sync(fd_set *readfds, int step) { /* multicast packet has been received */ if (FD_ISSET(STATE_SYNC(mcast_server->fd), readfds)) mcast_handler(); + + if (STATE_SYNC(sync)->run) + STATE_SYNC(sync)->run(step); + + /* flush pending messages */ + mcast_buffered_pending_netmsg(STATE_SYNC(mcast_client)); } static void kill_sync() @@ -189,8 +207,6 @@ static void kill_sync() mcast_server_destroy(STATE_SYNC(mcast_server)); mcast_client_destroy(STATE_SYNC(mcast_client)); - destroy_alarm_thread(); - if (STATE_SYNC(sync)->kill) STATE_SYNC(sync)->kill(); } @@ -267,10 +283,6 @@ static int local_handler_sync(int fd, int type, void *data) STATE_SYNC(mcast_server)); dump_stats_sync(fd); break; - case SEND_BULK: - dlog(STATE(log), "[REQ] sending bulk update"); - cache_bulk(STATE_SYNC(internal)); - break; default: if (STATE_SYNC(sync)->local) ret = STATE_SYNC(sync)->local(fd, type, data); @@ -280,7 +292,7 @@ static int local_handler_sync(int fd, int type, void *data) return ret; } -static void dump_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) +static void dump_sync(struct nf_conntrack *ct) { /* This is required by kernels < 2.6.20 */ nfct_attr_unset(ct, ATTR_TIMEOUT); @@ -294,23 +306,21 @@ static void dump_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) debug_ct(ct, "resync"); } -static void mcast_send_sync(struct nlmsghdr *nlh, - struct us_conntrack *u, +static void mcast_send_sync(struct us_conntrack *u, struct nf_conntrack *ct, - int type) + int query) { - char __net[4096]; - struct nethdr *net = (struct nethdr *) __net; - - memset(__net, 0, sizeof(__net)); + int len; + struct nethdr *net; - if (!state_helper_verdict(type, ct)) + if (!state_helper_verdict(query, ct)) return; - memcpy(__net + NETHDR_SIZ, nlh, nlh->nlmsg_len); - mcast_send_netmsg(STATE_SYNC(mcast_client), net); + net = BUILD_NETMSG(ct, query); + len = prepare_send_netmsg(STATE_SYNC(mcast_client), net); + mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), net, len); if (STATE_SYNC(sync)->send) - STATE_SYNC(sync)->send(type, net, u); + STATE_SYNC(sync)->send(net, u); } static int overrun_cb(enum nf_conntrack_msg_type type, @@ -332,8 +342,16 @@ static int overrun_cb(enum nf_conntrack_msg_type type, if (!cache_test(STATE_SYNC(internal), ct)) { if ((u = cache_update_force(STATE_SYNC(internal), ct))) { + int len; + debug_ct(u->ct, "overrun resync"); - mcast_build_send_update(u); + + struct nethdr *net = BUILD_NETMSG(u->ct, NFCT_Q_UPDATE); + len = prepare_send_netmsg(STATE_SYNC(mcast_client),net); + mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), + net, len); + if (STATE_SYNC(sync)->send) + STATE_SYNC(sync)->send(net, u); } } @@ -348,9 +366,17 @@ static int overrun_purge_step(void *data1, void *data2) ret = nfct_query(h, NFCT_Q_GET, u->ct); if (ret == -1 && errno == ENOENT) { + int len; + struct nethdr *net = BUILD_NETMSG(u->ct, NFCT_Q_DESTROY); + debug_ct(u->ct, "overrun purge resync"); - mcast_build_send_destroy(u); - __cache_del(STATE_SYNC(internal), u->ct); + + len = prepare_send_netmsg(STATE_SYNC(mcast_client), net); + mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), net, len); + if (STATE_SYNC(sync)->send) + STATE_SYNC(sync)->send(net, u); + + cache_del(STATE_SYNC(internal), u->ct); } return 0; @@ -382,7 +408,7 @@ static void overrun_sync() nfct_close(h); } -static void event_new_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) +static void event_new_sync(struct nf_conntrack *ct) { struct us_conntrack *u; @@ -394,12 +420,12 @@ static void event_new_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) nfct_attr_unset(ct, ATTR_TIMEOUT); retry: if ((u = cache_add(STATE_SYNC(internal), ct))) { - mcast_send_sync(nlh, u, ct, NFCT_T_NEW); + mcast_send_sync(u, ct, NFCT_Q_CREATE); debug_ct(u->ct, "internal new"); } else { if (errno == EEXIST) { cache_del(STATE_SYNC(internal), ct); - mcast_send_sync(nlh, NULL, ct, NFCT_T_DESTROY); + mcast_send_sync(NULL, ct, NFCT_Q_DESTROY); goto retry; } @@ -409,7 +435,7 @@ retry: } } -static void event_update_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) +static void event_update_sync(struct nf_conntrack *ct) { struct us_conntrack *u; @@ -420,15 +446,15 @@ static void event_update_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) return; } debug_ct(u->ct, "internal update"); - mcast_send_sync(nlh, u, ct, NFCT_T_UPDATE); + mcast_send_sync(u, ct, NFCT_Q_UPDATE); } -static int event_destroy_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) +static int event_destroy_sync(struct nf_conntrack *ct) { nfct_attr_unset(ct, ATTR_TIMEOUT); if (cache_del(STATE_SYNC(internal), ct)) { - mcast_send_sync(nlh, NULL, ct, NFCT_T_DESTROY); + mcast_send_sync(NULL, ct, NFCT_Q_DESTROY); debug_ct(ct, "internal destroy"); } else debug_ct(ct, "can't destroy"); @@ -437,7 +463,7 @@ static int event_destroy_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) struct ct_mode sync_mode = { .init = init_sync, .add_fds_to_set = add_fds_to_set_sync, - .step = step_sync, + .run = run_sync, .local = local_handler_sync, .kill = kill_sync, .dump = dump_sync, diff --git a/src/sync-nack.c b/src/sync-nack.c index 20ad1f4..dbda0a7 100644 --- a/src/sync-nack.c +++ b/src/sync-nack.c @@ -24,6 +24,7 @@ #include "buffer.h" #include "debug.h" #include "network.h" +#include "alarm.h" #include #include @@ -33,28 +34,34 @@ #define dp #endif -static LIST_HEAD(queue); +static LIST_HEAD(rs_list); +static LIST_HEAD(tx_list); +static unsigned int tx_list_len; +static struct buffer *rs_queue; +static struct buffer *tx_queue; struct cache_nack { - struct list_head head; + struct list_head rs_list; + struct list_head tx_list; u_int32_t seq; }; static void cache_nack_add(struct us_conntrack *u, void *data) { struct cache_nack *cn = data; - INIT_LIST_HEAD(&cn->head); + INIT_LIST_HEAD(&cn->rs_list); + INIT_LIST_HEAD(&cn->tx_list); } static void cache_nack_del(struct us_conntrack *u, void *data) { struct cache_nack *cn = data; - if (cn->head.next == &cn->head && - cn->head.prev == &cn->head) + if (cn->rs_list.next == &cn->rs_list && + cn->rs_list.prev == &cn->rs_list) return; - list_del(&cn->head); + list_del(&cn->rs_list); } static struct cache_extra cache_nack_extra = { @@ -65,19 +72,31 @@ static struct cache_extra cache_nack_extra = { static int nack_init() { - STATE_SYNC(buffer) = buffer_create(CONFIG(resend_buffer_size)); - if (STATE_SYNC(buffer) == NULL) + tx_queue = buffer_create(CONFIG(resend_buffer_size)); + if (tx_queue == NULL) { + dlog(STATE(log), "[FAIL] cannot create tx buffer"); return -1; + } + + rs_queue = buffer_create(CONFIG(resend_buffer_size)); + if (rs_queue == NULL) { + dlog(STATE(log), "[FAIL] cannot create rs buffer"); + return -1; + } + + INIT_LIST_HEAD(&tx_list); + INIT_LIST_HEAD(&rs_list); return 0; } static void nack_kill() { - buffer_destroy(STATE_SYNC(buffer)); + buffer_destroy(rs_queue); + buffer_destroy(tx_queue); } -static void mcast_send_control(u_int32_t flags, u_int32_t from, u_int32_t to) +static void tx_queue_add_ctlmsg(u_int32_t flags, u_int32_t from, u_int32_t to) { struct nethdr_ack ack = { .flags = flags, @@ -85,8 +104,19 @@ static void mcast_send_control(u_int32_t flags, u_int32_t from, u_int32_t to) .to = to, }; - mcast_send_error(STATE_SYNC(mcast_client), &ack); - buffer_add(STATE_SYNC(buffer), &ack, NETHDR_ACK_SIZ); + buffer_add(tx_queue, &ack, NETHDR_ACK_SIZ); +} + +static int do_cache_to_tx(void *data1, void *data2) +{ + struct us_conntrack *u = data2; + struct cache_nack *cn = cache_get_extra(STATE_SYNC(internal), u); + + /* add to tx list */ + list_add(&cn->tx_list, &tx_list); + tx_list_len++; + + return 0; } static int nack_local(int fd, int type, void *data) @@ -94,85 +124,78 @@ static int nack_local(int fd, int type, void *data) int ret = 1; switch(type) { - case REQUEST_DUMP: - mcast_send_control(NET_F_RESYNC, 0, 0); - dlog(STATE(log), "[REQ] request resync"); - break; - default: - ret = 0; - break; + case REQUEST_DUMP: + dlog(STATE(log), "[REQ] request resync"); + tx_queue_add_ctlmsg(NET_F_RESYNC, 0, 0); + break; + case SEND_BULK: + dlog(STATE(log), "[REQ] sending bulk update"); + cache_iterate(STATE_SYNC(internal), NULL, do_cache_to_tx); + break; + default: + ret = 0; + break; } return ret; } -static int buffer_compare(void *data1, void *data2) +static int rs_queue_to_tx(void *data1, void *data2) { struct nethdr *net = data1; struct nethdr_ack *nack = data2; - struct nlmsghdr *nlh = data1 + NETHDR_SIZ; - - unsigned old_seq = ntohl(net->seq); - if (between(ntohl(net->seq), nack->from, nack->to)) { - if (mcast_resend_netmsg(STATE_SYNC(mcast_client), net)) - dp("resend destroy (old seq=%u) (seq=%u)\n", - old_seq, ntohl(net->seq)); + if (between(net->seq, nack->from, nack->to)) { + dp("rs_queue_to_tx sq: %u fl:%u len:%u\n", + net->seq, net->flags, net->len); + buffer_add(tx_queue, net, net->len); } return 0; } -static int buffer_remove(void *data1, void *data2) +static int rs_queue_empty(void *data1, void *data2) { struct nethdr *net = data1; struct nethdr_ack *h = data2; - if (between(ntohl(net->seq), h->from, h->to)) { - dp("remove from buffer (seq=%u)\n", ntohl(net->seq)); - __buffer_del(STATE_SYNC(buffer), data1); + if (between(net->seq, h->from, h->to)) { + dp("remove from buffer (seq=%u)\n", net->seq); + buffer_del(rs_queue, data1); } return 0; } -static void queue_resend(struct cache *c, unsigned int from, unsigned int to) +static void rs_list_to_tx(struct cache *c, unsigned int from, unsigned int to) { struct list_head *n; struct us_conntrack *u; - list_for_each(n, &queue) { + list_for_each(n, &rs_list) { struct cache_nack *cn = (struct cache_nack *) n; struct us_conntrack *u; u = cache_get_conntrack(STATE_SYNC(internal), cn); - if (between(cn->seq, from, to)) { - debug_ct(u->ct, "resend nack"); - dp("resending nack'ed (oldseq=%u) ", cn->seq); - - if (mcast_build_send_update(u) == -1) - continue; - - dp("(newseq=%u)\n", cn->seq); + dp("resending nack'ed (oldseq=%u)\n", cn->seq); + list_add(&cn->tx_list, &tx_list); + tx_list_len++; } } } -static void queue_empty(struct cache *c, unsigned int from, unsigned int to) +static void rs_list_empty(struct cache *c, unsigned int from, unsigned int to) { struct list_head *n, *tmp; - struct us_conntrack *u; - dp("ACK from %u to %u\n", from, to); - list_for_each_safe(n, tmp, &queue) { + list_for_each_safe(n, tmp, &rs_list) { struct cache_nack *cn = (struct cache_nack *) n; + struct us_conntrack *u; u = cache_get_conntrack(STATE_SYNC(internal), cn); if (between(cn->seq, from, to)) { - dp("remove %u\n", cn->seq); - debug_ct(u->ct, "ack received: empty queue"); dp("queue: deleting from queue (seq=%u)\n", cn->seq); - list_del(&cn->head); - INIT_LIST_HEAD(&cn->head); + list_del(&cn->rs_list); + INIT_LIST_HEAD(&cn->rs_list); } } } @@ -187,73 +210,149 @@ static int nack_recv(const struct nethdr *net) if (!mcast_track_seq(net->seq, &exp_seq)) { dp("OOS: sending nack (seq=%u)\n", exp_seq); - mcast_send_control(NET_F_NACK, exp_seq, net->seq - 1); + tx_queue_add_ctlmsg(NET_F_NACK, exp_seq, net->seq-1); window = CONFIG(window_size); } else { /* received a window, send an acknowledgement */ if (--window == 0) { dp("sending ack (seq=%u)\n", net->seq); - mcast_send_control(NET_F_ACK, - net->seq - CONFIG(window_size), - net->seq); + tx_queue_add_ctlmsg(NET_F_ACK, + net->seq - CONFIG(window_size), + net->seq); } } - if (net->flags & NET_F_NACK) { + if (IS_NACK(net)) { struct nethdr_ack *nack = (struct nethdr_ack *) net; dp("NACK: from seq=%u to seq=%u\n", nack->from, nack->to); - queue_resend(STATE_SYNC(internal), nack->from, nack->to); - buffer_iterate(STATE_SYNC(buffer), nack, buffer_compare); + rs_list_to_tx(STATE_SYNC(internal), nack->from, nack->to); + buffer_iterate(rs_queue, nack, rs_queue_to_tx); return 1; - } else if (net->flags & NET_F_RESYNC) { + } else if (IS_RESYNC(net)) { dp("RESYNC ALL\n"); - cache_bulk(STATE_SYNC(internal)); + cache_iterate(STATE_SYNC(internal), NULL, do_cache_to_tx); return 1; - } else if (net->flags & NET_F_ACK) { + } else if (IS_ACK(net)) { struct nethdr_ack *h = (struct nethdr_ack *) net; dp("ACK: from seq=%u to seq=%u\n", h->from, h->to); - queue_empty(STATE_SYNC(internal), h->from, h->to); - buffer_iterate(STATE_SYNC(buffer), h, buffer_remove); + rs_list_empty(STATE_SYNC(internal), h->from, h->to); + buffer_iterate(rs_queue, h, rs_queue_empty); + return 1; + } else if (IS_ALIVE(net)) return 1; - } return 0; } -static void nack_send(int type, - const struct nethdr *net, - struct us_conntrack *u) +static void nack_send(struct nethdr *net, struct us_conntrack *u) { - int size = NETHDR_SIZ; - struct nlmsghdr *nlh = (struct nlmsghdr *) ((void *) net + size); + struct netpld *pld = NETHDR_DATA(net); struct cache_nack *cn; - - size += ntohl(nlh->nlmsg_len); - switch(type) { - case NFCT_T_NEW: - case NFCT_T_UPDATE: + HDR_NETWORK2HOST(net); + + switch(ntohs(pld->query)) { + case NFCT_Q_CREATE: + case NFCT_Q_UPDATE: cn = (struct cache_nack *) cache_get_extra(STATE_SYNC(internal), u); - if (cn->head.next == &cn->head && - cn->head.prev == &cn->head) + if (cn->rs_list.next == &cn->rs_list && + cn->rs_list.prev == &cn->rs_list) goto insert; - list_del(&cn->head); - INIT_LIST_HEAD(&cn->head); + list_del(&cn->rs_list); + INIT_LIST_HEAD(&cn->rs_list); insert: - cn->seq = ntohl(net->seq); - list_add(&cn->head, &queue); + cn->seq = net->seq; + list_add(&cn->rs_list, &rs_list); break; - case NFCT_T_DESTROY: - buffer_add(STATE_SYNC(buffer), net, size); + case NFCT_Q_DESTROY: + buffer_add(rs_queue, net, net->len); break; } } +static int tx_queue_xmit(void *data1, void *data2) +{ + struct nethdr *net = data1; + int len = prepare_send_netmsg(STATE_SYNC(mcast_client), net); + + dp("tx_queue sq: %u fl:%u len:%u\n", + ntohl(net->seq), ntohs(net->flags), ntohs(net->len)); + + mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), net, len); + HDR_NETWORK2HOST(net); + + if (IS_DATA(net) || IS_ACK(net) || IS_NACK(net)) { + dp("-> back_to_tx_queue sq: %u fl:%u len:%u\n", + net->seq, net->flags, net->len); + buffer_add(rs_queue, net, net->len); + } + buffer_del(tx_queue, net); + + return 0; +} + +static int tx_list_xmit(struct list_head *i, struct us_conntrack *u) +{ + int ret; + struct nethdr *net = BUILD_NETMSG(u->ct, NFCT_Q_UPDATE); + int len = prepare_send_netmsg(STATE_SYNC(mcast_client), net); + + dp("tx_list sq: %u fl:%u len:%u\n", + ntohl(net->seq), ntohs(net->flags), + ntohs(net->len)); + + list_del(i); + INIT_LIST_HEAD(i); + tx_list_len--; + + ret = mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), net, len); + if (STATE_SYNC(sync)->send) + STATE_SYNC(sync)->send(net, u); + + return ret; +} + +static struct alarm_list alive_alarm; + +static void do_alive_alarm(struct alarm_list *a, void *data) +{ + del_alarm(a); + tx_queue_add_ctlmsg(NET_F_ALIVE, 0, 0); +} + +static void nack_run(int step) +{ + struct list_head *i, *tmp; + + /* send messages in the tx_queue */ + buffer_iterate(tx_queue, NULL, tx_queue_xmit); + + /* send conntracks in the tx_list */ + list_for_each_safe(i, tmp, &tx_list) { + struct cache_nack *cn; + struct us_conntrack *u; + + cn = container_of(i, struct cache_nack, tx_list); + u = cache_get_conntrack(STATE_SYNC(internal), cn); + tx_list_xmit(i, u); + } + + if (alive_alarm.expires > 0) + mod_alarm(&alive_alarm, 1); + else { + init_alarm(&alive_alarm); + /* XXX: alive message expiration configurable */ + set_alarm_expiration(&alive_alarm, 1); + set_alarm_function(&alive_alarm, do_alive_alarm); + add_alarm(&alive_alarm); + } +} + struct sync_mode nack = { .internal_cache_flags = LIFETIME, .external_cache_flags = LIFETIME, @@ -263,4 +362,5 @@ struct sync_mode nack = { .local = nack_local, .recv = nack_recv, .send = nack_send, + .run = nack_run, }; diff --git a/src/sync-notrack.c b/src/sync-notrack.c index 1d6eba8..8588ecf 100644 --- a/src/sync-notrack.c +++ b/src/sync-notrack.c @@ -24,12 +24,16 @@ static void refresher(struct alarm_list *a, void *data) { + int len; + struct nethdr *net; struct us_conntrack *u = data; debug_ct(u->ct, "persistence update"); a->expires = random() % CONFIG(refresh) + 1; - mcast_build_send_update(u); + net = BUILD_NETMSG(u->ct, NFCT_Q_UPDATE); + len = prepare_send_netmsg(STATE_SYNC(mcast_client), net); + mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), net, len); } static void cache_notrack_add(struct us_conntrack *u, void *data) diff --git a/src/timer.c b/src/timer.c new file mode 100644 index 0000000..b85c286 --- /dev/null +++ b/src/timer.c @@ -0,0 +1,75 @@ +/* + * (C) 2006-2007 by Pablo Neira Ayuso + * + * 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 +#include +#include +#include "conntrackd.h" +#include "timer.h" + +#define TIMESLICE_CREDIT (1000000 / STEPS_PER_SECONDS) /* 200 ms timeslice */ + +void timer_init(struct timer *timer) +{ + memset(timer, 0, sizeof(struct timer)); + timer->credits = TIMESLICE_CREDIT; +} + +void timer_start(struct timer *timer) +{ + gettimeofday(&timer->start, NULL); +} + +static int timeval_subtract(struct timeval *diff, + struct timeval *start, + struct timeval *stop) +{ + diff->tv_sec = stop->tv_sec - start->tv_sec; + diff->tv_usec = stop->tv_usec - start->tv_usec; + + if (diff->tv_usec < 0) { + diff->tv_usec += 1000000; + diff->tv_sec--; + } + + /* Return 1 if result is negative. */ + return diff->tv_sec < 0; +} + +void timer_stop(struct timer *timer) +{ + gettimeofday(&timer->stop, NULL); + timeval_subtract(&timer->diff, &timer->start, &timer->stop); +} + +int timer_adjust_credit(struct timer *timer) +{ + if (timer->diff.tv_sec != 0) { + timer->credits = TIMESLICE_CREDIT; + return 1; + } + + timer->credits -= timer->diff.tv_usec; + + if (timer->credits < 0) { + timer->credits += TIMESLICE_CREDIT; + if (timer->credits < 0) + timer->credits = TIMESLICE_CREDIT; + return 1; + } + return 0; +} -- cgit v1.2.3 From 66cd168df39bfcf581bb36250a080a66331ee5cd Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Wed, 12 Sep 2007 15:23:14 +0000 Subject: add syslog support and bump version --- ChangeLog | 1 + configure.in | 2 +- examples/stats/conntrackd.conf | 11 +++- examples/sync/nack/node1/conntrackd.conf | 11 +++- examples/sync/nack/node2/conntrackd.conf | 11 +++- examples/sync/persistent/node1/conntrackd.conf | 11 +++- examples/sync/persistent/node2/conntrackd.conf | 11 +++- include/conntrackd.h | 4 ++ include/log.h | 2 +- src/cache_iterators.c | 10 ++-- src/log.c | 76 +++++++++++++++++++------- src/main.c | 12 ++-- src/netlink.c | 12 ++-- src/read_config_lex.l | 3 +- src/read_config_yy.y | 57 ++++++++++++++++++- src/run.c | 28 +++++----- src/stats-mode.c | 17 +++--- src/sync-mode.c | 33 +++++------ src/sync-nack.c | 8 +-- 19 files changed, 228 insertions(+), 92 deletions(-) (limited to 'src/stats-mode.c') diff --git a/ChangeLog b/ChangeLog index 6d1aa06..c085175 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,7 @@ o include kernel options and Fedora comments in the INSTALL file = conntrackd = o Remove window tracking disabling limitation (requires Linux kernel >= 2.6.22) +o syslog support (based on patch from Simon Lodal) version 0.9.5 (2007/07/29) ------------------------------ diff --git a/configure.in b/configure.in index 536d2d8..9400e37 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -AC_INIT(conntrack-tools, 0.9.5, pablo@netfilter.org) +AC_INIT(conntrack-tools, 0.9.6, pablo@netfilter.org) AC_CANONICAL_SYSTEM diff --git a/examples/stats/conntrackd.conf b/examples/stats/conntrackd.conf index e514ac0..07deaa8 100644 --- a/examples/stats/conntrackd.conf +++ b/examples/stats/conntrackd.conf @@ -14,9 +14,16 @@ General { HashLimit 65535 # - # Logfile + # Logfile: on, off, or a filename + # Default: on (/var/log/conntrackd.log) # - LogFile /var/log/conntrackd.log + #LogFile off + + # + # Syslog: on, off or a facility name (daemon (default) or local0..7) + # Default: off + # + #Syslog on # # Lockfile diff --git a/examples/sync/nack/node1/conntrackd.conf b/examples/sync/nack/node1/conntrackd.conf index 9a7d55f..ef9eb4a 100644 --- a/examples/sync/nack/node1/conntrackd.conf +++ b/examples/sync/nack/node1/conntrackd.conf @@ -65,9 +65,16 @@ General { HashLimit 65535 # - # Logfile + # Logfile: on, off, or a filename + # Default: on (/var/log/conntrackd.log) # - LogFile /var/log/conntrackd.log + #LogFile off + + # + # Syslog: on, off or a facility name (daemon (default) or local0..7) + # Default: off + # + #Syslog on # # Lockfile diff --git a/examples/sync/nack/node2/conntrackd.conf b/examples/sync/nack/node2/conntrackd.conf index cee16c8..c4d8a21 100644 --- a/examples/sync/nack/node2/conntrackd.conf +++ b/examples/sync/nack/node2/conntrackd.conf @@ -64,9 +64,16 @@ General { HashLimit 65535 # - # Logfile + # Logfile: on, off, or a filename + # Default: on (/var/log/conntrackd.log) # - LogFile /var/log/conntrackd.log + #LogFile off + + # + # Syslog: on, off or a facility name (daemon (default) or local0..7) + # Default: off + # + #Syslog on # # Lockfile diff --git a/examples/sync/persistent/node1/conntrackd.conf b/examples/sync/persistent/node1/conntrackd.conf index e80921b..d240fbb 100644 --- a/examples/sync/persistent/node1/conntrackd.conf +++ b/examples/sync/persistent/node1/conntrackd.conf @@ -70,9 +70,16 @@ General { HashLimit 65535 # - # Logfile + # Logfile: on, off, or a filename + # Default: on (/var/log/conntrackd.log) # - LogFile /var/log/conntrackd.log + #LogFile off + + # + # Syslog: on, off or a facility name (daemon (default) or local0..7) + # Default: off + # + #Syslog on # # Lockfile diff --git a/examples/sync/persistent/node2/conntrackd.conf b/examples/sync/persistent/node2/conntrackd.conf index ad4b040..d5a276e 100644 --- a/examples/sync/persistent/node2/conntrackd.conf +++ b/examples/sync/persistent/node2/conntrackd.conf @@ -70,9 +70,16 @@ General { HashLimit 65535 # - # Logfile + # Logfile: on, off, or a filename + # Default: on (/var/log/conntrackd.log) # - LogFile /var/log/conntrackd.log + #LogFile off + + # + # Syslog: on, off or a facility name (daemon (default) or local0..7) + # Default: off + # + #Syslog on # # Lockfile diff --git a/include/conntrackd.h b/include/conntrackd.h index e89fc79..fc15ebe 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -12,6 +12,7 @@ #include "state_helper.h" #include "linux_list.h" #include +#include /* UNIX facilities */ #define FLUSH_MASTER 0 /* flush kernel conntrack table */ @@ -29,6 +30,8 @@ #define DEFAULT_CONFIGFILE "/etc/conntrackd/conntrackd.conf" #define DEFAULT_LOCKFILE "/var/lock/conntrackd.lock" +#define DEFAULT_LOGFILE "/var/log/conntrackd.log" +#define DEFAULT_SYSLOG_FACILITY LOG_DAEMON enum { SYNC_MODE_PERSISTENT_BIT = 0, @@ -65,6 +68,7 @@ union inet_address { struct ct_conf { char logfile[FILENAME_MAXLEN]; + int syslog_facility; char lockfile[FILENAME_MAXLEN]; int hashsize; /* hashtable size */ struct mcast_conf mcast; /* multicast settings */ diff --git a/include/log.h b/include/log.h index 9ecff30..f6f450c 100644 --- a/include/log.h +++ b/include/log.h @@ -4,7 +4,7 @@ #include FILE *init_log(char *filename); -void dlog(FILE *fd, char *format, ...); +void dlog(FILE *fd, int priority, char *format, ...); void close_log(FILE *fd); #endif diff --git a/src/cache_iterators.c b/src/cache_iterators.c index 287f92f..24506e4 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -139,14 +139,14 @@ void cache_commit(struct cache *c) commit_exist = c->commit_exist - commit_exist; /* log results */ - dlog(STATE(log), "Committed %u new entries", commit_ok); + dlog(STATE(log), LOG_INFO, "Committed %u new entries", commit_ok); if (commit_exist) - dlog(STATE(log), "%u entries ignored, " - "already exist", commit_exist); + dlog(STATE(log), LOG_INFO, "%u entries ignored, " + "already exist", commit_exist); if (commit_fail) - dlog(STATE(log), "%u entries can't be " - "committed", commit_fail); + dlog(STATE(log), LOG_INFO, "%u entries can't be " + "committed", commit_fail); } static int do_flush(void *data1, void *data2) diff --git a/src/log.c b/src/log.c index 88cadea..5fea1c3 100644 --- a/src/log.c +++ b/src/log.c @@ -22,36 +22,74 @@ #include #include #include +#include "conntrackd.h" FILE *init_log(char *filename) { - FILE *fd; + FILE *fd = NULL; - fd = fopen(filename, "a+"); - if (fd == NULL) { - fprintf(stderr, "can't open log file `%s'\n", filename); - return NULL; + if (filename[0]) { + fd = fopen(filename, "a+"); + if (fd == NULL) { + fprintf(stderr, "can't open log file `%s'\n", filename); + return NULL; + } } + if (CONFIG(syslog_facility) != -1) + openlog(PACKAGE, LOG_PID, CONFIG(syslog_facility)); + return fd; } -void dlog(FILE *fd, char *format, ...) -{ - time_t t = time(NULL); - char *buf = ctime(&t); - va_list args; - - buf[strlen(buf)-1]='\0'; - va_start(args, format); - fprintf(fd, "[%s] (pid=%d) ", buf, getpid()); - vfprintf(fd, format, args); - va_end(args); - fprintf(fd, "\n"); - fflush(fd); +void dlog(FILE *fd, int priority, char *format, ...) + { + time_t t; + char *buf; + char *prio; + va_list args; + + if (fd) { + t = time(NULL); + buf = ctime(&t); + buf[strlen(buf)-1]='\0'; + switch (priority) { + case LOG_INFO: + prio = "info"; + break; + case LOG_NOTICE: + prio = "notice"; + break; + case LOG_WARNING: + prio = "warning"; + break; + case LOG_ERR: + prio = "ERROR"; + break; + default: + prio = "?"; + break; + } + va_start(args, format); + fprintf(fd, "[%s] (pid=%d) [%s] ", buf, getpid(), prio); + vfprintf(fd, format, args); + va_end(args); + fprintf(fd, "\n"); + fflush(fd); + } + + if (CONFIG(syslog_facility) != -1) { + va_start(args, format); + vsyslog(priority, format, args); + va_end(args); + } } void close_log(FILE *fd) { - fclose(fd); + if (fd != NULL) + fclose(fd); + + if (CONFIG(syslog_facility) != -1) + closelog(); } diff --git a/src/main.c b/src/main.c index 007b76e..712b572 100644 --- a/src/main.c +++ b/src/main.c @@ -244,10 +244,10 @@ int main(int argc, char *argv[]) } /* - * Setting up logfile + * Setting up logging */ STATE(log) = init_log(CONFIG(logfile)); - if (!STATE(log)) { + if (config_set && !STATE(log)) { fprintf(stdout, "can't open logfile `%s\n'", CONFIG(logfile)); exit(EXIT_FAILURE); } @@ -276,15 +276,15 @@ int main(int argc, char *argv[]) pid_t pid; if ((pid = fork()) == -1) { - dlog(STATE(log), "fork() failed: " - "%s", strerror(errno)); + dlog(STATE(log), LOG_ERR, "fork() failed: " + "%s", strerror(errno)); exit(EXIT_FAILURE); } else if (pid) exit(EXIT_SUCCESS); - dlog(STATE(log), "--- starting in daemon mode ---"); + dlog(STATE(log), LOG_INFO, "--- starting in daemon mode ---"); } else - dlog(STATE(log), "--- starting in console mode ---"); + dlog(STATE(log), LOG_INFO, "--- starting in console mode ---"); /* * initialization process diff --git a/src/netlink.c b/src/netlink.c index be5f82e..693646f 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -75,7 +75,7 @@ static int event_handler(enum nf_conntrack_msg_type type, update_traffic_stats(ct); break; default: - dlog(STATE(log), "received unknown msg from ctnetlink\n"); + dlog(STATE(log), LOG_WARNING, "unknown msg from ctnetlink\n"); break; } @@ -136,7 +136,7 @@ static int dump_handler(enum nf_conntrack_msg_type type, STATE(mode)->dump(ct); break; default: - dlog(STATE(log), "received unknown msg from ctnetlink"); + dlog(STATE(log), LOG_WARNING, "unknown msg from ctnetlink"); break; } return NFCT_CB_CONTINUE; @@ -169,7 +169,8 @@ void nl_resize_socket_buffer(struct nfct_handle *h) return; if (s > CONFIG(netlink_buffer_size_max_grown)) { - dlog(STATE(log), "WARNING: maximum netlink socket buffer " + dlog(STATE(log), LOG_WARNING, + "maximum netlink socket buffer " "size has been reached. We are likely to " "be losing events, this may lead to " "unsynchronized replicas. Please, consider " @@ -184,8 +185,9 @@ void nl_resize_socket_buffer(struct nfct_handle *h) CONFIG(netlink_buffer_size) = nfnl_rcvbufsiz(nfct_nfnlh(h), s); /* notify the sysadmin */ - dlog(STATE(log), "netlink socket buffer size has been set to %u bytes", - CONFIG(netlink_buffer_size)); + dlog(STATE(log), LOG_INFO, "netlink socket buffer size " + "has been set to %u bytes", + CONFIG(netlink_buffer_size)); } int nl_dump_conntrack_table(void) diff --git a/src/read_config_lex.l b/src/read_config_lex.l index 87e98d1..48c0409 100644 --- a/src/read_config_lex.l +++ b/src/read_config_lex.l @@ -42,7 +42,7 @@ ip6_part {hex_255}":"? ip6_form1 {ip6_part}{0,16}"::"{ip6_part}{0,16} ip6_form2 ({hex_255}":"){16}{hex_255} ip6 {ip6_form1}|{ip6_form2} -string [a-zA-Z0-9]* +string [a-zA-Z][a-zA-Z0-9]* persistent [P|p][E|e][R|r][S|s][I|i][S|s][T|t][E|e][N|n][T|T] nack [N|n][A|a][C|c][K|k] @@ -73,6 +73,7 @@ nack [N|n][A|a][C|c][K|k] "Backlog" { return T_BACKLOG; } "Group" { return T_GROUP; } "LogFile" { return T_LOG; } +"Syslog" { return T_SYSLOG; } "LockFile" { return T_LOCK; } "General" { return T_GENERAL; } "Sync" { return T_SYNC; } diff --git a/src/read_config_yy.y b/src/read_config_yy.y index de592d2..8bc83fe 100644 --- a/src/read_config_yy.y +++ b/src/read_config_yy.y @@ -25,6 +25,7 @@ #include #include "conntrackd.h" #include "ignore.h" +#include extern char *yytext; extern int yylineno; @@ -48,6 +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 %token T_IP T_PATH_VAL @@ -72,11 +74,56 @@ line : ignore_protocol | stats ; -log : T_LOG T_PATH_VAL +logfile_bool : T_LOG T_ON +{ + strncpy(conf.logfile, DEFAULT_LOGFILE, FILENAME_MAXLEN); +}; + +logfile_bool : T_LOG T_OFF +{ +}; + +logfile_path : T_LOG T_PATH_VAL { strncpy(conf.logfile, $2, FILENAME_MAXLEN); }; +syslog_bool : T_SYSLOG T_ON +{ + conf.syslog_facility = DEFAULT_SYSLOG_FACILITY; +}; + +syslog_bool : T_SYSLOG T_OFF +{ + conf.syslog_facility = -1; +} + +syslog_facility : T_SYSLOG T_STRING +{ + if (!strcmp($2, "daemon")) + conf.syslog_facility = LOG_DAEMON; + else if (!strcmp($2, "local0")) + conf.syslog_facility = LOG_LOCAL0; + else if (!strcmp($2, "local1")) + conf.syslog_facility = LOG_LOCAL1; + else if (!strcmp($2, "local2")) + conf.syslog_facility = LOG_LOCAL2; + else if (!strcmp($2, "local3")) + conf.syslog_facility = LOG_LOCAL3; + else if (!strcmp($2, "local4")) + conf.syslog_facility = LOG_LOCAL4; + else if (!strcmp($2, "local5")) + conf.syslog_facility = LOG_LOCAL5; + else if (!strcmp($2, "local6")) + conf.syslog_facility = LOG_LOCAL6; + else if (!strcmp($2, "local7")) + conf.syslog_facility = LOG_LOCAL7; + else { + fprintf(stderr, "'%s' is not a known syslog facility, ignoring.\n", $2); + return; + } +}; + lock : T_LOCK T_PATH_VAL { strncpy(conf.lockfile, $2, FILENAME_MAXLEN); @@ -461,7 +508,10 @@ general_list: general_line: hashsize | hashlimit - | log + | logfile_bool + | logfile_path + | syslog_facility + | syslog_bool | lock | unix_line | netlink_buffer_size @@ -516,6 +566,9 @@ init_config(char *filename) if (!fp) return -1; + /* Zero may be a valid facility */ + CONFIG(syslog_facility) = -1; + yyrestart(fp); yyparse(); fclose(fp); diff --git a/src/run.c b/src/run.c index 644f82e..9ce9923 100644 --- a/src/run.c +++ b/src/run.c @@ -40,7 +40,7 @@ void killer(int foo) STATE(mode)->kill(); destroy_alarm_scheduler(); unlink(CONFIG(lockfile)); - dlog(STATE(log), "------- shutdown received ----"); + dlog(STATE(log), LOG_INFO, "------- shutdown received ----"); close_log(STATE(log)); sigprocmask(SIG_UNBLOCK, &STATE(block), NULL); @@ -60,31 +60,31 @@ void local_handler(int fd, void *data) ret = read(fd, &type, sizeof(type)); if (ret == -1) { - dlog(STATE(log), "can't read from unix socket"); + dlog(STATE(log), LOG_INFO, "can't read from unix socket"); return; } if (ret == 0) { - dlog(STATE(log), "local request: nothing to process?"); + dlog(STATE(log), LOG_INFO, "local request: nothing received?"); return; } switch(type) { case FLUSH_MASTER: - dlog(STATE(log), "[DEPRECATED] `conntrackd -F' is deprecated. " - "Use conntrack -F instead."); + dlog(STATE(log), LOG_NOTICE, "`conntrackd -F' is deprecated. " + "Use conntrack -F instead."); if (fork() == 0) { execlp("conntrack", "conntrack", "-F", NULL); exit(EXIT_SUCCESS); } return; case RESYNC_MASTER: - dlog(STATE(log), "[REQ] resync with master table"); + dlog(STATE(log), LOG_NOTICE, "resync with master table"); nl_dump_conntrack_table(); return; } if (!STATE(mode)->local(fd, type, data)) - dlog(STATE(log), "[FAIL] unknown local request %d", type); + dlog(STATE(log), LOG_ERR, "unknown local request %d", type); } int init(int mode) @@ -105,30 +105,30 @@ int init(int mode) /* Initialization */ if (STATE(mode)->init() == -1) { - dlog(STATE(log), "[FAIL] initialization failed"); + dlog(STATE(log), LOG_ERR, "initialization failed"); return -1; } if (init_alarm_scheduler() == -1) { - dlog(STATE(log), "[FAIL] can't initialize alarm scheduler"); + dlog(STATE(log), LOG_ERR, "can't initialize alarm scheduler"); return -1; } /* local UNIX socket */ STATE(local) = local_server_create(&CONFIG(local)); if (!STATE(local)) { - dlog(STATE(log), "[FAIL] can't open unix socket!"); + dlog(STATE(log), LOG_ERR, "can't open unix socket!"); return -1; } if (nl_init_event_handler() == -1) { - dlog(STATE(log), "[FAIL] can't open netlink handler! " - "no ctnetlink kernel support?"); + dlog(STATE(log), LOG_ERR, "can't open netlink handler! " + "no ctnetlink kernel support?"); return -1; } if (nl_init_dump_handler() == -1) { - dlog(STATE(log), "[FAIL] can't open netlink handler! " + dlog(STATE(log), LOG_ERR, "can't open netlink handler! " "no ctnetlink kernel support?"); return -1; } @@ -152,7 +152,7 @@ int init(int mode) if (signal(SIGCHLD, child) == SIG_ERR) return -1; - dlog(STATE(log), "[OK] initialization completed"); + dlog(STATE(log), LOG_INFO, "initialization completed"); return 0; } diff --git a/src/stats-mode.c b/src/stats-mode.c index 65bab1b..1d68e02 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -32,7 +32,7 @@ static int init_stats(void) state.stats = malloc(sizeof(struct ct_stats_state)); if (!state.stats) { - dlog(STATE(log), "[FAIL] can't allocate memory for stats sync"); + dlog(STATE(log), LOG_ERR, "can't allocate memory for stats"); return -1; } memset(state.stats, 0, sizeof(struct ct_stats_state)); @@ -42,8 +42,8 @@ static int init_stats(void) CONFIG(family), NULL); if (!STATE_STATS(cache)) { - dlog(STATE(log), "[FAIL] can't allocate memory for the " - "external cache"); + dlog(STATE(log), LOG_ERR, "can't allocate memory for the " + "external cache"); return -1; } @@ -68,7 +68,7 @@ static int local_handler_stats(int fd, int type, void *data) cache_dump(STATE_STATS(cache), fd, NFCT_O_XML); break; case FLUSH_CACHE: - dlog(STATE(log), "[REQ] flushing caches"); + dlog(STATE(log), LOG_NOTICE, "flushing caches"); cache_flush(STATE_STATS(cache)); break; case KILL: @@ -122,7 +122,7 @@ static void overrun_stats() h = nfct_open(CONNTRACK, 0); if (!h) { - dlog(STATE(log), "can't open overrun handler"); + dlog(STATE(log), LOG_ERR, "can't open overrun handler"); return; } @@ -132,7 +132,8 @@ static void overrun_stats() ret = nfct_query(h, NFCT_Q_DUMP, &family); if (ret == -1) - dlog(STATE(log), "overrun query error %s", strerror(errno)); + dlog(STATE(log), LOG_ERR, + "overrun query error %s", strerror(errno)); nfct_close(h); } @@ -143,8 +144,8 @@ static void event_new_stats(struct nf_conntrack *ct) debug_ct(ct, "cache new"); } else { if (errno != EEXIST) { - dlog(STATE(log), "can't add to cache cache: " - "%s\n", strerror(errno)); + dlog(STATE(log), LOG_ERR, + "can't add to cache cache: %s\n", strerror(errno)); debug_ct(ct, "can't add"); } } diff --git a/src/sync-mode.c b/src/sync-mode.c index 917a3b2..e48b121 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -77,7 +77,7 @@ retry: debug_ct(ct, "can't destroy"); break; default: - dlog(STATE(log), "mcast received unknown query %d\n", query); + dlog(STATE(log), LOG_ERR, "mcast unknown query %d\n", query); break; } } @@ -97,7 +97,7 @@ static void mcast_handler() struct nethdr *net = (struct nethdr *) ptr; if (ntohs(net->len) > remain) { - dlog(STATE(log), "fragmented messages"); + dlog(STATE(log), LOG_ERR, "fragmented messages"); break; } @@ -121,7 +121,7 @@ static int init_sync(void) state.sync = malloc(sizeof(struct ct_sync_state)); if (!state.sync) { - dlog(STATE(log), "[FAIL] can't allocate memory for state sync"); + dlog(STATE(log), LOG_ERR, "can't allocate memory for sync"); return -1; } memset(state.sync, 0, sizeof(struct ct_sync_state)); @@ -142,8 +142,8 @@ static int init_sync(void) STATE_SYNC(sync)->internal_cache_extra); if (!STATE_SYNC(internal)) { - dlog(STATE(log), "[FAIL] can't allocate memory for " - "the internal cache"); + dlog(STATE(log), LOG_ERR, "can't allocate memory for " + "the internal cache"); return -1; } @@ -154,27 +154,27 @@ static int init_sync(void) NULL); if (!STATE_SYNC(external)) { - dlog(STATE(log), "[FAIL] can't allocate memory for the " - "external cache"); + dlog(STATE(log), LOG_ERR, "can't allocate memory for the " + "external cache"); return -1; } /* multicast server to receive events from the wire */ STATE_SYNC(mcast_server) = mcast_server_create(&CONFIG(mcast)); if (STATE_SYNC(mcast_server) == NULL) { - dlog(STATE(log), "[FAIL] can't open multicast server!"); + dlog(STATE(log), LOG_ERR, "can't open multicast server!"); return -1; } /* multicast client to send events on the wire */ STATE_SYNC(mcast_client) = mcast_client_create(&CONFIG(mcast)); if (STATE_SYNC(mcast_client) == NULL) { - dlog(STATE(log), "[FAIL] can't open client multicast socket!"); + dlog(STATE(log), LOG_ERR, "can't open client multicast socket"); return -1; } if (mcast_buffered_init(&CONFIG(mcast)) == -1) { - dlog(STATE(log), "[FAIL] can't init tx buffer!"); + dlog(STATE(log), LOG_ERR, "can't init tx buffer!"); return -1; } @@ -269,13 +269,13 @@ static int local_handler_sync(int fd, int type, void *data) case COMMIT: ret = fork(); if (ret == 0) { - dlog(STATE(log), "[REQ] committing external cache"); + dlog(STATE(log), LOG_INFO, "committing external cache"); cache_commit(STATE_SYNC(external)); exit(EXIT_SUCCESS); } break; case FLUSH_CACHE: - dlog(STATE(log), "[REQ] flushing caches"); + dlog(STATE(log), LOG_INFO, "flushing caches"); cache_flush(STATE_SYNC(internal)); cache_flush(STATE_SYNC(external)); break; @@ -398,7 +398,7 @@ static void overrun_sync() h = nfct_open(CONNTRACK, 0); if (!h) { - dlog(STATE(log), "can't open overrun handler"); + dlog(STATE(log), LOG_ERR, "can't open overrun handler"); return; } @@ -406,7 +406,8 @@ static void overrun_sync() ret = nfct_query(h, NFCT_Q_DUMP, &family); if (ret == -1) - dlog(STATE(log), "overrun query error %s", strerror(errno)); + dlog(STATE(log), LOG_ERR, + "overrun query error %s", strerror(errno)); nfct_callback_unregister(h); @@ -436,8 +437,8 @@ retry: goto retry; } - dlog(STATE(log), "can't add to internal cache: " - "%s\n", strerror(errno)); + dlog(STATE(log), LOG_ERR, "can't add to internal cache: " + "%s\n", strerror(errno)); debug_ct(ct, "can't add"); } } diff --git a/src/sync-nack.c b/src/sync-nack.c index dbda0a7..fa61be4 100644 --- a/src/sync-nack.c +++ b/src/sync-nack.c @@ -74,13 +74,13 @@ static int nack_init() { tx_queue = buffer_create(CONFIG(resend_buffer_size)); if (tx_queue == NULL) { - dlog(STATE(log), "[FAIL] cannot create tx buffer"); + dlog(STATE(log), LOG_ERR, "cannot create tx buffer"); return -1; } rs_queue = buffer_create(CONFIG(resend_buffer_size)); if (rs_queue == NULL) { - dlog(STATE(log), "[FAIL] cannot create rs buffer"); + dlog(STATE(log), LOG_ERR, "cannot create rs buffer"); return -1; } @@ -125,11 +125,11 @@ static int nack_local(int fd, int type, void *data) switch(type) { case REQUEST_DUMP: - dlog(STATE(log), "[REQ] request resync"); + dlog(STATE(log), LOG_NOTICE, "request resync"); tx_queue_add_ctlmsg(NET_F_RESYNC, 0, 0); break; case SEND_BULK: - dlog(STATE(log), "[REQ] sending bulk update"); + dlog(STATE(log), LOG_NOTICE, "sending bulk update"); cache_iterate(STATE_SYNC(internal), NULL, do_cache_to_tx); break; default: -- cgit v1.2.3 From c41a0d3efc957505e72067e99a873ce66be0834a Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Thu, 3 Jan 2008 15:51:48 +0000 Subject: o add support for connection logging to the statistics mode via Logfile o minor irrelevant fixes for uncommon error paths and fix several typos o use LOG_INFO for connection logging, use LOG_NOTICE for other information o minor error handling updates --- ChangeLog | 2 ++ doc/stats/conntrackd.conf | 22 +++++++++++---- include/conntrackd.h | 6 ++++ include/log.h | 7 ++--- src/cache_iterators.c | 10 +++---- src/ignore_pool.c | 4 +-- src/log.c | 56 +++++++++++++++++++++++++++++-------- src/main.c | 14 ++++------ src/netlink.c | 6 ++-- src/network.c | 4 +-- src/read_config_yy.y | 70 +++++++++++++++++++++++++++++++++++++++++++++-- src/run.c | 26 +++++++++--------- src/stats-mode.c | 9 ++++++ src/sync-mode.c | 5 ++-- 14 files changed, 182 insertions(+), 59 deletions(-) (limited to 'src/stats-mode.c') diff --git a/ChangeLog b/ChangeLog index bf79b6a..83e1524 100644 --- a/ChangeLog +++ b/ChangeLog @@ -25,6 +25,8 @@ o rename `examples' directory to `doc' 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 minor irrelevant fixes for uncommon error paths and fix several typos version 0.9.5 (2007/07/29) ------------------------------ diff --git a/doc/stats/conntrackd.conf b/doc/stats/conntrackd.conf index 07deaa8..198b8a3 100644 --- a/doc/stats/conntrackd.conf +++ b/doc/stats/conntrackd.conf @@ -49,6 +49,23 @@ General { SocketBufferSizeMaxGrown 655355 } +Stats { + # + # Enable connection logging. Default is off. + # Logfile: on, off, or a filename + # Default file: (/var/log/conntrackd-stats.log) + # + LogFile on + + # + # 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, + # otherwise you'll get a warning message. + # + #Syslog on +} + # # Ignore traffic for a certain set of IP's: Usually # all the IP assigned to the firewall since local @@ -69,8 +86,3 @@ IgnoreProtocol { # VRRP # numeric numbers also valid } - -# -# Strip NAT traffic -# -StripNAT diff --git a/include/conntrackd.h b/include/conntrackd.h index 1bb3879..e5b8a4e 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -31,6 +31,7 @@ #define DEFAULT_CONFIGFILE "/etc/conntrackd/conntrackd.conf" #define DEFAULT_LOCKFILE "/var/lock/conntrackd.lock" #define DEFAULT_LOGFILE "/var/log/conntrackd.log" +#define DEFAULT_STATS_LOGFILE "/var/log/conntrackd-stats.log" #define DEFAULT_SYSLOG_FACILITY LOG_DAEMON enum { @@ -87,6 +88,10 @@ struct ct_conf { unsigned int resend_buffer_size;/* FTFW protocol */ unsigned int window_size; int cache_write_through; + struct { + char logfile[FILENAME_MAXLEN]; + int syslog_facility; + } stats; }; #define STATE(x) st.x @@ -94,6 +99,7 @@ struct ct_conf { struct ct_general_state { sigset_t block; FILE *log; + FILE *stats_log; int local; struct ct_mode *mode; struct ignore_pool *ignore_pool; diff --git a/include/log.h b/include/log.h index f6f450c..467ae8f 100644 --- a/include/log.h +++ b/include/log.h @@ -1,10 +1,9 @@ #ifndef _LOG_H_ #define _LOG_H_ -#include - -FILE *init_log(char *filename); +int init_log(); void dlog(FILE *fd, int priority, char *format, ...); -void close_log(FILE *fd); +void dlog_ct(FILE *fd, struct nf_conntrack *ct); +void close_log(); #endif diff --git a/src/cache_iterators.c b/src/cache_iterators.c index c29100c..85f87ab 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -120,14 +120,14 @@ void cache_commit(struct cache *c) commit_exist = c->commit_exist - commit_exist; /* log results */ - dlog(STATE(log), LOG_INFO, "Committed %u new entries", commit_ok); + dlog(STATE(log), LOG_NOTICE, "Committed %u new entries", commit_ok); if (commit_exist) - dlog(STATE(log), LOG_INFO, "%u entries ignored, " - "already exist", commit_exist); + dlog(STATE(log), LOG_NOTICE, "%u entries ignored, " + "already exist", commit_exist); if (commit_fail) - dlog(STATE(log), LOG_INFO, "%u entries can't be " - "committed", commit_fail); + dlog(STATE(log), LOG_NOTICE, "%u entries can't be " + "committed", commit_fail); } static int do_flush(void *data1, void *data2) diff --git a/src/ignore_pool.c b/src/ignore_pool.c index 619c2fa..ee457ba 100644 --- a/src/ignore_pool.c +++ b/src/ignore_pool.c @@ -118,7 +118,7 @@ int __ignore_pool_test_ipv6(struct ignore_pool *ip, struct nf_conntrack *ct) int ignore_pool_test(struct ignore_pool *ip, struct nf_conntrack *ct) { - int ret; + int ret = 0; switch(nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO)) { case AF_INET: @@ -128,7 +128,7 @@ int ignore_pool_test(struct ignore_pool *ip, struct nf_conntrack *ct) ret = __ignore_pool_test_ipv6(ip, ct); break; default: - dlog(STATE(log), "unknown conntrack layer 3 protocol?"); + dlog(STATE(log), LOG_WARNING, "unknown layer 3 protocol?"); break; } diff --git a/src/log.c b/src/log.c index 5fea1c3..e3f2102 100644 --- a/src/log.c +++ b/src/log.c @@ -24,22 +24,31 @@ #include #include "conntrackd.h" -FILE *init_log(char *filename) +int init_log(void) { - FILE *fd = NULL; + if (CONFIG(logfile)[0]) { + STATE(log) = fopen(CONFIG(logfile), "a+"); + if (STATE(log) == NULL) { + fprintf(stderr, "can't open log file `%s'\n", + CONFIG(logfile)); + return -1; + } + } - if (filename[0]) { - fd = fopen(filename, "a+"); - if (fd == NULL) { - fprintf(stderr, "can't open log file `%s'\n", filename); - return NULL; + if (CONFIG(stats).logfile[0]) { + STATE(stats_log) = fopen(CONFIG(stats).logfile, "a+"); + if (STATE(stats_log) == NULL) { + fprintf(stderr, "can't open log file `%s'\n", + CONFIG(stats).logfile); + return -1; } } - if (CONFIG(syslog_facility) != -1) + if (CONFIG(syslog_facility) != -1 || + CONFIG(stats).syslog_facility != -1) openlog(PACKAGE, LOG_PID, CONFIG(syslog_facility)); - return fd; + return 0; } void dlog(FILE *fd, int priority, char *format, ...) @@ -85,10 +94,33 @@ void dlog(FILE *fd, int priority, char *format, ...) } } -void close_log(FILE *fd) +void dlog_ct(FILE *fd, struct nf_conntrack *ct) +{ + time_t t; + char buf[1024]; + char *tmp; + + if (fd) { + t = time(NULL); + ctime_r(&t, buf); + tmp = buf + strlen(buf); + buf[strlen(buf)-1]='\t'; + nfct_snprintf(buf+strlen(buf), 1024-strlen(buf), ct, 0, 0, 0); + fprintf(fd, "%s\n", buf); + fflush(fd); + } + + if (CONFIG(stats).syslog_facility != -1) + syslog(LOG_INFO, "%s", tmp); +} + +void close_log(void) { - if (fd != NULL) - fclose(fd); + if (STATE(log) != NULL) + fclose(STATE(log)); + + if (STATE(stats_log) != NULL) + fclose(STATE(stats_log)); if (CONFIG(syslog_facility) != -1) closelog(); diff --git a/src/main.c b/src/main.c index 3a54911..e0ca46d 100644 --- a/src/main.c +++ b/src/main.c @@ -246,8 +246,7 @@ int main(int argc, char *argv[]) /* * Setting up logging */ - STATE(log) = init_log(CONFIG(logfile)); - if (config_set && !STATE(log)) { + if (config_set && init_log() == -1) { fprintf(stderr, "can't open logfile `%s\n'", CONFIG(logfile)); exit(EXIT_FAILURE); } @@ -255,7 +254,7 @@ int main(int argc, char *argv[]) if (type == REQUEST) { if (do_local_request(action, &conf.local, local_step) == -1) { fprintf(stderr, "can't connect: is conntrackd " - "running? appropiate permissions?\n"); + "running? appropriate permissions?\n"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); @@ -276,22 +275,21 @@ int main(int argc, char *argv[]) pid_t pid; if ((pid = fork()) == -1) { - dlog(STATE(log), LOG_ERR, "fork() failed: " - "%s", strerror(errno)); + perror("fork has failed: "); exit(EXIT_FAILURE); } else if (pid) exit(EXIT_SUCCESS); - dlog(STATE(log), LOG_INFO, "--- starting in daemon mode ---"); + dlog(STATE(log), LOG_NOTICE, "-- starting in daemon mode --"); } else - dlog(STATE(log), LOG_INFO, "--- starting in console mode ---"); + dlog(STATE(log), LOG_NOTICE, "-- starting in console mode --"); /* * initialization process */ if (init(mode) == -1) { - close_log(STATE(log)); + close_log(); fprintf(stderr, "ERROR: conntrackd cannot start, please " "check the logfile for more info\n"); unlink(CONFIG(lockfile)); diff --git a/src/netlink.c b/src/netlink.c index d453fe1..ab945d8 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -185,9 +185,9 @@ void nl_resize_socket_buffer(struct nfct_handle *h) CONFIG(netlink_buffer_size) = nfnl_rcvbufsiz(nfct_nfnlh(h), s); /* notify the sysadmin */ - dlog(STATE(log), LOG_INFO, "netlink socket buffer size " - "has been set to %u bytes", - CONFIG(netlink_buffer_size)); + dlog(STATE(log), LOG_NOTICE, "netlink socket buffer size " + "has been set to %u bytes", + CONFIG(netlink_buffer_size)); } int nl_dump_conntrack_table(void) diff --git a/src/network.c b/src/network.c index 9bd3469..a20c1e0 100644 --- a/src/network.c +++ b/src/network.c @@ -221,8 +221,8 @@ int mcast_track_seq(u_int32_t seq, u_int32_t *exp_seq) /* out of sequence: replayed/delayed packet? */ if (before(seq, STATE_SYNC(last_seq_recv)+1)) - dlog(STATE(log), "delayed packet? exp=%u rcv=%u", - STATE_SYNC(last_seq_recv)+1, seq); + dlog(STATE(log), LOG_WARNING, "delayed packet? exp=%u rcv=%u", + STATE_SYNC(last_seq_recv)+1, seq); out: *exp_seq = STATE_SYNC(last_seq_recv)+1; diff --git a/src/read_config_yy.y b/src/read_config_yy.y index 92806f8..ebb1c73 100644 --- a/src/read_config_yy.y +++ b/src/read_config_yy.y @@ -123,6 +123,11 @@ syslog_facility : T_SYSLOG T_STRING "ignoring.\n", $2); return; } + + if (conf.stats.syslog_facility != -1 && + conf.syslog_facility != conf.stats.syslog_facility) + fprintf(stderr, "WARNING: Conflicting Syslog facility " + "values, defaulting to General.\n"); }; lock : T_LOCK T_PATH_VAL @@ -549,16 +554,74 @@ family : T_FAMILY T_STRING conf.family = AF_INET; }; -stats: T_SYNC '{' stats_list '}'; +stats: T_STATS '{' stats_list '}'; stats_list: | stats_list stat_line ; -stat_line: - | +stat_line: stat_logfile_bool + | stat_logfile_path + | stat_syslog_bool + | stat_syslog_facility ; +stat_logfile_bool : T_LOG T_ON +{ + strncpy(conf.stats.logfile, DEFAULT_STATS_LOGFILE, FILENAME_MAXLEN); +}; + +stat_logfile_bool : T_LOG T_OFF +{ +}; + +stat_logfile_path : T_LOG T_PATH_VAL +{ + strncpy(conf.stats.logfile, $2, FILENAME_MAXLEN); +}; + +stat_syslog_bool : T_SYSLOG T_ON +{ + conf.stats.syslog_facility = DEFAULT_SYSLOG_FACILITY; +}; + +stat_syslog_bool : T_SYSLOG T_OFF +{ + conf.stats.syslog_facility = -1; +} + +stat_syslog_facility : T_SYSLOG T_STRING +{ + if (!strcmp($2, "daemon")) + conf.stats.syslog_facility = LOG_DAEMON; + else if (!strcmp($2, "local0")) + conf.stats.syslog_facility = LOG_LOCAL0; + else if (!strcmp($2, "local1")) + conf.stats.syslog_facility = LOG_LOCAL1; + else if (!strcmp($2, "local2")) + conf.stats.syslog_facility = LOG_LOCAL2; + else if (!strcmp($2, "local3")) + conf.stats.syslog_facility = LOG_LOCAL3; + else if (!strcmp($2, "local4")) + conf.stats.syslog_facility = LOG_LOCAL4; + else if (!strcmp($2, "local5")) + conf.stats.syslog_facility = LOG_LOCAL5; + else if (!strcmp($2, "local6")) + conf.stats.syslog_facility = LOG_LOCAL6; + else if (!strcmp($2, "local7")) + conf.stats.syslog_facility = LOG_LOCAL7; + else { + fprintf(stderr, "'%s' is not a known syslog facility, " + "ignoring.\n", $2); + return; + } + + if (conf.syslog_facility != -1 && + conf.stats.syslog_facility != conf.syslog_facility) + fprintf(stderr, "WARNING: Conflicting Syslog facility " + "values, defaulting to General.\n"); +}; + %% int @@ -580,6 +643,7 @@ init_config(char *filename) /* Zero may be a valid facility */ CONFIG(syslog_facility) = -1; + CONFIG(stats).syslog_facility = -1; yyrestart(fp); yyparse(); diff --git a/src/run.c b/src/run.c index 9ce9923..0411fcb 100644 --- a/src/run.c +++ b/src/run.c @@ -40,7 +40,7 @@ void killer(int foo) STATE(mode)->kill(); destroy_alarm_scheduler(); unlink(CONFIG(lockfile)); - dlog(STATE(log), LOG_INFO, "------- shutdown received ----"); + dlog(STATE(log), LOG_NOTICE, "---- shutdown received ----"); close_log(STATE(log)); sigprocmask(SIG_UNBLOCK, &STATE(block), NULL); @@ -60,18 +60,16 @@ void local_handler(int fd, void *data) ret = read(fd, &type, sizeof(type)); if (ret == -1) { - dlog(STATE(log), LOG_INFO, "can't read from unix socket"); + dlog(STATE(log), LOG_ERR, "can't read from unix socket"); return; } - if (ret == 0) { - dlog(STATE(log), LOG_INFO, "local request: nothing received?"); + if (ret == 0) return; - } switch(type) { case FLUSH_MASTER: - dlog(STATE(log), LOG_NOTICE, "`conntrackd -F' is deprecated. " - "Use conntrack -F instead."); + dlog(STATE(log), LOG_WARNING, "`conntrackd -F' is deprecated. " + "Use conntrack -F instead."); if (fork() == 0) { execlp("conntrack", "conntrack", "-F", NULL); exit(EXIT_SUCCESS); @@ -84,7 +82,7 @@ void local_handler(int fd, void *data) } if (!STATE(mode)->local(fd, type, data)) - dlog(STATE(log), LOG_ERR, "unknown local request %d", type); + dlog(STATE(log), LOG_WARNING, "unknown local request %d", type); } int init(int mode) @@ -152,7 +150,7 @@ int init(int mode) if (signal(SIGCHLD, child) == SIG_ERR) return -1; - dlog(STATE(log), LOG_INFO, "initialization completed"); + dlog(STATE(log), LOG_NOTICE, "initialization completed"); return 0; } @@ -181,7 +179,8 @@ static void __run(long credit, int step) if (errno == EINTR) return; - dlog(STATE(log), "select() failed: %s", strerror(errno)); + dlog(STATE(log), LOG_WARNING, + "select failed: %s", strerror(errno)); return; } @@ -218,8 +217,8 @@ static void __run(long credit, int step) case EAGAIN: break; default: - dlog(STATE(log), "event catch says: %s", - strerror(errno)); + dlog(STATE(log), LOG_WARNING, + "event catch says: %s", strerror(errno)); break; } } @@ -251,7 +250,8 @@ void run(void) timer_stop(&timer); if (timer_adjust_credit(&timer)) - dlog(STATE(log), "alarm run takes too long!"); + dlog(STATE(log), LOG_WARNING, + "alarm run takes too long!"); step = (step + 1) < STEPS_PER_SECONDS ? step + 1 : 0; } diff --git a/src/stats-mode.c b/src/stats-mode.c index 1d68e02..e817c4e 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -88,6 +88,8 @@ static int local_handler_stats(int fd, int type, void *data) static void dump_stats(struct nf_conntrack *ct) { + nfct_attr_unset(ct, ATTR_TIMEOUT); + if (cache_update_force(STATE_STATS(cache), ct)) debug_ct(ct, "resync entry"); } @@ -140,6 +142,8 @@ static void overrun_stats() static void event_new_stats(struct nf_conntrack *ct) { + nfct_attr_unset(ct, ATTR_TIMEOUT); + if (cache_add(STATE_STATS(cache), ct)) { debug_ct(ct, "cache new"); } else { @@ -153,6 +157,8 @@ static void event_new_stats(struct nf_conntrack *ct) static void event_update_stats(struct nf_conntrack *ct) { + nfct_attr_unset(ct, ATTR_TIMEOUT); + if (!cache_update_force(STATE_STATS(cache), ct)) { debug_ct(ct, "can't update"); return; @@ -162,8 +168,11 @@ static void event_update_stats(struct nf_conntrack *ct) static int event_destroy_stats(struct nf_conntrack *ct) { + nfct_attr_unset(ct, ATTR_TIMEOUT); + if (cache_del(STATE_STATS(cache), ct)) { debug_ct(ct, "cache destroy"); + dlog_ct(STATE(stats_log), ct); return 1; } else { debug_ct(ct, "can't destroy!"); diff --git a/src/sync-mode.c b/src/sync-mode.c index 7cd2b84..7c42c78 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -273,13 +273,14 @@ static int local_handler_sync(int fd, int type, void *data) case COMMIT: ret = fork(); if (ret == 0) { - dlog(STATE(log), LOG_INFO, "committing external cache"); + dlog(STATE(log), LOG_NOTICE, + "committing external cache"); cache_commit(STATE_SYNC(external)); exit(EXIT_SUCCESS); } break; case FLUSH_CACHE: - dlog(STATE(log), LOG_INFO, "flushing caches"); + dlog(STATE(log), LOG_NOTICE, "flushing caches"); cache_flush(STATE_SYNC(internal)); cache_flush(STATE_SYNC(external)); break; -- cgit v1.2.3 From 1102a95296e39f671efe51bb6bd9b30e5c14c91e Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Sat, 5 Jan 2008 16:41:15 +0000 Subject: implement buffered connection logging to improve performance --- ChangeLog | 1 + doc/stats/conntrackd.conf | 10 +++++++ include/buffer.h | 18 +++++++++++++ include/conntrackd.h | 3 +++ include/log.h | 8 +++++- src/Makefile.am | 2 +- src/buffer.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++ src/log.c | 28 +++++++++++++++++--- src/read_config_lex.l | 1 + src/read_config_yy.y | 8 +++++- src/stats-mode.c | 12 ++++++++- 11 files changed, 151 insertions(+), 7 deletions(-) create mode 100644 include/buffer.h create mode 100644 src/buffer.c (limited to 'src/stats-mode.c') 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 ) 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 @@ -58,6 +58,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) 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 #include #include "cache.h" +#include "buffer.h" #include "debug.h" #include #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 + +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 + * + * 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 +#include +#include +#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 #include #include +#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 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 #include "cache.h" +#include "log.h" #include "conntrackd.h" #include #include @@ -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!"); -- cgit v1.2.3 From 6023de67c84e531939b77454783835c65f694bff Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Mon, 7 Jan 2008 16:32:10 +0000 Subject: fix segfaul in the exit path for the statistics mode (introduced in r7175) --- src/log.c | 3 ++- src/run.c | 2 +- src/stats-mode.c | 8 +++++--- 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src/stats-mode.c') diff --git a/src/log.c b/src/log.c index 176bdcd..51109b6 100644 --- a/src/log.c +++ b/src/log.c @@ -171,6 +171,7 @@ void close_log(void) if (STATE(stats_log) != NULL) fclose(STATE(stats_log)); - if (CONFIG(syslog_facility) != -1) + if (CONFIG(syslog_facility) != -1 || + CONFIG(stats).syslog_facility != -1) closelog(); } diff --git a/src/run.c b/src/run.c index ebf4b3c..609b454 100644 --- a/src/run.c +++ b/src/run.c @@ -41,7 +41,7 @@ void killer(int foo) destroy_alarm_scheduler(); unlink(CONFIG(lockfile)); dlog(STATE(log), LOG_NOTICE, "---- shutdown received ----"); - close_log(STATE(log)); + close_log(); sigprocmask(SIG_UNBLOCK, &STATE(block), NULL); diff --git a/src/stats-mode.c b/src/stats-mode.c index 05a1b2c..ee9b3fd 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -60,9 +60,11 @@ 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)); + /* flush the buffer before exiting */ + if (STATE(stats_log) != NULL) + buffer_flush(STATE(stats_log), + dlog_buffered_ct_flush, + STATE(stats_log)); } /* handler for requests coming via UNIX socket */ -- cgit v1.2.3 From a7cec817806de3855e42bc1a81f60fd4154b8cf2 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Fri, 11 Jan 2008 01:17:01 +0000 Subject: fix buffer flush before exiting --- src/stats-mode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/stats-mode.c') diff --git a/src/stats-mode.c b/src/stats-mode.c index ee9b3fd..20efc95 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -62,7 +62,7 @@ static void kill_stats() cache_destroy(STATE_STATS(cache)); /* flush the buffer before exiting */ if (STATE(stats_log) != NULL) - buffer_flush(STATE(stats_log), + buffer_flush(STATE_STATS(buffer_log), dlog_buffered_ct_flush, STATE(stats_log)); } -- cgit v1.2.3 From 369a532132e9c9f19e0dd07d2e2c554c92c70f67 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Tue, 15 Jan 2008 13:04:16 +0000 Subject: Max Kellermann : fix wrong invocations after prototype cleanup --- ChangeLog | 1 + src/cache_timer.c | 2 +- src/stats-mode.c | 2 +- src/sync-mode.c | 23 ++++++++++++----------- 4 files changed, 15 insertions(+), 13 deletions(-) (limited to 'src/stats-mode.c') diff --git a/ChangeLog b/ChangeLog index c9de1ed..158a7d2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -53,6 +53,7 @@ o use list_for_each_entry() instead of list_for_each() o use const when possible o remove prefetch in slist.h since it confuses gcc o fix illegal use of return in the yacc code, use break instead +o fix wrong invocations after prototype cleanup version 0.9.5 (2007/07/29) ------------------------------ diff --git a/src/cache_timer.c b/src/cache_timer.c index 02f3ae4..2379f4b 100644 --- a/src/cache_timer.c +++ b/src/cache_timer.c @@ -45,7 +45,7 @@ static void timer_add(struct us_conntrack *u, void *data) static void timer_update(struct us_conntrack *u, void *data) { struct alarm_list *alarm = data; - mod_alarm(alarm, CONFIG(cache_timeout)); + mod_alarm(alarm, CONFIG(cache_timeout), 0); } static void timer_destroy(struct us_conntrack *u, void *data) diff --git a/src/stats-mode.c b/src/stats-mode.c index 20efc95..de53751 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -84,7 +84,7 @@ static int local_handler_stats(int fd, int type, void *data) cache_flush(STATE_STATS(cache)); break; case KILL: - killer(); + killer(0); break; case STATS: cache_stats(STATE_STATS(cache), fd); diff --git a/src/sync-mode.c b/src/sync-mode.c index d38d91f..c3630b6 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -31,7 +31,7 @@ static void do_mcast_handler_step(struct nethdr *net) { - unsigned int query; + int query; struct netpld *pld = NETHDR_DATA(net); char __ct[nfct_maxsize()]; struct nf_conntrack *ct = (struct nf_conntrack *) __ct; @@ -82,7 +82,7 @@ retry: } /* handler for multicast messages received */ -static void mcast_handler() +static void mcast_handler(void) { int numbytes, remain; char __net[65536], *ptr = __net; /* XXX: maximum MTU for IPv4 */ @@ -116,8 +116,6 @@ static void mcast_handler() static int init_sync(void) { - int ret; - state.sync = malloc(sizeof(struct ct_sync_state)); if (!state.sync) { dlog(STATE(log), LOG_ERR, "can't allocate memory for sync"); @@ -212,7 +210,7 @@ static void run_sync(fd_set *readfds) mcast_buffered_pending_netmsg(STATE_SYNC(mcast_client)); } -static void kill_sync() +static void kill_sync(void) { cache_destroy(STATE_SYNC(internal)); cache_destroy(STATE_SYNC(external)); @@ -226,7 +224,7 @@ static void kill_sync() STATE_SYNC(sync)->kill(); } -static dump_stats_sync(int fd) +static void dump_stats_sync(int fd) { char buf[512]; int size; @@ -234,8 +232,8 @@ static dump_stats_sync(int fd) size = sprintf(buf, "multicast sequence tracking:\n" "%20llu Pckts mfrm " "%20llu Pckts lost\n\n", - STATE(malformed), - STATE_SYNC(packets_lost)); + (unsigned long long)STATE(malformed), + (unsigned long long)STATE_SYNC(packets_lost)); send(fd, buf, size, 0); } @@ -289,7 +287,7 @@ static int local_handler_sync(int fd, int type, void *data) cache_flush(STATE_SYNC(external)); break; case KILL: - killer(); + killer(0); break; case STATS: cache_stats(STATE_SYNC(internal), fd); @@ -403,7 +401,7 @@ static int overrun_purge_step(void *data1, void *data2) } /* it's likely that we're losing events, just try to do our best here */ -static void overrun_sync() +static void overrun_sync(void) { int ret; struct nfct_handle *h; @@ -481,8 +479,11 @@ static int event_destroy_sync(struct nf_conntrack *ct) if (cache_del(STATE_SYNC(internal), ct)) { mcast_send_sync(NULL, ct, NFCT_Q_DESTROY); debug_ct(ct, "internal destroy"); - } else + return 1; + } else { debug_ct(ct, "can't destroy"); + return 0; + } } struct ct_mode sync_mode = { -- cgit v1.2.3 From 4e37e2d9079b4c1890a39f26e5082d6b1e7d0024 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Tue, 15 Jan 2008 13:39:46 +0000 Subject: Max Kellermann : add missing function prototypes --- ChangeLog | 1 + include/alarm.h | 17 +++++++++++++++++ include/conntrackd.h | 6 ++++++ include/ignore.h | 1 + include/network.h | 6 ++++++ src/cache_iterators.c | 1 + src/cache_wt.c | 1 + src/main.c | 4 ---- src/netlink.c | 4 ++++ src/network.c | 1 + src/run.c | 1 + src/stats-mode.c | 2 ++ src/sync-mode.c | 4 ++++ src/traffic_stats.c | 1 + 14 files changed, 46 insertions(+), 4 deletions(-) (limited to 'src/stats-mode.c') diff --git a/ChangeLog b/ChangeLog index 8d95e48..d417dab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -57,6 +57,7 @@ o fix illegal use of return in the yacc code, use break instead o fix wrong invocations after prototype cleanup o set the return type of the parse functions to "void" o use the comma operator instead of curly braces +o add missing function prototypes version 0.9.5 (2007/07/29) ------------------------------ diff --git a/include/alarm.h b/include/alarm.h index fbe34f6..c68e7f4 100644 --- a/include/alarm.h +++ b/include/alarm.h @@ -17,4 +17,21 @@ set_alarm_expiration(struct alarm_list *t, long tv_sec, long tv_usec) t->tv.tv_usec = tv_usec; } +void set_alarm_function(struct alarm_list *t, + void (*fcn)(struct alarm_list *a, void *data)); + +void set_alarm_data(struct alarm_list *t, void *data); + +void init_alarm(struct alarm_list *t); + +void add_alarm(struct alarm_list *alarm); + +void del_alarm(struct alarm_list *alarm); + +void mod_alarm(struct alarm_list *alarm, unsigned long sc, unsigned long usc); + +int get_next_alarm(struct timeval *tv, struct timeval *next_alarm); + +int do_alarm_run(struct timeval *next_alarm); + #endif diff --git a/include/conntrackd.h b/include/conntrackd.h index e8b90cc..33732a4 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -175,4 +175,10 @@ extern struct ct_mode stats_mode; #define MAX(x, y) x > y ? x : y +/* These live in run.c */ +void killer(int foo); +void local_handler(int fd, void *data); +int init(void); +void run(void); + #endif diff --git a/include/ignore.h b/include/ignore.h index 40cb02d..96deb93 100644 --- a/include/ignore.h +++ b/include/ignore.h @@ -8,5 +8,6 @@ struct ignore_pool { struct ignore_pool *ignore_pool_create(u_int8_t family); void ignore_pool_destroy(struct ignore_pool *ip); int ignore_pool_add(struct ignore_pool *ip, void *data); +int ignore_pool_test(struct ignore_pool *ip, struct nf_conntrack *ct); #endif diff --git a/include/network.h b/include/network.h index e92f6c3..88ff43b 100644 --- a/include/network.h +++ b/include/network.h @@ -54,6 +54,8 @@ void build_netmsg(struct nf_conntrack *ct, int query, struct nethdr *net); int prepare_send_netmsg(struct mcast_sock *m, void *data); int mcast_send_netmsg(struct mcast_sock *m, void *data); int mcast_recv_netmsg(struct mcast_sock *m, void *data, int len); +int handle_netmsg(struct nethdr *net); +int mcast_track_seq(u_int32_t seq, u_int32_t *exp_seq); struct mcast_conf; @@ -161,4 +163,8 @@ struct netattr { #define NTA_ALIGN(len) (((len) + NTA_ALIGNTO - 1) & ~(NTA_ALIGNTO - 1)) #define NTA_LENGTH(len) (NTA_ALIGN(sizeof(struct netattr)) + (len)) +void build_netpld(struct nf_conntrack *ct, struct netpld *pld, int query); + +void parse_netpld(struct nf_conntrack *ct, struct netpld *pld, int *query); + #endif diff --git a/src/cache_iterators.c b/src/cache_iterators.c index 85f87ab..d43ae6f 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -20,6 +20,7 @@ #include "jhash.h" #include "hash.h" #include "conntrackd.h" +#include "netlink.h" #include #include #include "us-conntrack.h" diff --git a/src/cache_wt.c b/src/cache_wt.c index 2a9d8e7..fee17e2 100644 --- a/src/cache_wt.c +++ b/src/cache_wt.c @@ -16,6 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "netlink.h" #include #include "conntrackd.h" #include "us-conntrack.h" diff --git a/src/main.c b/src/main.c index 19d999a..2497a7f 100644 --- a/src/main.c +++ b/src/main.c @@ -61,10 +61,6 @@ void show_usage(char *progname) fprintf(stdout, "%s\n", usage_options); } -/* These live in run.c */ -int init(void); -void run(void); - void set_operation_mode(int *current, int want, char *argv[]) { if (*current == NOT_SET) { diff --git a/src/netlink.c b/src/netlink.c index ab945d8..7800b10 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -16,7 +16,11 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "netlink.h" #include "conntrackd.h" +#include "traffic_stats.h" +#include "ignore.h" +#include "log.h" #include #include #include diff --git a/src/network.c b/src/network.c index 8f1dc94..e7ffbac 100644 --- a/src/network.c +++ b/src/network.c @@ -20,6 +20,7 @@ #include "network.h" #include "us-conntrack.h" #include "sync.h" +#include "log.h" static unsigned int seq_set, cur_seq; diff --git a/src/run.c b/src/run.c index 8919b6c..7fbeaf5 100644 --- a/src/run.c +++ b/src/run.c @@ -19,6 +19,7 @@ */ #include "conntrackd.h" +#include "netlink.h" #include #include #include "us-conntrack.h" diff --git a/src/stats-mode.c b/src/stats-mode.c index de53751..0983b97 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "netlink.h" +#include "traffic_stats.h" #include #include "cache.h" #include "log.h" diff --git a/src/sync-mode.c b/src/sync-mode.c index c3630b6..8be8c18 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -16,6 +16,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "netlink.h" +#include "traffic_stats.h" +#include "log.h" #include #include "cache.h" #include "conntrackd.h" @@ -28,6 +31,7 @@ #include "sync.h" #include "network.h" #include "debug.h" +#include static void do_mcast_handler_step(struct nethdr *net) { diff --git a/src/traffic_stats.c b/src/traffic_stats.c index b510b77..b2cdaae 100644 --- a/src/traffic_stats.c +++ b/src/traffic_stats.c @@ -16,6 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "traffic_stats.h" #include "cache.h" #include "hash.h" #include "conntrackd.h" -- cgit v1.2.3 From 82290b2b0bd2ebb5539b61b98e993ae807c2e8d7 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Tue, 15 Jan 2008 14:00:14 +0000 Subject: Max Kellermann : Fix tons of gcc warnings --- ChangeLog | 3 ++- extensions/libct_proto_icmp.c | 2 +- extensions/libct_proto_tcp.c | 2 +- extensions/libct_proto_udp.c | 4 +--- include/cache.h | 2 +- include/conntrack.h | 8 ++++---- include/conntrackd.h | 4 ++++ include/debug.h | 4 ++-- include/linux_list.h | 2 +- include/log.h | 6 +++--- include/network.h | 2 +- src/alarm.c | 3 ++- src/buffer.c | 1 + src/cache.c | 28 ++++++++++++++------------- src/cache_iterators.c | 5 +++-- src/cache_lifetime.c | 2 ++ src/cache_timer.c | 2 +- src/cache_wt.c | 2 +- src/conntrack.c | 44 ++++++++++++++++++++++++++----------------- src/hash.c | 8 ++------ src/ignore_pool.c | 10 +++++++--- src/local.c | 2 +- src/log.c | 9 +++++---- src/main.c | 12 +++++++++--- src/mcast.c | 10 ++++++---- src/network.c | 5 ++--- src/read_config_yy.y | 2 +- src/run.c | 17 +++++++++++++---- src/stats-mode.c | 6 ++---- src/sync-alarm.c | 2 ++ src/sync-ftfw.c | 9 +++++---- src/sync-mode.c | 2 +- src/traffic_stats.c | 4 ++-- 33 files changed, 131 insertions(+), 93 deletions(-) (limited to 'src/stats-mode.c') diff --git a/ChangeLog b/ChangeLog index 6543aaf..f42234a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -42,7 +42,6 @@ o wake up the daemon iff there are real events to handle instead of polling o add support for tagged vlan interfaces in the config file, e.g. eth0.1 o improve alarm framework based on suggestions from Max Kellerman o constify queue_iterate() -o use timeradd() since manipulating tv_sec directly Max Kellermann : @@ -63,6 +62,8 @@ o merge several *_alarm() functions into init_alarm() o use add_alarm() in mod_alarm() to avoid code duplication o import tcp_state_helper only once o add missing printf arguments +o use timeradd() since manipulating tv_sec directly +o fix lots of gcc warnings version 0.9.5 (2007/07/29) ------------------------------ diff --git a/extensions/libct_proto_icmp.c b/extensions/libct_proto_icmp.c index 09fd8da..7c59072 100644 --- a/extensions/libct_proto_icmp.c +++ b/extensions/libct_proto_icmp.c @@ -51,7 +51,7 @@ static char icmp_commands_v_options[NUMBER_OF_CMD][ICMP_NUMBER_OF_OPT] = /*EXP_EVENT*/ {0,0,0}, }; -static void help() +static void help(void) { fprintf(stdout, " --icmp-type\t\t\ticmp type\n"); fprintf(stdout, " --icmp-code\t\t\ticmp code\n"); diff --git a/extensions/libct_proto_tcp.c b/extensions/libct_proto_tcp.c index 1f630b3..a3b1826 100644 --- a/extensions/libct_proto_tcp.c +++ b/extensions/libct_proto_tcp.c @@ -73,7 +73,7 @@ static const char *states[] = { "LISTEN" }; -static void help() +static void help(void) { fprintf(stdout, " --orig-port-src\t\toriginal source port\n"); fprintf(stdout, " --orig-port-dst\t\toriginal destination port\n"); diff --git a/extensions/libct_proto_udp.c b/extensions/libct_proto_udp.c index 2216b71..267e3d6 100644 --- a/extensions/libct_proto_udp.c +++ b/extensions/libct_proto_udp.c @@ -38,7 +38,7 @@ static const char *udp_optflags[UDP_NUMBER_OF_OPT] = { "mask-port-dst", "tuple-port-src", "tuple-port-dst" }; -static void help() +static void help(void) { fprintf(stdout, " --orig-port-src\t\toriginal source port\n"); fprintf(stdout, " --orig-port-dst\t\toriginal destination port\n"); @@ -166,8 +166,6 @@ static void final_check(unsigned int flags, unsigned int cmd, struct nf_conntrack *ct) { - int ret = 0; - if ((flags & (UDP_ORIG_SPORT|UDP_ORIG_DPORT)) && !(flags & (UDP_REPL_SPORT|UDP_REPL_DPORT))) { nfct_set_attr_u16(ct, diff --git a/include/cache.h b/include/cache.h index 5ca6ce4..e4fb945 100644 --- a/include/cache.h +++ b/include/cache.h @@ -75,7 +75,7 @@ struct cache_extra { struct nf_conntrack; -struct cache *cache_create(char *name, unsigned int features, u_int8_t proto, struct cache_extra *extra); +struct cache *cache_create(const char *name, unsigned int features, u_int8_t proto, struct cache_extra *extra); void cache_destroy(struct cache *e); struct us_conntrack *cache_add(struct cache *c, struct nf_conntrack *ct); diff --git a/include/conntrack.h b/include/conntrack.h index 1b2581e..8f2b6a2 100644 --- a/include/conntrack.h +++ b/include/conntrack.h @@ -148,9 +148,9 @@ enum { struct ctproto_handler { struct list_head head; - char *name; + const char *name; u_int16_t protonum; - char *version; + const char *version; enum ctattr_protoinfo protoinfo_attr; @@ -164,7 +164,7 @@ struct ctproto_handler { unsigned int command, struct nf_conntrack *ct); - void (*help)(); + void (*help)(void); struct option *opts; @@ -181,7 +181,7 @@ void generic_opt_check(int options, int nops, char *optset, const char *optflg[]); -void exit_error(enum exittype status, char *msg, ...); +void exit_error(enum exittype status, const char *msg, ...); extern void register_proto(struct ctproto_handler *h); diff --git a/include/conntrackd.h b/include/conntrackd.h index 33732a4..d3f66ba 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -181,4 +181,8 @@ void local_handler(int fd, void *data); int init(void); void run(void); +/* from read_config_yy.c */ +int +init_config(char *filename); + #endif diff --git a/include/debug.h b/include/debug.h index 1ffd9ac..f205983 100644 --- a/include/debug.h +++ b/include/debug.h @@ -14,8 +14,8 @@ }) #define debug printf #else -#define debug_ct(ct, msg) -#define debug +#define debug_ct(ct, msg) do {} while (0) +#define debug(...) do {} while (0) #endif #endif diff --git a/include/linux_list.h b/include/linux_list.h index 57b56d7..b84b1c4 100644 --- a/include/linux_list.h +++ b/include/linux_list.h @@ -13,7 +13,7 @@ * */ #define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) /* diff --git a/include/log.h b/include/log.h index b5bbddb..64bf1ce 100644 --- a/include/log.h +++ b/include/log.h @@ -6,10 +6,10 @@ struct buffer; struct nf_conntrack; -int init_log(); -void dlog(FILE *fd, int priority, char *format, ...); +int init_log(void); +void dlog(FILE *fd, int priority, const char *format, ...); 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(); +void close_log(void); #endif diff --git a/include/network.h b/include/network.h index 88ff43b..d0b639b 100644 --- a/include/network.h +++ b/include/network.h @@ -60,7 +60,7 @@ int mcast_track_seq(u_int32_t seq, u_int32_t *exp_seq); struct mcast_conf; int mcast_buffered_init(struct mcast_conf *conf); -void mcast_buffered_destroy(); +void mcast_buffered_destroy(void); int mcast_buffered_send_netmsg(struct mcast_sock *m, void *data, int len); int mcast_buffered_pending_netmsg(struct mcast_sock *m); diff --git a/src/alarm.c b/src/alarm.c index 3467e7b..25075ef 100644 --- a/src/alarm.c +++ b/src/alarm.c @@ -36,7 +36,8 @@ void init_alarm(struct alarm_list *t, t->function = fcn; } -void __add_alarm(struct alarm_list *alarm) +static void +__add_alarm(struct alarm_list *alarm) { struct alarm_list *t; diff --git a/src/buffer.c b/src/buffer.c index 4f60123..79266a7 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -50,6 +50,7 @@ int buffer_add(struct buffer *b, void *data, unsigned int size) memcpy(b->data + b->cur_size, data, size); b->cur_size += size; + return 0; } void buffer_flush(struct buffer *b, diff --git a/src/cache.c b/src/cache.c index a0950d5..c5afb00 100644 --- a/src/cache.c +++ b/src/cache.c @@ -23,6 +23,7 @@ #include #include "us-conntrack.h" #include "cache.h" +#include static u_int32_t hash(const void *data, struct hashtable *table) { @@ -120,7 +121,7 @@ struct cache_feature *cache_feature[CACHE_MAX_FEATURE] = { [WRITE_THROUGH_FEATURE] = &writethrough_feature, }; -struct cache *cache_create(char *name, +struct cache *cache_create(const char *name, unsigned int features, u_int8_t proto, struct cache_extra *extra) @@ -209,7 +210,7 @@ void cache_destroy(struct cache *c) static struct us_conntrack *__add(struct cache *c, struct nf_conntrack *ct) { - int i; + unsigned i; size_t size = c->h->datasize; char buf[size]; struct us_conntrack *u = (struct us_conntrack *) buf; @@ -226,7 +227,7 @@ static struct us_conntrack *__add(struct cache *c, struct nf_conntrack *ct) u = hashtable_add(c->h, u); if (u) { - void *data = u->data; + char *data = u->data; for (i = 0; i < c->num_features; i++) { c->features[i]->add(u, data); @@ -234,7 +235,7 @@ static struct us_conntrack *__add(struct cache *c, struct nf_conntrack *ct) } if (c->extra && c->extra->add) - c->extra->add(u, ((void *) u) + c->extra_offset); + c->extra->add(u, ((char *) u) + c->extra_offset); return u; } @@ -268,8 +269,8 @@ static struct us_conntrack *__update(struct cache *c, struct nf_conntrack *ct) u = (struct us_conntrack *) hashtable_test(c->h, u); if (u) { - int i; - void *data = u->data; + unsigned i; + char *data = u->data; if (nfct_attr_is_set(ct, ATTR_STATUS)) nfct_set_attr_u32(u->ct, ATTR_STATUS, @@ -287,14 +288,15 @@ static struct us_conntrack *__update(struct cache *c, struct nf_conntrack *ct) } if (c->extra && c->extra->update) - c->extra->update(u, ((void *) u) + c->extra_offset); + c->extra->update(u, ((char *) u) + c->extra_offset); return u; } return NULL; } -struct us_conntrack *__cache_update(struct cache *c, struct nf_conntrack *ct) +static struct us_conntrack * +__cache_update(struct cache *c, struct nf_conntrack *ct) { struct us_conntrack *u; @@ -358,8 +360,8 @@ static int __del(struct cache *c, struct nf_conntrack *ct) u = (struct us_conntrack *) hashtable_test(c->h, u); if (u) { - int i; - void *data = u->data; + unsigned i; + char *data = u->data; struct nf_conntrack *p = u->ct; for (i = 0; i < c->num_features; i++) { @@ -368,7 +370,7 @@ static int __del(struct cache *c, struct nf_conntrack *ct) } if (c->extra && c->extra->destroy) - c->extra->destroy(u, ((void *) u) + c->extra_offset); + c->extra->destroy(u, ((char *) u) + c->extra_offset); hashtable_del(c->h, u); free(p); @@ -390,12 +392,12 @@ int cache_del(struct cache *c, struct nf_conntrack *ct) struct us_conntrack *cache_get_conntrack(struct cache *c, void *data) { - return data - c->extra_offset; + return (struct us_conntrack *)((char*)data - c->extra_offset); } void *cache_get_extra(struct cache *c, void *data) { - return data + c->extra_offset; + return (char*)data + c->extra_offset; } void cache_stats(const struct cache *c, int fd) diff --git a/src/cache_iterators.c b/src/cache_iterators.c index d43ae6f..4fdb920 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -19,6 +19,7 @@ #include "cache.h" #include "jhash.h" #include "hash.h" +#include "log.h" #include "conntrackd.h" #include "netlink.h" #include @@ -36,8 +37,8 @@ static int do_dump(void *data1, void *data2) int size; struct __dump_container *container = data1; struct us_conntrack *u = data2; - void *data = u->data; - int i; + char *data = u->data; + unsigned i; memset(buf, 0, sizeof(buf)); size = nfct_snprintf(buf, diff --git a/src/cache_lifetime.c b/src/cache_lifetime.c index ae54df2..26496d2 100644 --- a/src/cache_lifetime.c +++ b/src/cache_lifetime.c @@ -21,6 +21,8 @@ #include "us-conntrack.h" #include "cache.h" #include "alarm.h" +#include +#include static void lifetime_add(struct us_conntrack *u, void *data) { diff --git a/src/cache_timer.c b/src/cache_timer.c index 8b4e4ea..53ed703 100644 --- a/src/cache_timer.c +++ b/src/cache_timer.c @@ -62,7 +62,7 @@ static int timer_dump(struct us_conntrack *u, void *data, char *buf, int type) gettimeofday(&tv, NULL); timersub(&tv, &alarm->tv, &tmp); - return sprintf(buf, " [expires in %ds]", tmp.tv_sec); + return sprintf(buf, " [expires in %lds]", tmp.tv_sec); } struct cache_feature timer_feature = { diff --git a/src/cache_wt.c b/src/cache_wt.c index fee17e2..9d0af0b 100644 --- a/src/cache_wt.c +++ b/src/cache_wt.c @@ -25,7 +25,7 @@ static void add_update(struct us_conntrack *u) { char __ct[nfct_maxsize()]; - struct nf_conntrack *ct = (struct nf_conntrack *) __ct; + struct nf_conntrack *ct = (struct nf_conntrack *)(void*) __ct; memcpy(ct, u->ct, nfct_maxsize()); diff --git a/src/conntrack.c b/src/conntrack.c index 28340c1..f301a82 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -45,6 +45,8 @@ #include #include #include +#include +#include #ifdef HAVE_ARPA_INET_H #include #endif @@ -175,14 +177,15 @@ static struct ctproto_handler *findproto(char *name) return handler; } -void extension_help(struct ctproto_handler *h) +static void +extension_help(struct ctproto_handler *h) { fprintf(stdout, "\n"); fprintf(stdout, "Proto `%s' help:\n", h->name); h->help(); } -void +static void __attribute__((noreturn)) exit_tryhelp(int status) { fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n", @@ -190,7 +193,8 @@ exit_tryhelp(int status) exit(status); } -void exit_error(enum exittype status, char *msg, ...) +void __attribute__((noreturn)) +exit_error(enum exittype status, const char *msg, ...) { va_list args; @@ -281,7 +285,7 @@ merge_options(struct option *oldopts, const struct option *newopts, #define ENOTSUPP 524 /* Operation is not supported */ /* Translates errno numbers into more human-readable form than strerror. */ -const char * +static const char * err2str(int err, enum action command) { unsigned int i; @@ -318,7 +322,7 @@ err2str(int err, enum action command) #define PARSE_MAX 3 static struct parse_parameter { - char *parameter[6]; + const char *parameter[6]; size_t size; unsigned int value[6]; } parse_array[PARSE_MAX] = { @@ -336,7 +340,8 @@ static int do_parse_parameter(const char *str, size_t str_length, unsigned int *value, int parse_type) { - int i, ret = 0; + size_t i; + int ret = 0; struct parse_parameter *p = &parse_array[parse_type]; if (strncasecmp(str, "SRC_NAT", str_length) == 0) { @@ -384,7 +389,8 @@ add_command(unsigned int *cmd, const int newcmd, const int othercmds) *cmd |= newcmd; } -unsigned int check_type(int argc, char *argv[]) +static unsigned int +check_type(int argc, char *argv[]) { char *table = NULL; @@ -424,7 +430,8 @@ struct addr_parse { unsigned int family; }; -int parse_inetaddr(const char *cp, struct addr_parse *parse) +static int +parse_inetaddr(const char *cp, struct addr_parse *parse) { if (inet_aton(cp, &parse->addr)) return AF_INET; @@ -441,7 +448,8 @@ union ct_address { u_int32_t v6[4]; }; -int parse_addr(const char *cp, union ct_address *address) +static int +parse_addr(const char *cp, union ct_address *address) { struct addr_parse parse; int ret; @@ -458,7 +466,7 @@ int parse_addr(const char *cp, union ct_address *address) static void nat_parse(char *arg, int portok, struct nf_conntrack *obj, int type) { - char *colon, *dash, *error; + char *colon, *error; union ct_address parse; colon = strchr(arg, ':'); @@ -495,7 +503,8 @@ nat_parse(char *arg, int portok, struct nf_conntrack *obj, int type) nfct_set_attr_u32(obj, ATTR_DNAT_IPV4, parse.v4); } -static void event_sighandler(int s) +static void __attribute__((noreturn)) +event_sighandler(int s) { fprintf(stdout, "Now closing conntrack event dumping...\n"); nfct_close(cth); @@ -524,7 +533,6 @@ static const char usage_conntrack_parameters[] = " -e, --event-mask eventmask\t\tEvent mask, eg. NEW,DESTROY\n" " -z, --zero \t\t\t\tZero counters while listing\n" " -o, --output type[,...]\t\tOutput format, eg. xml\n"; - ; static const char usage_expectation_parameters[] = "Expectation parameters and options:\n" @@ -546,7 +554,9 @@ static const char usage_parameters[] = ; -void usage(char *prog) { +static void +usage(char *prog) +{ fprintf(stdout, "Command line interface for the connection " "tracking system. Version %s\n", VERSION); fprintf(stdout, "Usage: %s [commands] [options]\n", prog); @@ -662,11 +672,11 @@ int main(int argc, char *argv[]) char __obj[nfct_maxsize()]; char __exptuple[nfct_maxsize()]; char __mask[nfct_maxsize()]; - struct nf_conntrack *obj = (struct nf_conntrack *) __obj; - struct nf_conntrack *exptuple = (struct nf_conntrack *) __exptuple; - struct nf_conntrack *mask = (struct nf_conntrack *) __mask; + struct nf_conntrack *obj = (struct nf_conntrack *)(void*) __obj; + struct nf_conntrack *exptuple = (struct nf_conntrack *)(void*) __exptuple; + struct nf_conntrack *mask = (struct nf_conntrack *)(void*) __mask; char __exp[nfexp_maxsize()]; - struct nf_expect *exp = (struct nf_expect *) __exp; + struct nf_expect *exp = (struct nf_expect *)(void*) __exp; int l3protonum; union ct_address ad; unsigned int command; diff --git a/src/hash.c b/src/hash.c index 3ed6ad2..553dd1d 100644 --- a/src/hash.c +++ b/src/hash.c @@ -53,7 +53,6 @@ hashtable_create(int hashsize, int limit, int datasize, { int i; struct hashtable *h; - struct hashtype *t; int size = sizeof(struct hashtable) + hashsize * sizeof(struct slist_head); @@ -87,7 +86,6 @@ void *hashtable_add(struct hashtable *table, void *data) struct slist_head *e; struct hashtable_node *n; u_int32_t id; - int i; /* hash table is full */ if (table->count >= table->limit) { @@ -122,7 +120,6 @@ void *hashtable_test(struct hashtable *table, const void *data) struct slist_head *e; u_int32_t id; struct hashtable_node *n; - int i; id = table->hash(data, table); @@ -141,7 +138,6 @@ int hashtable_del(struct hashtable *table, void *data) struct slist_head *e, *next, *prev; u_int32_t id; struct hashtable_node *n; - int i; id = table->hash(data, table); @@ -160,7 +156,7 @@ int hashtable_del(struct hashtable *table, void *data) int hashtable_flush(struct hashtable *table) { - int i; + u_int32_t i; struct slist_head *e, *next, *prev; struct hashtable_node *n; @@ -179,7 +175,7 @@ int hashtable_flush(struct hashtable *table) int hashtable_iterate(struct hashtable *table, void *data, int (*iterate)(void *data1, void *data2)) { - int i; + u_int32_t i; struct slist_head *e, *next, *prev; struct hashtable_node *n; diff --git a/src/ignore_pool.c b/src/ignore_pool.c index ee457ba..82afa93 100644 --- a/src/ignore_pool.c +++ b/src/ignore_pool.c @@ -20,8 +20,11 @@ #include "hash.h" #include "conntrackd.h" #include "ignore.h" +#include "log.h" #include +#include + /* XXX: These should be configurable */ #define IGNORE_POOL_SIZE 128 #define IGNORE_POOL_LIMIT INT_MAX @@ -53,7 +56,6 @@ static int compare6(const void *data1, const void *data2) struct ignore_pool *ignore_pool_create(u_int8_t proto) { - int i, j = 0; struct ignore_pool *ip; ip = malloc(sizeof(struct ignore_pool)); @@ -100,7 +102,8 @@ int ignore_pool_add(struct ignore_pool *ip, void *data) return 1; } -int __ignore_pool_test_ipv4(struct ignore_pool *ip, struct nf_conntrack *ct) +static int +__ignore_pool_test_ipv4(struct ignore_pool *ip, struct nf_conntrack *ct) { return (hashtable_test(ip->h, nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC)) || hashtable_test(ip->h, nfct_get_attr(ct, ATTR_ORIG_IPV4_DST)) || @@ -108,7 +111,8 @@ int __ignore_pool_test_ipv4(struct ignore_pool *ip, struct nf_conntrack *ct) hashtable_test(ip->h, nfct_get_attr(ct, ATTR_REPL_IPV4_DST))); } -int __ignore_pool_test_ipv6(struct ignore_pool *ip, struct nf_conntrack *ct) +static int +__ignore_pool_test_ipv6(struct ignore_pool *ip, struct nf_conntrack *ct) { return (hashtable_test(ip->h, nfct_get_attr(ct, ATTR_ORIG_IPV6_SRC)) || hashtable_test(ip->h, nfct_get_attr(ct, ATTR_ORIG_IPV6_DST)) || diff --git a/src/local.c b/src/local.c index be51b9e..9ff5f82 100644 --- a/src/local.c +++ b/src/local.c @@ -68,7 +68,7 @@ int do_local_server_step(int fd, void *data, { int rfd; struct sockaddr_un local; - size_t sin_size = sizeof(struct sockaddr_un); + socklen_t sin_size = sizeof(struct sockaddr_un); if ((rfd = accept(fd, (struct sockaddr *)&local, &sin_size)) == -1) return -1; diff --git a/src/log.c b/src/log.c index 51109b6..b42e049 100644 --- a/src/log.c +++ b/src/log.c @@ -18,7 +18,7 @@ * Description: Logging support for the conntrack daemon */ -#include +#include "log.h" #include #include #include @@ -26,6 +26,7 @@ #include #include #include +#include #include "buffer.h" #include "conntrackd.h" @@ -78,11 +79,11 @@ int init_log(void) return 0; } -void dlog(FILE *fd, int priority, char *format, ...) +void dlog(FILE *fd, int priority, const char *format, ...) { time_t t; char *buf; - char *prio; + const char *prio; va_list args; if (fd) { @@ -125,7 +126,7 @@ void dlog_buffered_ct_flush(void *buffer_data, void *data) { FILE *fd = data; - fprintf(fd, "%s", buffer_data); + fprintf(fd, "%s", (const char*)buffer_data); fflush(fd); } diff --git a/src/main.c b/src/main.c index 2497a7f..11974ff 100644 --- a/src/main.c +++ b/src/main.c @@ -28,6 +28,9 @@ #include "hash.h" #include "jhash.h" +#undef _POSIX_SOURCE +#include + struct ct_general_state st; union ct_state state; @@ -52,7 +55,8 @@ static const char usage_options[] = "Options:\n" " -C [configfile], configuration file path\n"; -void show_usage(char *progname) +static void +show_usage(char *progname) { fprintf(stdout, "Connection tracking userspace daemon v%s\n", VERSION); fprintf(stdout, "Usage: %s [commands] [options]\n\n", progname); @@ -61,7 +65,8 @@ void show_usage(char *progname) fprintf(stdout, "%s\n", usage_options); } -void set_operation_mode(int *current, int want, char *argv[]) +static void +set_operation_mode(int *current, int want, char *argv[]) { if (*current == NOT_SET) { *current = want; @@ -109,7 +114,7 @@ static int check_capabilities(void) int main(int argc, char *argv[]) { - int ret, i, config_set = 0, action; + int ret, i, config_set = 0, action = -1; char config_file[PATH_MAX]; int type = 0; struct utsname u; @@ -305,4 +310,5 @@ int main(int argc, char *argv[]) * run main process */ run(); + return 0; } diff --git a/src/mcast.c b/src/mcast.c index cdaed5f..cf03593 100644 --- a/src/mcast.c +++ b/src/mcast.c @@ -192,7 +192,6 @@ __mcast_client_create_ipv6(struct mcast_sock *m, struct mcast_conf *conf) struct mcast_sock *mcast_client_create(struct mcast_conf *conf) { int ret = 0; - struct sockaddr_in addr; struct mcast_sock *m; m = (struct mcast_sock *) malloc(sizeof(struct mcast_sock)); @@ -300,9 +299,12 @@ void mcast_dump_stats(int fd, struct mcast_sock *s, struct mcast_sock *r) "%20llu Pckts recv\n" "%20llu Error send " "%20llu Error recv\n\n", - s->stats.bytes, r->stats.bytes, - s->stats.messages, r->stats.messages, - s->stats.error, r->stats.error); + (unsigned long long)s->stats.bytes, + (unsigned long long)r->stats.bytes, + (unsigned long long)s->stats.messages, + (unsigned long long)r->stats.messages, + (unsigned long long)s->stats.error, + (unsigned long long)r->stats.error); send(fd, buf, size, 0); } diff --git a/src/network.c b/src/network.c index e7ffbac..9d6e6e1 100644 --- a/src/network.c +++ b/src/network.c @@ -22,6 +22,8 @@ #include "sync.h" #include "log.h" +#include + static unsigned int seq_set, cur_seq; static int __do_send(struct mcast_sock *m, void *data, int len) @@ -65,8 +67,6 @@ static int __do_prepare(struct mcast_sock *m, void *data, int len) static int __prepare_ctl(struct mcast_sock *m, void *data) { - struct nethdr_ack *nack = (struct nethdr_ack *) data; - return __do_prepare(m, data, NETHDR_ACK_SIZ); } @@ -172,7 +172,6 @@ void build_netmsg(struct nf_conntrack *ct, int query, struct nethdr *net) int handle_netmsg(struct nethdr *net) { - int ret; struct netpld *pld = NETHDR_DATA(net); /* message too small: no room for the header */ diff --git a/src/read_config_yy.y b/src/read_config_yy.y index 8f8759f..82131d7 100644 --- a/src/read_config_yy.y +++ b/src/read_config_yy.y @@ -639,7 +639,7 @@ buffer_size: T_STAT_BUFFER_SIZE T_NUMBER %% -int +int __attribute__((noreturn)) yyerror(char *msg) { fprintf(stderr, "Error parsing config file: "); diff --git a/src/run.c b/src/run.c index 7fbeaf5..3fd98cd 100644 --- a/src/run.c +++ b/src/run.c @@ -20,12 +20,19 @@ #include "conntrackd.h" #include "netlink.h" +#include "ignore.h" +#include "log.h" +#include "alarm.h" #include #include #include "us-conntrack.h" #include #include #include +#include +#include +#include +#include void killer(int foo) { @@ -84,7 +91,8 @@ void local_handler(int fd, void *data) dlog(STATE(log), LOG_WARNING, "unknown local request %d", type); } -int init(void) +int +init(void) { if (CONFIG(flags) & CTD_STATS_MODE) STATE(mode) = &stats_mode; @@ -164,11 +172,11 @@ static int __run(struct timeval *next_alarm) if (ret == -1) { /* interrupted syscall, retry */ if (errno == EINTR) - return; + return 0; dlog(STATE(log), LOG_WARNING, "select failed: %s", strerror(errno)); - return; + return 0; } /* timeout expired, run the alarm list */ @@ -223,7 +231,8 @@ static int __run(struct timeval *next_alarm) return 0; } -void run(void) +void __attribute__((noreturn)) +run(void) { struct timeval next_alarm; struct timeval *next = &next_alarm; diff --git a/src/stats-mode.c b/src/stats-mode.c index 0983b97..563e1f6 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -31,8 +31,6 @@ static int init_stats(void) { - int ret; - state.stats = malloc(sizeof(struct ct_stats_state)); if (!state.stats) { dlog(STATE(log), LOG_ERR, "can't allocate memory for stats"); @@ -59,7 +57,7 @@ static int init_stats(void) return 0; } -static void kill_stats() +static void kill_stats(void) { cache_destroy(STATE_STATS(cache)); /* flush the buffer before exiting */ @@ -130,7 +128,7 @@ static int overrun_cb(enum nf_conntrack_msg_type type, return NFCT_CB_CONTINUE; } -static void overrun_stats() +static void overrun_stats(void) { int ret; struct nfct_handle *h; diff --git a/src/sync-alarm.c b/src/sync-alarm.c index d9a8267..05ddf81 100644 --- a/src/sync-alarm.c +++ b/src/sync-alarm.c @@ -22,6 +22,8 @@ #include "us-conntrack.h" #include "alarm.h" +#include + static void refresher(struct alarm_list *a, void *data) { int len; diff --git a/src/sync-ftfw.c b/src/sync-ftfw.c index 63fd4b2..d881298 100644 --- a/src/sync-ftfw.c +++ b/src/sync-ftfw.c @@ -25,13 +25,14 @@ #include "debug.h" #include "network.h" #include "alarm.h" +#include "log.h" #include #include #if 0 #define dp printf #else -#define dp +#define dp(...) #endif static LIST_HEAD(rs_list); @@ -92,7 +93,7 @@ static void do_alive_alarm(struct alarm_list *a, void *data) add_alarm(&alive_alarm); } -static int ftfw_init() +static int ftfw_init(void) { tx_queue = queue_create(CONFIG(resend_queue_size)); if (tx_queue == NULL) { @@ -117,7 +118,7 @@ static int ftfw_init() return 0; } -static void ftfw_kill() +static void ftfw_kill(void) { queue_destroy(rs_queue); queue_destroy(tx_queue); @@ -330,7 +331,7 @@ static int tx_list_xmit(struct list_head *i, struct us_conntrack *u) return ret; } -static void ftfw_run() +static void ftfw_run(void) { struct cache_ftfw *cn, *tmp; diff --git a/src/sync-mode.c b/src/sync-mode.c index 8be8c18..f2bfc9f 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -38,7 +38,7 @@ static void do_mcast_handler_step(struct nethdr *net) int query; struct netpld *pld = NETHDR_DATA(net); char __ct[nfct_maxsize()]; - struct nf_conntrack *ct = (struct nf_conntrack *) __ct; + struct nf_conntrack *ct = (struct nf_conntrack *)(void*) __ct; struct us_conntrack *u = NULL; if (STATE_SYNC(sync)->recv(net)) diff --git a/src/traffic_stats.c b/src/traffic_stats.c index b2cdaae..b6fa030 100644 --- a/src/traffic_stats.c +++ b/src/traffic_stats.c @@ -48,8 +48,8 @@ void dump_traffic_stats(int fd) STATE(packets)[NFCT_DIR_REPLY]; size = sprintf(buf, "traffic processed:\n"); - size += sprintf(buf+size, "%20llu Bytes ", bytes); - size += sprintf(buf+size, "%20llu Pckts\n\n", packets); + size += sprintf(buf+size, "%20llu Bytes ", (unsigned long long)bytes); + size += sprintf(buf+size, "%20llu Pckts\n\n", (unsigned long long)packets); send(fd, buf, size, 0); } -- cgit v1.2.3 From 5c7db5abef470bc6a0f2e3858a5fc75731c9f3bd Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Thu, 17 Jan 2008 17:16:54 +0000 Subject: Max Kellermann : fix memory leaks in several error output paths --- ChangeLog | 1 + src/mcast.c | 4 ++++ src/stats-mode.c | 3 +++ src/sync-mode.c | 3 +++ 4 files changed, 11 insertions(+) (limited to 'src/stats-mode.c') diff --git a/ChangeLog b/ChangeLog index 3d53d51..e9a6b5f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -76,6 +76,7 @@ o chdir("/") to release the cwd inode o ignore setsid() failure, because there is only one possible and o fix harmless error condition o add buffer_destroy() to buffer.c +o fix memory leaks in several error output paths version 0.9.5 (2007/07/29) ------------------------------ diff --git a/src/mcast.c b/src/mcast.c index 185a7e2..9684b61 100644 --- a/src/mcast.c +++ b/src/mcast.c @@ -80,6 +80,8 @@ struct mcast_sock *mcast_server_create(struct mcast_conf *conf) if (ioctl(m->fd, SIOCGIFMTU, &ifr) == -1) { debug("ioctl"); + close(m->fd); + free(m); return NULL; } conf->mtu = ifr.ifr_mtu; @@ -201,6 +203,7 @@ struct mcast_sock *mcast_client_create(struct mcast_conf *conf) if ((m->fd = socket(conf->ipproto, SOCK_DGRAM, 0)) == -1) { debug("mcast_sock_client_create:socket"); + free(m); return NULL; } @@ -224,6 +227,7 @@ struct mcast_sock *mcast_client_create(struct mcast_conf *conf) } if (ret == -1) { + close(m->fd); free(m); m = NULL; } diff --git a/src/stats-mode.c b/src/stats-mode.c index 563e1f6..0c42d95 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -41,6 +41,7 @@ static int init_stats(void) 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"); + free(state.stats); return -1; } @@ -51,6 +52,8 @@ static int init_stats(void) if (!STATE_STATS(cache)) { dlog(STATE(log), LOG_ERR, "can't allocate memory for the " "external cache"); + free(state.stats); + buffer_destroy(STATE_STATS(buffer_log)); return -1; } diff --git a/src/sync-mode.c b/src/sync-mode.c index f2bfc9f..1632019 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -180,11 +180,14 @@ static int init_sync(void) STATE_SYNC(mcast_client) = mcast_client_create(&CONFIG(mcast)); if (STATE_SYNC(mcast_client) == NULL) { dlog(STATE(log), LOG_ERR, "can't open client multicast socket"); + mcast_server_destroy(STATE_SYNC(mcast_server)); return -1; } if (mcast_buffered_init(&CONFIG(mcast)) == -1) { dlog(STATE(log), LOG_ERR, "can't init tx buffer!"); + mcast_server_destroy(STATE_SYNC(mcast_server)); + mcast_client_destroy(STATE_SYNC(mcast_client)); return -1; } -- cgit v1.2.3 From 001805d9998229534264758432c06295614f8e2a Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Thu, 17 Jan 2008 17:36:32 +0000 Subject: Max Kellermann : import only required C headers and put local headers on top to check --- ChangeLog | 1 + extensions/libct_proto_icmp.c | 4 +++- extensions/libct_proto_udp.c | 1 - include/alarm.h | 2 ++ include/cache.h | 1 - include/conntrack.h | 1 - include/conntrackd.h | 9 +-------- include/ignore.h | 2 ++ include/linux_list.h | 2 ++ include/local.h | 2 -- include/network.h | 2 ++ include/queue.h | 3 --- src/alarm.c | 7 ------- src/buffer.c | 4 +++- src/cache.c | 6 ++++-- src/cache_iterators.c | 5 +++-- src/cache_lifetime.c | 2 -- src/cache_timer.c | 7 ++++--- src/cache_wt.c | 6 +++--- src/conntrack.c | 12 +++--------- src/hash.c | 8 +++----- src/ignore_pool.c | 5 +++-- src/local.c | 7 ++++--- src/log.c | 8 +++----- src/main.c | 8 ++++---- src/mcast.c | 10 ++++------ src/netlink.c | 8 +------- src/network.c | 5 +++-- src/parse.c | 4 ++-- src/queue.c | 4 ++++ src/read_config_lex.l | 1 - src/read_config_yy.y | 1 + src/run.c | 7 ++----- src/stats-mode.c | 11 +++++------ src/sync-alarm.c | 3 +++ src/sync-ftfw.c | 7 +++---- src/sync-mode.c | 14 +++++++------- src/traffic_stats.c | 7 ------- 38 files changed, 85 insertions(+), 112 deletions(-) (limited to 'src/stats-mode.c') diff --git a/ChangeLog b/ChangeLog index e0a0da7..f84f7aa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -81,6 +81,7 @@ o fix harmless error condition o add buffer_destroy() to buffer.c o fix memory leaks in several error output paths o use size_t for buffer sizes +o import only required C headers and put local headers on top to check version 0.9.5 (2007/07/29) ------------------------------ diff --git a/extensions/libct_proto_icmp.c b/extensions/libct_proto_icmp.c index 7c59072..f81c3b4 100644 --- a/extensions/libct_proto_icmp.c +++ b/extensions/libct_proto_icmp.c @@ -8,6 +8,9 @@ * (at your option) any later version. * */ + +#include "conntrack.h" + #include #include #include @@ -15,7 +18,6 @@ #include #include #include -#include "conntrack.h" static struct option opts[] = { {"icmp-type", 1, 0, '1'}, diff --git a/extensions/libct_proto_udp.c b/extensions/libct_proto_udp.c index 267e3d6..a72f9cf 100644 --- a/extensions/libct_proto_udp.c +++ b/extensions/libct_proto_udp.c @@ -10,7 +10,6 @@ #include #include #include -#include #include /* For htons */ #include #include diff --git a/include/alarm.h b/include/alarm.h index 338968a..532084a 100644 --- a/include/alarm.h +++ b/include/alarm.h @@ -3,6 +3,8 @@ #include "linux_list.h" +#include + struct alarm_list { struct list_head head; struct timeval tv; diff --git a/include/cache.h b/include/cache.h index 0743d3f..a2b2005 100644 --- a/include/cache.h +++ b/include/cache.h @@ -3,7 +3,6 @@ #include #include -#include /* cache features */ enum { diff --git a/include/conntrack.h b/include/conntrack.h index d6b6150..63facf4 100644 --- a/include/conntrack.h +++ b/include/conntrack.h @@ -2,7 +2,6 @@ #define _CONNTRACK_H #include "linux_list.h" -#include #include #include diff --git a/include/conntrackd.h b/include/conntrackd.h index bb4b183..c16d3d7 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -6,14 +6,7 @@ #include #include -#include -#include "cache.h" -#include "buffer.h" -#include "debug.h" -#include -#include "state_helper.h" -#include "linux_list.h" -#include +#include #include /* UNIX facilities */ diff --git a/include/ignore.h b/include/ignore.h index f1c2846..efb375d 100644 --- a/include/ignore.h +++ b/include/ignore.h @@ -3,6 +3,8 @@ #include +struct nf_conntrack; + struct ignore_pool { struct hashtable *h; }; diff --git a/include/linux_list.h b/include/linux_list.h index b84b1c4..de182a4 100644 --- a/include/linux_list.h +++ b/include/linux_list.h @@ -1,6 +1,8 @@ #ifndef _LINUX_LIST_H #define _LINUX_LIST_H +#include + #undef offsetof #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) diff --git a/include/local.h b/include/local.h index aae73a7..be77d35 100644 --- a/include/local.h +++ b/include/local.h @@ -1,8 +1,6 @@ #ifndef _LOCAL_SOCKET_H_ #define _LOCAL_SOCKET_H_ -#include - #ifndef UNIX_PATH_MAX #define UNIX_PATH_MAX 108 #endif diff --git a/include/network.h b/include/network.h index f9976dd..6dfd79d 100644 --- a/include/network.h +++ b/include/network.h @@ -3,6 +3,8 @@ #include +struct nf_conntrack; + struct nethdr { uint16_t flags; uint16_t len; diff --git a/include/queue.h b/include/queue.h index ab04d62..9a5d7b8 100644 --- a/include/queue.h +++ b/include/queue.h @@ -1,9 +1,6 @@ #ifndef _QUEUE_H_ #define _QUEUE_H_ -#include -#include -#include #include "linux_list.h" struct queue { diff --git a/src/alarm.c b/src/alarm.c index d00e281..576839a 100644 --- a/src/alarm.c +++ b/src/alarm.c @@ -16,14 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include -#include -#include "linux_list.h" -#include "conntrackd.h" #include "alarm.h" -#include "jhash.h" -#include -#include static LIST_HEAD(alarm_list); diff --git a/src/buffer.c b/src/buffer.c index 389dd38..739174a 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -15,10 +15,12 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "buffer.h" + #include #include #include -#include "buffer.h" struct buffer *buffer_create(size_t size) { diff --git a/src/cache.c b/src/cache.c index dcb0123..2f0e57a 100644 --- a/src/cache.c +++ b/src/cache.c @@ -16,14 +16,16 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "cache.h" #include "jhash.h" #include "hash.h" +#include "us-conntrack.h" #include "conntrackd.h" + #include #include -#include "us-conntrack.h" -#include "cache.h" #include +#include static uint32_t hash(const void *data, struct hashtable *table) { diff --git a/src/cache_iterators.c b/src/cache_iterators.c index 4fdb920..bf70dd1 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -17,14 +17,15 @@ */ #include "cache.h" -#include "jhash.h" #include "hash.h" #include "log.h" #include "conntrackd.h" #include "netlink.h" +#include "us-conntrack.h" + #include #include -#include "us-conntrack.h" +#include struct __dump_container { int fd; diff --git a/src/cache_lifetime.c b/src/cache_lifetime.c index 26496d2..ad3416a 100644 --- a/src/cache_lifetime.c +++ b/src/cache_lifetime.c @@ -17,10 +17,8 @@ */ #include -#include "conntrackd.h" #include "us-conntrack.h" #include "cache.h" -#include "alarm.h" #include #include diff --git a/src/cache_timer.c b/src/cache_timer.c index 53ed703..0fbba14 100644 --- a/src/cache_timer.c +++ b/src/cache_timer.c @@ -16,12 +16,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include -#include +#include "cache.h" #include "conntrackd.h" #include "us-conntrack.h" -#include "cache.h" #include "alarm.h" +#include "debug.h" + +#include static void timeout(struct alarm_list *a, void *data) { diff --git a/src/cache_wt.c b/src/cache_wt.c index 9d0af0b..8ff8fae 100644 --- a/src/cache_wt.c +++ b/src/cache_wt.c @@ -16,11 +16,11 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "cache.h" #include "netlink.h" -#include -#include "conntrackd.h" #include "us-conntrack.h" -#include "cache.h" + +#include static void add_update(struct us_conntrack *u) { diff --git a/src/conntrack.c b/src/conntrack.c index 7918b3f..5f0cb1a 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -33,9 +33,10 @@ * Ported to the new libnetfilter_conntrack API * */ + +#include "conntrack.h" + #include -#include -#include #include #include #include @@ -43,22 +44,15 @@ #include #include #include -#include #include #include #include #ifdef HAVE_ARPA_INET_H #include #endif -#include -#include #include #include -#include "linux_list.h" -#include "conntrack.h" #include -#include -#include static const char cmdflags[NUMBER_OF_CMD] = {'L','I','U','D','G','F','E','V','h','L','I','D','G','F','E'}; diff --git a/src/hash.c b/src/hash.c index d7724c8..cf64df4 100644 --- a/src/hash.c +++ b/src/hash.c @@ -18,14 +18,12 @@ * Description: generic hash table implementation */ -#include +#include "hash.h" +#include "slist.h" + #include #include -#include #include -#include "slist.h" -#include "hash.h" - struct hashtable_node *hashtable_alloc_node(int datasize, void *data) { diff --git a/src/ignore_pool.c b/src/ignore_pool.c index 5889398..c77a55b 100644 --- a/src/ignore_pool.c +++ b/src/ignore_pool.c @@ -16,14 +16,15 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "ignore.h" #include "jhash.h" #include "hash.h" #include "conntrackd.h" -#include "ignore.h" #include "log.h" -#include +#include #include +#include /* XXX: These should be configurable */ #define IGNORE_POOL_SIZE 128 diff --git a/src/local.c b/src/local.c index d861e12..f0aba1c 100644 --- a/src/local.c +++ b/src/local.c @@ -18,12 +18,13 @@ * Description: UNIX sockets library */ +#include "local.h" + #include #include +#include #include -#include - -#include "local.h" +#include int local_server_create(struct local_conf *conf) { diff --git a/src/log.c b/src/log.c index 35ae0c3..a2d48a4 100644 --- a/src/log.c +++ b/src/log.c @@ -19,16 +19,14 @@ */ #include "log.h" -#include -#include -#include +#include "buffer.h" +#include "conntrackd.h" + #include #include #include #include #include -#include "buffer.h" -#include "conntrackd.h" int init_log(void) { diff --git a/src/main.c b/src/main.c index b860982..3d8cfe9 100644 --- a/src/main.c +++ b/src/main.c @@ -16,17 +16,17 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include "conntrackd.h" #include "log.h" + #include #include #include #include #include -#include -#include "hash.h" -#include "jhash.h" +#include +#include +#include #undef _POSIX_SOURCE #include diff --git a/src/mcast.c b/src/mcast.c index 9684b61..77aa35c 100644 --- a/src/mcast.c +++ b/src/mcast.c @@ -17,19 +17,17 @@ * * Description: multicast socket library */ + +#include "mcast.h" +#include "debug.h" + #include #include -#include #include -#include -#include -#include #include #include #include #include -#include "mcast.h" -#include "debug.h" struct mcast_sock *mcast_server_create(struct mcast_conf *conf) { diff --git a/src/netlink.c b/src/netlink.c index 388407a..0457e8a 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -21,13 +21,7 @@ #include "traffic_stats.h" #include "ignore.h" #include "log.h" -#include -#include -#include -#include "us-conntrack.h" -#include -#include -#include "network.h" +#include "debug.h" int ignore_conntrack(struct nf_conntrack *ct) { diff --git a/src/network.c b/src/network.c index 939e94b..7c7a08a 100644 --- a/src/network.c +++ b/src/network.c @@ -18,11 +18,12 @@ #include "conntrackd.h" #include "network.h" -#include "us-conntrack.h" -#include "sync.h" #include "log.h" +#include "debug.h" #include +#include +#include static unsigned int seq_set, cur_seq; diff --git a/src/parse.c b/src/parse.c index a248b47..5bc71ef 100644 --- a/src/parse.c +++ b/src/parse.c @@ -16,10 +16,10 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include -#include #include "network.h" +#include + static void parse_u8(struct nf_conntrack *ct, int attr, void *data) { uint8_t *value = (uint8_t *) data; diff --git a/src/queue.c b/src/queue.c index a721760..7b20e83 100644 --- a/src/queue.c +++ b/src/queue.c @@ -18,6 +18,10 @@ #include "queue.h" +#include +#include +#include + struct queue *queue_create(size_t max_size) { struct queue *b; diff --git a/src/read_config_lex.l b/src/read_config_lex.l index 6211fee..65df1e7 100644 --- a/src/read_config_lex.l +++ b/src/read_config_lex.l @@ -20,7 +20,6 @@ */ #include "read_config_yy.h" -#include "conntrackd.h" %} %option yylineno diff --git a/src/read_config_yy.y b/src/read_config_yy.y index 82131d7..531b1fe 100644 --- a/src/read_config_yy.y +++ b/src/read_config_yy.y @@ -26,6 +26,7 @@ #include "conntrackd.h" #include "ignore.h" #include +#include extern struct state_replication_helper tcp_state_helper; diff --git a/src/run.c b/src/run.c index cb5116d..9076028 100644 --- a/src/run.c +++ b/src/run.c @@ -23,16 +23,13 @@ #include "ignore.h" #include "log.h" #include "alarm.h" -#include + #include -#include "us-conntrack.h" #include #include #include -#include #include -#include -#include +#include void killer(int foo) { diff --git a/src/stats-mode.c b/src/stats-mode.c index 0c42d95..0ecb2b0 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -18,16 +18,15 @@ #include "netlink.h" #include "traffic_stats.h" -#include +#include "buffer.h" +#include "debug.h" #include "cache.h" #include "log.h" #include "conntrackd.h" -#include -#include + #include -#include "us-conntrack.h" -#include -#include +#include +#include static int init_stats(void) { diff --git a/src/sync-alarm.c b/src/sync-alarm.c index 05ddf81..6ee306e 100644 --- a/src/sync-alarm.c +++ b/src/sync-alarm.c @@ -21,8 +21,11 @@ #include "network.h" #include "us-conntrack.h" #include "alarm.h" +#include "cache.h" +#include "debug.h" #include +#include static void refresher(struct alarm_list *a, void *data) { diff --git a/src/sync-ftfw.c b/src/sync-ftfw.c index f0b3262..f6d2ed3 100644 --- a/src/sync-ftfw.c +++ b/src/sync-ftfw.c @@ -16,18 +16,17 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include "conntrackd.h" #include "sync.h" -#include "linux_list.h" #include "us-conntrack.h" #include "queue.h" #include "debug.h" #include "network.h" #include "alarm.h" #include "log.h" -#include -#include +#include "cache.h" + +#include #if 0 #define dp printf diff --git a/src/sync-mode.c b/src/sync-mode.c index 1632019..0a0fcc2 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -16,22 +16,22 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "sync.h" #include "netlink.h" #include "traffic_stats.h" #include "log.h" -#include +#include "state_helper.h" #include "cache.h" #include "conntrackd.h" -#include -#include -#include #include "us-conntrack.h" -#include -#include -#include "sync.h" #include "network.h" #include "debug.h" + +#include #include +#include +#include +#include static void do_mcast_handler_step(struct nethdr *net) { diff --git a/src/traffic_stats.c b/src/traffic_stats.c index 93511ce..9e40d53 100644 --- a/src/traffic_stats.c +++ b/src/traffic_stats.c @@ -17,14 +17,7 @@ */ #include "traffic_stats.h" -#include "cache.h" -#include "hash.h" #include "conntrackd.h" -#include -#include -#include -#include "us-conntrack.h" -#include void update_traffic_stats(struct nf_conntrack *ct) { -- cgit v1.2.3 From 91d431dacd79d93d671ace690e2e9c7fbb0f2877 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Fri, 18 Jan 2008 13:09:49 +0000 Subject: Max Kellermann : Simplify logging infrastructure --- ChangeLog | 4 +-- doc/stats/conntrackd.conf | 10 ------- include/Makefile.am | 2 +- include/buffer.h | 22 -------------- include/conntrackd.h | 1 - include/log.h | 6 ++-- src/Makefile.am | 2 +- src/buffer.c | 76 ----------------------------------------------- src/cache_iterators.c | 10 +++---- src/ignore_pool.c | 2 +- src/log.c | 34 ++++++--------------- src/main.c | 4 +-- src/netlink.c | 28 ++++++++--------- src/network.c | 2 +- src/read_config_yy.y | 2 +- src/run.c | 24 +++++++-------- src/stats-mode.c | 30 +++++-------------- src/sync-ftfw.c | 8 ++--- src/sync-mode.c | 32 ++++++++++---------- 19 files changed, 78 insertions(+), 221 deletions(-) delete mode 100644 include/buffer.h delete mode 100644 src/buffer.c (limited to 'src/stats-mode.c') diff --git a/ChangeLog b/ChangeLog index a9dfd8b..25c8c38 100644 --- a/ChangeLog +++ b/ChangeLog @@ -31,7 +31,6 @@ 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 ) o obsolete `-S' option: Use information provided by the config file @@ -81,13 +80,12 @@ o always close stdin - even in non-daemon mode, it is of no use o chdir("/") to release the cwd inode o ignore setsid() failure, because there is only one possible and o fix harmless error condition -o add buffer_destroy() to buffer.c o fix memory leaks in several error output paths -o use size_t for buffer sizes o import only required C headers and put local headers on top to check o fix double free() bug in the error output path of mcast_create() o eliminate unsed cache_get_conntrack() in rs_list_to_tx() o remove capability code and rely on the error returned by the syscall +o major simplification of the logging infrastructure o use fputs() instead of fprintf() in log.c version 0.9.5 (2007/07/29) diff --git a/doc/stats/conntrackd.conf b/doc/stats/conntrackd.conf index 8f899b4..4bc5642 100644 --- a/doc/stats/conntrackd.conf +++ b/doc/stats/conntrackd.conf @@ -58,16 +58,6 @@ 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) diff --git a/include/Makefile.am b/include/Makefile.am index ff8611f..e8e7f81 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,7 +1,7 @@ noinst_HEADERS = alarm.h jhash.h slist.h cache.h linux_list.h \ sync.h conntrackd.h local.h us-conntrack.h \ - debug.h log.h hash.h mcast.h buffer.h conntrack.h \ + debug.h log.h hash.h mcast.h conntrack.h \ state_helper.h network.h ignore.h queue.h \ traffic_stats.h netlink.h diff --git a/include/buffer.h b/include/buffer.h deleted file mode 100644 index ab1ccd3..0000000 --- a/include/buffer.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _BUFFER_H_ -#define _BUFFER_H_ - -#include - -struct buffer { - unsigned char *data; - size_t size; - size_t cur_size; -}; - -struct buffer *buffer_create(size_t size); -void buffer_destroy(struct buffer *b); - -int buffer_add(struct buffer *b, void *data, size_t size); -void buffer_flush(struct buffer *b, - void (*cb)(void *buffer_data, - void *data), - void *data); -size_t buffer_size(const struct buffer *b); - -#endif diff --git a/include/conntrackd.h b/include/conntrackd.h index c16d3d7..b223a17 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -132,7 +132,6 @@ 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 64bf1ce..b258633 100644 --- a/include/log.h +++ b/include/log.h @@ -3,13 +3,11 @@ #include -struct buffer; struct nf_conntrack; int init_log(void); -void dlog(FILE *fd, int priority, const char *format, ...); -void dlog_buffered_ct(FILE *fd, struct buffer *b, struct nf_conntrack *ct); -void dlog_buffered_ct_flush(void *buffer_data, void *data); +void dlog(int priority, const char *format, ...); +void dlog_ct(struct nf_conntrack *ct); void close_log(void); #endif diff --git a/src/Makefile.am b/src/Makefile.am index fafb5ff..15628b7 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 buffer.c \ +conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.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 deleted file mode 100644 index 739174a..0000000 --- a/src/buffer.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * (C) 2006-2008 by Pablo Neira Ayuso - * - * 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 "buffer.h" - -#include -#include -#include - -struct buffer *buffer_create(size_t 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; -} - -void buffer_destroy(struct buffer *b) -{ - free(b->data); - free(b); -} - -int buffer_add(struct buffer *b, void *data, size_t size) -{ - if (b->size - b->cur_size < size) { - errno = ENOSPC; - return -1; - } - - memcpy(b->data + b->cur_size, data, size); - b->cur_size += size; - return 0; -} - -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); -} - -size_t buffer_size(const struct buffer *b) -{ - return b->size; -} diff --git a/src/cache_iterators.c b/src/cache_iterators.c index bf70dd1..92b7b7f 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -123,14 +123,14 @@ void cache_commit(struct cache *c) commit_exist = c->commit_exist - commit_exist; /* log results */ - dlog(STATE(log), LOG_NOTICE, "Committed %u new entries", commit_ok); + dlog(LOG_NOTICE, "Committed %u new entries", commit_ok); if (commit_exist) - dlog(STATE(log), LOG_NOTICE, "%u entries ignored, " - "already exist", commit_exist); + dlog(LOG_NOTICE, "%u entries ignored, " + "already exist", commit_exist); if (commit_fail) - dlog(STATE(log), LOG_NOTICE, "%u entries can't be " - "committed", commit_fail); + dlog(LOG_NOTICE, "%u entries can't be " + "committed", commit_fail); } static int do_flush(void *data1, void *data2) diff --git a/src/ignore_pool.c b/src/ignore_pool.c index c77a55b..2d898d1 100644 --- a/src/ignore_pool.c +++ b/src/ignore_pool.c @@ -133,7 +133,7 @@ int ignore_pool_test(struct ignore_pool *ip, struct nf_conntrack *ct) ret = __ignore_pool_test_ipv6(ip, ct); break; default: - dlog(STATE(log), LOG_WARNING, "unknown layer 3 protocol?"); + dlog(LOG_WARNING, "unknown layer 3 protocol?"); break; } diff --git a/src/log.c b/src/log.c index 41b2057..51e757f 100644 --- a/src/log.c +++ b/src/log.c @@ -19,7 +19,6 @@ */ #include "log.h" -#include "buffer.h" #include "conntrackd.h" #include @@ -38,6 +37,8 @@ int init_log(void) strerror(errno)); return -1; } + + setlinebuf(STATE(log)); } if (CONFIG(stats).logfile[0]) { @@ -48,6 +49,8 @@ int init_log(void) strerror(errno)); return -1; } + + setlinebuf(STATE(stats_log)); } if (CONFIG(syslog_facility) != -1 || @@ -57,8 +60,9 @@ int init_log(void) return 0; } -void dlog(FILE *fd, int priority, const char *format, ...) +void dlog(int priority, const char *format, ...) { + FILE *fd = STATE(log); time_t t; char *buf; const char *prio; @@ -100,16 +104,9 @@ void dlog(FILE *fd, int priority, const char *format, ...) } } -void dlog_buffered_ct_flush(void *buffer_data, void *data) -{ - FILE *fd = data; - - fputs((const char*)buffer_data, fd); - fflush(fd); -} - -void dlog_buffered_ct(FILE *fd, struct buffer *b, struct nf_conntrack *ct) +void dlog_ct(struct nf_conntrack *ct) { + FILE *fd = STATE(stats_log); time_t t; char buf[1024]; char *tmp; @@ -122,20 +119,7 @@ void dlog_buffered_ct(FILE *fd, struct buffer *b, struct nf_conntrack *ct) if (fd) { snprintf(buf+strlen(buf), 1024-strlen(buf), "\n"); - /* zero size buffer: force fflush */ - if (buffer_size(b) == 0) { - fputs(buf, fd); - 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! */ - fputs(buf, fd); - fflush(fd); - } - } + fputs(buf, fd); } if (CONFIG(stats).syslog_facility != -1) diff --git a/src/main.c b/src/main.c index 0aa5317..8221564 100644 --- a/src/main.c +++ b/src/main.c @@ -250,9 +250,9 @@ int main(int argc, char *argv[]) close(STDOUT_FILENO); close(STDERR_FILENO); - dlog(STATE(log), LOG_NOTICE, "-- starting in daemon mode --"); + dlog(LOG_NOTICE, "-- starting in daemon mode --"); } else - dlog(STATE(log), LOG_NOTICE, "-- starting in console mode --"); + dlog(LOG_NOTICE, "-- starting in console mode --"); /* * run main process diff --git a/src/netlink.c b/src/netlink.c index 0457e8a..bb94001 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -73,7 +73,7 @@ static int event_handler(enum nf_conntrack_msg_type type, update_traffic_stats(ct); break; default: - dlog(STATE(log), LOG_WARNING, "unknown msg from ctnetlink\n"); + dlog(LOG_WARNING, "unknown msg from ctnetlink\n"); break; } @@ -134,7 +134,7 @@ static int dump_handler(enum nf_conntrack_msg_type type, STATE(mode)->dump(ct); break; default: - dlog(STATE(log), LOG_WARNING, "unknown msg from ctnetlink"); + dlog(LOG_WARNING, "unknown msg from ctnetlink"); break; } return NFCT_CB_CONTINUE; @@ -167,15 +167,15 @@ void nl_resize_socket_buffer(struct nfct_handle *h) return; if (s > CONFIG(netlink_buffer_size_max_grown)) { - dlog(STATE(log), LOG_WARNING, - "maximum netlink socket buffer " - "size has been reached. We are likely to " - "be losing events, this may lead to " - "unsynchronized replicas. Please, consider " - "increasing netlink socket buffer size via " - "SocketBufferSize and " - "SocketBufferSizeMaxGrown clauses in " - "conntrackd.conf"); + dlog(LOG_WARNING, + "maximum netlink socket buffer " + "size has been reached. We are likely to " + "be losing events, this may lead to " + "unsynchronized replicas. Please, consider " + "increasing netlink socket buffer size via " + "SocketBufferSize and " + "SocketBufferSizeMaxGrown clauses in " + "conntrackd.conf"); s = CONFIG(netlink_buffer_size_max_grown); warned = 1; } @@ -183,9 +183,9 @@ void nl_resize_socket_buffer(struct nfct_handle *h) CONFIG(netlink_buffer_size) = nfnl_rcvbufsiz(nfct_nfnlh(h), s); /* notify the sysadmin */ - dlog(STATE(log), LOG_NOTICE, "netlink socket buffer size " - "has been set to %u bytes", - CONFIG(netlink_buffer_size)); + dlog(LOG_NOTICE, "netlink socket buffer size " + "has been set to %u bytes", + CONFIG(netlink_buffer_size)); } int nl_dump_conntrack_table(void) diff --git a/src/network.c b/src/network.c index 7c7a08a..da26545 100644 --- a/src/network.c +++ b/src/network.c @@ -222,7 +222,7 @@ int mcast_track_seq(uint32_t seq, uint32_t *exp_seq) /* out of sequence: replayed/delayed packet? */ if (before(seq, STATE_SYNC(last_seq_recv)+1)) - dlog(STATE(log), LOG_WARNING, "delayed packet? exp=%u rcv=%u", + dlog(LOG_WARNING, "delayed packet? exp=%u rcv=%u", STATE_SYNC(last_seq_recv)+1, seq); out: diff --git a/src/read_config_yy.y b/src/read_config_yy.y index 531b1fe..0ba5331 100644 --- a/src/read_config_yy.y +++ b/src/read_config_yy.y @@ -635,7 +635,7 @@ stat_syslog_facility : T_SYSLOG T_STRING buffer_size: T_STAT_BUFFER_SIZE T_NUMBER { - conf.stats.buffer_size = $2; + fprintf(stderr, "WARNING: LogFileBufferSize is deprecated.\n"); }; %% diff --git a/src/run.c b/src/run.c index 9076028..a5b6a79 100644 --- a/src/run.c +++ b/src/run.c @@ -43,7 +43,7 @@ void killer(int foo) local_server_destroy(STATE(local), CONFIG(local).path); STATE(mode)->kill(); unlink(CONFIG(lockfile)); - dlog(STATE(log), LOG_NOTICE, "---- shutdown received ----"); + dlog(LOG_NOTICE, "---- shutdown received ----"); close_log(); sigprocmask(SIG_UNBLOCK, &STATE(block), NULL); @@ -63,7 +63,7 @@ void local_handler(int fd, void *data) ret = read(fd, &type, sizeof(type)); if (ret == -1) { - dlog(STATE(log), LOG_ERR, "can't read from unix socket"); + dlog(LOG_ERR, "can't read from unix socket"); return; } if (ret == 0) @@ -71,7 +71,7 @@ void local_handler(int fd, void *data) switch(type) { case FLUSH_MASTER: - dlog(STATE(log), LOG_WARNING, "`conntrackd -F' is deprecated. " + dlog(LOG_WARNING, "`conntrackd -F' is deprecated. " "Use conntrack -F instead."); if (fork() == 0) { execlp("conntrack", "conntrack", "-F", NULL); @@ -79,13 +79,13 @@ void local_handler(int fd, void *data) } return; case RESYNC_MASTER: - dlog(STATE(log), LOG_NOTICE, "resync with master table"); + dlog(LOG_NOTICE, "resync with master table"); nl_dump_conntrack_table(); return; } if (!STATE(mode)->local(fd, type, data)) - dlog(STATE(log), LOG_WARNING, "unknown local request %d", type); + dlog(LOG_WARNING, "unknown local request %d", type); } int @@ -104,25 +104,25 @@ init(void) /* Initialization */ if (STATE(mode)->init() == -1) { - dlog(STATE(log), LOG_ERR, "initialization failed"); + dlog(LOG_ERR, "initialization failed"); return -1; } /* local UNIX socket */ STATE(local) = local_server_create(&CONFIG(local)); if (!STATE(local)) { - dlog(STATE(log), LOG_ERR, "can't open unix socket!"); + dlog(LOG_ERR, "can't open unix socket!"); return -1; } if (nl_init_event_handler() == -1) { - dlog(STATE(log), LOG_ERR, "can't open netlink handler! " + dlog(LOG_ERR, "can't open netlink handler! " "no ctnetlink kernel support?"); return -1; } if (nl_init_dump_handler() == -1) { - dlog(STATE(log), LOG_ERR, "can't open netlink handler! " + dlog(LOG_ERR, "can't open netlink handler! " "no ctnetlink kernel support?"); return -1; } @@ -146,7 +146,7 @@ init(void) if (signal(SIGCHLD, child) == SIG_ERR) return -1; - dlog(STATE(log), LOG_NOTICE, "initialization completed"); + dlog(LOG_NOTICE, "initialization completed"); return 0; } @@ -171,7 +171,7 @@ static int __run(struct timeval *next_alarm) if (errno == EINTR) return 0; - dlog(STATE(log), LOG_WARNING, + dlog(LOG_WARNING, "select failed: %s", strerror(errno)); return 0; } @@ -213,7 +213,7 @@ static int __run(struct timeval *next_alarm) case EAGAIN: break; default: - dlog(STATE(log), LOG_WARNING, + dlog(LOG_WARNING, "event catch says: %s", strerror(errno)); break; } diff --git a/src/stats-mode.c b/src/stats-mode.c index 0ecb2b0..9e6089c 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -18,7 +18,6 @@ #include "netlink.h" #include "traffic_stats.h" -#include "buffer.h" #include "debug.h" #include "cache.h" #include "log.h" @@ -32,27 +31,19 @@ static int init_stats(void) { state.stats = malloc(sizeof(struct ct_stats_state)); if (!state.stats) { - dlog(STATE(log), LOG_ERR, "can't allocate memory for stats"); + dlog(LOG_ERR, "can't allocate memory for stats"); return -1; } 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"); - free(state.stats); - return -1; - } - STATE_STATS(cache) = cache_create("stats", LIFETIME, CONFIG(family), NULL); if (!STATE_STATS(cache)) { - dlog(STATE(log), LOG_ERR, "can't allocate memory for the " - "external cache"); + dlog(LOG_ERR, "can't allocate memory for the " + "external cache"); free(state.stats); - buffer_destroy(STATE_STATS(buffer_log)); return -1; } @@ -62,11 +53,6 @@ static int init_stats(void) static void kill_stats(void) { cache_destroy(STATE_STATS(cache)); - /* flush the buffer before exiting */ - if (STATE(stats_log) != NULL) - buffer_flush(STATE_STATS(buffer_log), - dlog_buffered_ct_flush, - STATE(stats_log)); } /* handler for requests coming via UNIX socket */ @@ -82,7 +68,7 @@ static int local_handler_stats(int fd, int type, void *data) cache_dump(STATE_STATS(cache), fd, NFCT_O_XML); break; case FLUSH_CACHE: - dlog(STATE(log), LOG_NOTICE, "flushing caches"); + dlog(LOG_NOTICE, "flushing caches"); cache_flush(STATE_STATS(cache)); break; case KILL: @@ -138,7 +124,7 @@ static void overrun_stats(void) h = nfct_open(CONNTRACK, 0); if (!h) { - dlog(STATE(log), LOG_ERR, "can't open overrun handler"); + dlog(LOG_ERR, "can't open overrun handler"); return; } @@ -148,7 +134,7 @@ static void overrun_stats(void) ret = nfct_query(h, NFCT_Q_DUMP, &family); if (ret == -1) - dlog(STATE(log), LOG_ERR, + dlog(LOG_ERR, "overrun query error %s", strerror(errno)); nfct_close(h); @@ -162,7 +148,7 @@ static void event_new_stats(struct nf_conntrack *ct) debug_ct(ct, "cache new"); } else { if (errno != EEXIST) { - dlog(STATE(log), LOG_ERR, + dlog(LOG_ERR, "can't add to cache cache: %s\n", strerror(errno)); debug_ct(ct, "can't add"); } @@ -186,7 +172,7 @@ static int event_destroy_stats(struct nf_conntrack *ct) if (cache_del(STATE_STATS(cache), ct)) { debug_ct(ct, "cache destroy"); - dlog_buffered_ct(STATE(stats_log), STATE_STATS(buffer_log), ct); + dlog_ct(ct); return 1; } else { debug_ct(ct, "can't destroy!"); diff --git a/src/sync-ftfw.c b/src/sync-ftfw.c index f6d2ed3..94df5f9 100644 --- a/src/sync-ftfw.c +++ b/src/sync-ftfw.c @@ -98,13 +98,13 @@ static int ftfw_init(void) { tx_queue = queue_create(CONFIG(resend_queue_size)); if (tx_queue == NULL) { - dlog(STATE(log), LOG_ERR, "cannot create tx queue"); + dlog(LOG_ERR, "cannot create tx queue"); return -1; } rs_queue = queue_create(CONFIG(resend_queue_size)); if (rs_queue == NULL) { - dlog(STATE(log), LOG_ERR, "cannot create rs queue"); + dlog(LOG_ERR, "cannot create rs queue"); return -1; } @@ -143,11 +143,11 @@ static int ftfw_local(int fd, int type, void *data) switch(type) { case REQUEST_DUMP: - dlog(STATE(log), LOG_NOTICE, "request resync"); + dlog(LOG_NOTICE, "request resync"); tx_queue_add_ctlmsg(NET_F_RESYNC, 0, 0); break; case SEND_BULK: - dlog(STATE(log), LOG_NOTICE, "sending bulk update"); + dlog(LOG_NOTICE, "sending bulk update"); cache_iterate(STATE_SYNC(internal), NULL, do_cache_to_tx); break; default: diff --git a/src/sync-mode.c b/src/sync-mode.c index dc8e782..4b2fad7 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -80,7 +80,7 @@ retry: debug_ct(ct, "can't destroy"); break; default: - dlog(STATE(log), LOG_ERR, "mcast unknown query %d\n", query); + dlog(LOG_ERR, "mcast unknown query %d\n", query); break; } } @@ -100,7 +100,7 @@ static void mcast_handler(void) struct nethdr *net = (struct nethdr *) ptr; if (ntohs(net->len) > remain) { - dlog(STATE(log), LOG_ERR, "fragmented messages"); + dlog(LOG_ERR, "fragmented messages"); break; } @@ -122,7 +122,7 @@ static int init_sync(void) { state.sync = malloc(sizeof(struct ct_sync_state)); if (!state.sync) { - dlog(STATE(log), LOG_ERR, "can't allocate memory for sync"); + dlog(LOG_ERR, "can't allocate memory for sync"); return -1; } memset(state.sync, 0, sizeof(struct ct_sync_state)); @@ -148,8 +148,8 @@ static int init_sync(void) STATE_SYNC(sync)->internal_cache_extra); if (!STATE_SYNC(internal)) { - dlog(STATE(log), LOG_ERR, "can't allocate memory for " - "the internal cache"); + dlog(LOG_ERR, "can't allocate memory for " + "the internal cache"); return -1; } @@ -164,28 +164,28 @@ static int init_sync(void) NULL); if (!STATE_SYNC(external)) { - dlog(STATE(log), LOG_ERR, "can't allocate memory for the " - "external cache"); + dlog(LOG_ERR, "can't allocate memory for the " + "external cache"); return -1; } /* multicast server to receive events from the wire */ STATE_SYNC(mcast_server) = mcast_server_create(&CONFIG(mcast)); if (STATE_SYNC(mcast_server) == NULL) { - dlog(STATE(log), LOG_ERR, "can't open multicast server!"); + dlog(LOG_ERR, "can't open multicast server!"); return -1; } /* multicast client to send events on the wire */ STATE_SYNC(mcast_client) = mcast_client_create(&CONFIG(mcast)); if (STATE_SYNC(mcast_client) == NULL) { - dlog(STATE(log), LOG_ERR, "can't open client multicast socket"); + dlog(LOG_ERR, "can't open client multicast socket"); mcast_server_destroy(STATE_SYNC(mcast_server)); return -1; } if (mcast_buffered_init(&CONFIG(mcast)) == -1) { - dlog(STATE(log), LOG_ERR, "can't init tx buffer!"); + dlog(LOG_ERR, "can't init tx buffer!"); mcast_server_destroy(STATE_SYNC(mcast_server)); mcast_client_destroy(STATE_SYNC(mcast_client)); return -1; @@ -282,14 +282,14 @@ static int local_handler_sync(int fd, int type, void *data) case COMMIT: ret = fork(); if (ret == 0) { - dlog(STATE(log), LOG_NOTICE, + dlog(LOG_NOTICE, "committing external cache"); cache_commit(STATE_SYNC(external)); exit(EXIT_SUCCESS); } break; case FLUSH_CACHE: - dlog(STATE(log), LOG_NOTICE, "flushing caches"); + dlog(LOG_NOTICE, "flushing caches"); cache_flush(STATE_SYNC(internal)); cache_flush(STATE_SYNC(external)); break; @@ -416,7 +416,7 @@ static void overrun_sync(void) h = nfct_open(CONNTRACK, 0); if (!h) { - dlog(STATE(log), LOG_ERR, "can't open overrun handler"); + dlog(LOG_ERR, "can't open overrun handler"); return; } @@ -424,7 +424,7 @@ static void overrun_sync(void) ret = nfct_query(h, NFCT_Q_DUMP, &family); if (ret == -1) - dlog(STATE(log), LOG_ERR, + dlog(LOG_ERR, "overrun query error %s", strerror(errno)); nfct_callback_unregister(h); @@ -457,8 +457,8 @@ retry: goto retry; } - dlog(STATE(log), LOG_ERR, "can't add to internal cache: " - "%s\n", strerror(errno)); + dlog(LOG_ERR, "can't add to internal cache: " + "%s\n", strerror(errno)); debug_ct(ct, "can't add"); } } -- cgit v1.2.3 From 6f7bc84fb819e87a9145394b0e08fd194b1497da Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Sat, 2 Feb 2008 04:35:05 +0000 Subject: add IPv6 support to conntrackd --- ChangeLog | 1 + TODO | 2 +- include/cache.h | 2 +- include/ignore.h | 5 ++- include/mcast.h | 3 +- src/cache.c | 107 ++++++++++++++++++++++++++++++++------------------- src/ignore_pool.c | 65 ++++++++++++++++++------------- src/mcast.c | 18 +++++---- src/read_config_yy.y | 99 ++++++++++++++++++++++++++++++++++------------- src/stats-mode.c | 1 - src/sync-mode.c | 2 - 11 files changed, 197 insertions(+), 108 deletions(-) (limited to 'src/stats-mode.c') diff --git a/ChangeLog b/ChangeLog index dc4efab..aa9b3d2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,7 @@ o cleanup error message o add support for -E -o xml,timestamp = conntrackd = +o Add IPv6 support o Remove window tracking disabling limitation (requires Linux kernel >= 2.6.22) o syslog support (based on patch from Simon Lodal) o add CacheWriteThrough clause: external cache write through policy diff --git a/TODO b/TODO index 04923fc..9450aeb 100644 --- a/TODO +++ b/TODO @@ -18,7 +18,7 @@ by dificulty levels: = Requires some work = [ ] study better keepalived transitions - [ ] test/fix ipv6 support + [X] fix ipv6 support [X] add support setup related conntracks [ ] NAT sequence adjustment support diff --git a/include/cache.h b/include/cache.h index a2b2005..f5afbe5 100644 --- a/include/cache.h +++ b/include/cache.h @@ -75,7 +75,7 @@ struct cache_extra { struct nf_conntrack; -struct cache *cache_create(const char *name, unsigned int features, uint8_t proto, struct cache_extra *extra); +struct cache *cache_create(const char *name, unsigned int features, struct cache_extra *extra); void cache_destroy(struct cache *e); struct us_conntrack *cache_add(struct cache *c, struct nf_conntrack *ct); diff --git a/include/ignore.h b/include/ignore.h index efb375d..e5e96ff 100644 --- a/include/ignore.h +++ b/include/ignore.h @@ -7,11 +7,12 @@ struct nf_conntrack; struct ignore_pool { struct hashtable *h; + struct hashtable *h6; }; -struct ignore_pool *ignore_pool_create(uint8_t family); +struct ignore_pool *ignore_pool_create(void); void ignore_pool_destroy(struct ignore_pool *ip); -int ignore_pool_add(struct ignore_pool *ip, void *data); +int ignore_pool_add(struct ignore_pool *ip, void *data, uint8_t family); int ignore_pool_test(struct ignore_pool *ip, struct nf_conntrack *ct); #endif diff --git a/include/mcast.h b/include/mcast.h index 4e89c72..c2fd3ec 100644 --- a/include/mcast.h +++ b/include/mcast.h @@ -16,7 +16,7 @@ struct mcast_conf { } in; union { struct in_addr interface_addr; - struct in6_addr interface_addr6; + unsigned int interface_index6; } ifa; int mtu; char iface[IFNAMSIZ]; @@ -34,6 +34,7 @@ struct mcast_sock { struct sockaddr_in ipv4; struct sockaddr_in6 ipv6; } addr; + socklen_t sockaddr_len; struct mcast_stats stats; }; diff --git a/src/cache.c b/src/cache.c index 2f0e57a..73d539a 100644 --- a/src/cache.c +++ b/src/cache.c @@ -19,6 +19,7 @@ #include "cache.h" #include "jhash.h" #include "hash.h" +#include "log.h" #include "us-conntrack.h" #include "conntrackd.h" @@ -27,11 +28,9 @@ #include #include -static uint32_t hash(const void *data, struct hashtable *table) +static uint32_t __hash4(const struct nf_conntrack *ct, struct hashtable *table) { unsigned int a, b; - const struct us_conntrack *u = data; - struct nf_conntrack *ct = u->ct; a = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC), sizeof(uint32_t), ((nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16) | @@ -51,11 +50,9 @@ static uint32_t hash(const void *data, struct hashtable *table) return ((uint64_t)jhash_2words(a, b, 0) * table->hashsize) >> 32; } -static uint32_t hash6(const void *data, struct hashtable *table) +static uint32_t __hash6(const struct nf_conntrack *ct, struct hashtable *table) { unsigned int a, b; - const struct us_conntrack *u = data; - struct nf_conntrack *ct = u->ct; a = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV6_SRC), sizeof(uint32_t)*4, ((nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16) | @@ -68,12 +65,30 @@ static uint32_t hash6(const void *data, struct hashtable *table) return ((uint64_t)jhash_2words(a, b, 0) * table->hashsize) >> 32; } +static uint32_t hash(const void *data, struct hashtable *table) +{ + int ret = 0; + const struct us_conntrack *u = data; + + switch(nfct_get_attr_u8(u->ct, ATTR_L3PROTO)) { + case AF_INET: + ret = __hash4(u->ct, table); + break; + case AF_INET6: + ret = __hash6(u->ct, table); + break; + default: + dlog(LOG_ERR, "unknown layer 3 proto in hash"); + break; + } + + return ret; +} + static int __compare(const struct nf_conntrack *ct1, const struct nf_conntrack *ct2) { - return ((nfct_get_attr_u8(ct1, ATTR_ORIG_L3PROTO) == - nfct_get_attr_u8(ct2, ATTR_ORIG_L3PROTO)) && - (nfct_get_attr_u8(ct1, ATTR_ORIG_L4PROTO) == + return ((nfct_get_attr_u8(ct1, ATTR_ORIG_L4PROTO) == nfct_get_attr_u8(ct2, ATTR_ORIG_L4PROTO)) && (nfct_get_attr_u16(ct1, ATTR_ORIG_PORT_SRC) == nfct_get_attr_u16(ct2, ATTR_ORIG_PORT_SRC)) && @@ -85,11 +100,9 @@ static int __compare(const struct nf_conntrack *ct1, nfct_get_attr_u16(ct2, ATTR_REPL_PORT_DST))); } -static int compare(const void *data1, const void *data2) +static int +__compare4(const struct us_conntrack *u1, const struct us_conntrack *u2) { - const struct us_conntrack *u1 = data1; - const struct us_conntrack *u2 = data2; - return ((nfct_get_attr_u32(u1->ct, ATTR_ORIG_IPV4_SRC) == nfct_get_attr_u32(u2->ct, ATTR_ORIG_IPV4_SRC)) && (nfct_get_attr_u32(u1->ct, ATTR_ORIG_IPV4_DST) == @@ -101,20 +114,46 @@ static int compare(const void *data1, const void *data2) __compare(u1->ct, u2->ct)); } -static int compare6(const void *data1, const void *data2) +static int +__compare6(const struct us_conntrack *u1, const struct us_conntrack *u2) { + return ((memcmp(nfct_get_attr(u1->ct, ATTR_ORIG_IPV6_SRC), + nfct_get_attr(u2->ct, ATTR_ORIG_IPV6_SRC), + sizeof(uint32_t)*4) == 0) && + (memcmp(nfct_get_attr(u1->ct, ATTR_ORIG_IPV6_DST), + nfct_get_attr(u2->ct, ATTR_ORIG_IPV6_DST), + sizeof(uint32_t)*4) == 0) && + (memcmp(nfct_get_attr(u1->ct, ATTR_REPL_IPV6_SRC), + nfct_get_attr(u2->ct, ATTR_REPL_IPV6_SRC), + sizeof(uint32_t)*4) == 0) && + (memcmp(nfct_get_attr(u1->ct, ATTR_REPL_IPV6_DST), + nfct_get_attr(u2->ct, ATTR_REPL_IPV6_DST), + sizeof(uint32_t)*4) == 0) && + __compare(u1->ct, u2->ct)); +} + +static int compare(const void *data1, const void *data2) +{ + int ret = 0; const struct us_conntrack *u1 = data1; const struct us_conntrack *u2 = data2; - return ((nfct_get_attr_u32(u1->ct, ATTR_ORIG_IPV6_SRC) == - nfct_get_attr_u32(u2->ct, ATTR_ORIG_IPV6_SRC)) && - (nfct_get_attr_u32(u1->ct, ATTR_ORIG_IPV6_DST) == - nfct_get_attr_u32(u2->ct, ATTR_ORIG_IPV6_DST)) && - (nfct_get_attr_u32(u1->ct, ATTR_REPL_IPV6_SRC) == - nfct_get_attr_u32(u2->ct, ATTR_REPL_IPV6_SRC)) && - (nfct_get_attr_u32(u1->ct, ATTR_REPL_IPV6_DST) == - nfct_get_attr_u32(u2->ct, ATTR_REPL_IPV6_DST)) && - __compare(u1->ct, u2->ct)); + if (nfct_get_attr_u8(u1->ct, ATTR_L3PROTO) != + nfct_get_attr_u8(u2->ct, ATTR_L3PROTO)) + return ret; + + switch(nfct_get_attr_u8(u1->ct, ATTR_L3PROTO)) { + case AF_INET: + ret = __compare4(u1, u2); + break; + case AF_INET6: + ret = __compare6(u1, u2); + break; + default: + dlog(LOG_ERR, "unknown layer 3 in compare"); + break; + } + return ret; } struct cache_feature *cache_feature[CACHE_MAX_FEATURE] = { @@ -125,7 +164,6 @@ struct cache_feature *cache_feature[CACHE_MAX_FEATURE] = { struct cache *cache_create(const char *name, unsigned int features, - uint8_t proto, struct cache_extra *extra) { size_t size = sizeof(struct us_conntrack); @@ -175,22 +213,11 @@ struct cache *cache_create(const char *name, } memcpy(c->feature_offset, feature_offset, sizeof(unsigned int) * j); - switch(proto) { - case AF_INET: - c->h = hashtable_create(CONFIG(hashsize), - CONFIG(limit), - size, - hash, - compare); - break; - case AF_INET6: - c->h = hashtable_create(CONFIG(hashsize), - CONFIG(limit), - size, - hash6, - compare6); - break; - } + c->h = hashtable_create(CONFIG(hashsize), + CONFIG(limit), + size, + hash, + compare); if (!c->h) { free(c->features); diff --git a/src/ignore_pool.c b/src/ignore_pool.c index 2d898d1..027d628 100644 --- a/src/ignore_pool.c +++ b/src/ignore_pool.c @@ -26,7 +26,7 @@ #include #include -/* XXX: These should be configurable */ +/* XXX: These should be configurable, better use a rb-tree */ #define IGNORE_POOL_SIZE 128 #define IGNORE_POOL_LIMIT INT_MAX @@ -55,7 +55,7 @@ static int compare6(const void *data1, const void *data2) return memcmp(data1, data2, sizeof(uint32_t)*4) == 0; } -struct ignore_pool *ignore_pool_create(uint8_t proto) +struct ignore_pool *ignore_pool_create(void) { struct ignore_pool *ip; @@ -64,24 +64,23 @@ struct ignore_pool *ignore_pool_create(uint8_t proto) return NULL; memset(ip, 0, sizeof(struct ignore_pool)); - switch(proto) { - case AF_INET: - ip->h = hashtable_create(IGNORE_POOL_SIZE, - IGNORE_POOL_LIMIT, - sizeof(uint32_t), - hash, - compare); - break; - case AF_INET6: - ip->h = hashtable_create(IGNORE_POOL_SIZE, - IGNORE_POOL_LIMIT, - sizeof(uint32_t)*4, - hash6, - compare6); - break; + ip->h = hashtable_create(IGNORE_POOL_SIZE, + IGNORE_POOL_LIMIT, + sizeof(uint32_t), + hash, + compare); + if (!ip->h) { + free(ip); + return NULL; } - if (!ip->h) { + ip->h6 = hashtable_create(IGNORE_POOL_SIZE, + IGNORE_POOL_LIMIT, + sizeof(uint32_t)*4, + hash6, + compare6); + if (!ip->h6) { + free(ip->h); free(ip); return NULL; } @@ -92,20 +91,31 @@ struct ignore_pool *ignore_pool_create(uint8_t proto) void ignore_pool_destroy(struct ignore_pool *ip) { hashtable_destroy(ip->h); + hashtable_destroy(ip->h6); free(ip); } -int ignore_pool_add(struct ignore_pool *ip, void *data) +int ignore_pool_add(struct ignore_pool *ip, void *data, uint8_t family) { - if (!hashtable_add(ip->h, data)) - return 0; - + switch(family) { + case AF_INET: + if (!hashtable_add(ip->h, data)) + return 0; + break; + case AF_INET6: + if (!hashtable_add(ip->h6, data)) + return 0; + break; + } return 1; } static int __ignore_pool_test_ipv4(struct ignore_pool *ip, struct nf_conntrack *ct) { + if (!ip->h) + return 0; + return (hashtable_test(ip->h, nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC)) || hashtable_test(ip->h, nfct_get_attr(ct, ATTR_ORIG_IPV4_DST)) || hashtable_test(ip->h, nfct_get_attr(ct, ATTR_REPL_IPV4_SRC)) || @@ -115,10 +125,13 @@ __ignore_pool_test_ipv4(struct ignore_pool *ip, struct nf_conntrack *ct) static int __ignore_pool_test_ipv6(struct ignore_pool *ip, struct nf_conntrack *ct) { - return (hashtable_test(ip->h, nfct_get_attr(ct, ATTR_ORIG_IPV6_SRC)) || - hashtable_test(ip->h, nfct_get_attr(ct, ATTR_ORIG_IPV6_DST)) || - hashtable_test(ip->h, nfct_get_attr(ct, ATTR_REPL_IPV6_SRC)) || - hashtable_test(ip->h, nfct_get_attr(ct, ATTR_REPL_IPV6_DST))); + if (!ip->h6) + return 0; + + return (hashtable_test(ip->h6, nfct_get_attr(ct, ATTR_ORIG_IPV6_SRC)) || + hashtable_test(ip->h6, nfct_get_attr(ct, ATTR_ORIG_IPV6_DST)) || + hashtable_test(ip->h6, nfct_get_attr(ct, ATTR_REPL_IPV6_SRC)) || + hashtable_test(ip->h6, nfct_get_attr(ct, ATTR_REPL_IPV6_DST))); } int ignore_pool_test(struct ignore_pool *ip, struct nf_conntrack *ct) diff --git a/src/mcast.c b/src/mcast.c index 8307f26..f945511 100644 --- a/src/mcast.c +++ b/src/mcast.c @@ -51,17 +51,20 @@ struct mcast_sock *mcast_server_create(struct mcast_conf *conf) m->addr.ipv4.sin_family = AF_INET; m->addr.ipv4.sin_port = htons(conf->port); m->addr.ipv4.sin_addr.s_addr = htonl(INADDR_ANY); + + m->sockaddr_len = sizeof(struct sockaddr_in); break; case AF_INET6: memcpy(&mreq.ipv6.ipv6mr_multiaddr, &conf->in.inet_addr6, sizeof(uint32_t) * 4); - memcpy(&mreq.ipv6.ipv6mr_interface, &conf->ifa.interface_addr6, - sizeof(uint32_t) * 4); + mreq.ipv6.ipv6mr_interface = conf->ifa.interface_index6; m->addr.ipv6.sin6_family = AF_INET6; m->addr.ipv6.sin6_port = htons(conf->port); m->addr.ipv6.sin6_addr = in6addr_any; + + m->sockaddr_len = sizeof(struct sockaddr_in6); break; } @@ -93,8 +96,7 @@ struct mcast_sock *mcast_server_create(struct mcast_conf *conf) return NULL; } - if (bind(m->fd, (struct sockaddr *) &m->addr, - sizeof(struct sockaddr)) == -1) { + if (bind(m->fd, (struct sockaddr *) &m->addr, m->sockaddr_len) == -1) { debug("mcast_sock_server_create:bind"); close(m->fd); free(m); @@ -139,6 +141,7 @@ __mcast_client_create_ipv4(struct mcast_sock *m, struct mcast_conf *conf) m->addr.ipv4.sin_family = AF_INET; m->addr.ipv4.sin_port = htons(conf->port); m->addr.ipv4.sin_addr = conf->in.inet_addr; + m->sockaddr_len = sizeof(struct sockaddr_in); if (setsockopt(m->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &no, sizeof(int)) < 0) { @@ -168,6 +171,7 @@ __mcast_client_create_ipv6(struct mcast_sock *m, struct mcast_conf *conf) memcpy(&m->addr.ipv6.sin6_addr, &conf->in.inet_addr6, sizeof(struct in6_addr)); + m->sockaddr_len = sizeof(struct sockaddr_in6); if (setsockopt(m->fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &no, sizeof(int)) < 0) { @@ -177,8 +181,8 @@ __mcast_client_create_ipv6(struct mcast_sock *m, struct mcast_conf *conf) } if (setsockopt(m->fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, - &conf->ifa.interface_addr, - sizeof(struct in_addr)) == -1) { + &conf->ifa.interface_index6, + sizeof(unsigned int)) == -1) { debug("mcast_sock_client_create:setsockopt3"); close(m->fd); return -1; @@ -247,7 +251,7 @@ ssize_t mcast_send(struct mcast_sock *m, void *data, int size) size, 0, (struct sockaddr *) &m->addr, - sizeof(struct sockaddr)); + m->sockaddr_len); if (ret == -1) { debug("mcast_sock_send"); m->stats.error++; diff --git a/src/read_config_yy.y b/src/read_config_yy.y index 0ba5331..86fee9b 100644 --- a/src/read_config_yy.y +++ b/src/read_config_yy.y @@ -177,37 +177,63 @@ ignore_traffic_options : ignore_traffic_option : T_IPV4_ADDR T_IP { union inet_address ip; - int family = 0; memset(&ip, 0, sizeof(union inet_address)); - if (inet_aton($2, &ip.ipv4)) - family = AF_INET; -#ifdef HAVE_INET_PTON_IPV6 - else if (inet_pton(AF_INET6, $2, &ip.ipv6) > 0) - family = AF_INET6; -#endif + if (!inet_aton($2, &ip.ipv4)) { + fprintf(stderr, "%s is not a valid IPv4, ignoring", $2); + break; + } + + if (!STATE(ignore_pool)) { + STATE(ignore_pool) = ignore_pool_create(); + if (!STATE(ignore_pool)) { + fprintf(stderr, "Can't create ignore pool!\n"); + exit(EXIT_FAILURE); + } + } + + if (!ignore_pool_add(STATE(ignore_pool), &ip, AF_INET)) { + if (errno == EEXIST) + fprintf(stderr, "IP %s is repeated " + "in the ignore pool\n", $2); + if (errno == ENOSPC) + fprintf(stderr, "Too many IP in the ignore pool!\n"); + } +}; - if (!family) { - fprintf(stderr, "%s is not a valid IP, ignoring", $2); +ignore_traffic_option : T_IPV6_ADDR T_IP +{ + union inet_address ip; + + memset(&ip, 0, sizeof(union inet_address)); + +#ifdef HAVE_INET_PTON_IPV6 + if (inet_pton(AF_INET6, $2, &ip.ipv6) <= 0) { + fprintf(stderr, "%s is not a valid IPv6, ignoring", $2); break; } +#else + fprintf(stderr, "Cannot find inet_pton(), IPv6 unsupported!"); + break; +#endif if (!STATE(ignore_pool)) { - STATE(ignore_pool) = ignore_pool_create(family); + STATE(ignore_pool) = ignore_pool_create(); if (!STATE(ignore_pool)) { fprintf(stderr, "Can't create ignore pool!\n"); exit(EXIT_FAILURE); } } - if (!ignore_pool_add(STATE(ignore_pool), &ip)) { + if (!ignore_pool_add(STATE(ignore_pool), &ip, AF_INET6)) { if (errno == EEXIST) fprintf(stderr, "IP %s is repeated " "in the ignore pool\n", $2); if (errno == ENOSPC) fprintf(stderr, "Too many IP in the ignore pool!\n"); } + }; multicast_line : T_MULTICAST '{' multicast_options '}'; @@ -235,8 +261,13 @@ multicast_option : T_IPV4_ADDR T_IP multicast_option : T_IPV6_ADDR T_IP { #ifdef HAVE_INET_PTON_IPV6 - if (inet_pton(AF_INET6, $2, &conf.mcast.in) <= 0) + if (inet_pton(AF_INET6, $2, &conf.mcast.in) <= 0) { fprintf(stderr, "%s is not a valid IPv6 address\n", $2); + break; + } +#else + fprintf(stderr, "Cannot find inet_pton(), IPv6 unsupported!"); + break; #endif if (conf.mcast.ipproto == AF_INET) { @@ -247,6 +278,19 @@ multicast_option : T_IPV6_ADDR T_IP } conf.mcast.ipproto = AF_INET6; + + if (conf.mcast.iface[0] && !conf.mcast.ifa.interface_index6) { + unsigned int idx; + + idx = if_nametoindex($2); + if (!idx) { + fprintf(stderr, "%s is an invalid interface.\n", $2); + break; + } + + conf.mcast.ifa.interface_index6 = idx; + conf.mcast.ipproto = AF_INET6; + } }; multicast_option : T_IPV4_IFACE T_IP @@ -268,24 +312,25 @@ multicast_option : T_IPV4_IFACE T_IP multicast_option : T_IPV6_IFACE T_IP { -#ifdef HAVE_INET_PTON_IPV6 - if (inet_pton(AF_INET6, $2, &conf.mcast.ifa) <= 0) - fprintf(stderr, "%s is not a valid IPv6 address\n", $2); -#endif - - if (conf.mcast.ipproto == AF_INET) { - fprintf(stderr, "Your multicast interface is IPv6 but " - "is binded to an IPv4 interface? Surely " - "this is not what you want\n"); - break; - } - - conf.mcast.ipproto = AF_INET6; -}; + fprintf(stderr, "IPv6_interface not required for IPv6, ignoring.\n"); +} multicast_option : T_IFACE T_STRING { strncpy(conf.mcast.iface, $2, IFNAMSIZ); + + if (conf.mcast.ipproto == AF_INET6) { + unsigned int idx; + + idx = if_nametoindex($2); + if (!idx) { + fprintf(stderr, "%s is an invalid interface.\n", $2); + break; + } + + conf.mcast.ifa.interface_index6 = idx; + conf.mcast.ipproto = AF_INET6; + } }; multicast_option : T_BACKLOG T_NUMBER @@ -690,7 +735,7 @@ init_config(char *filename) /* create empty pool */ if (!STATE(ignore_pool)) { - STATE(ignore_pool) = ignore_pool_create(CONFIG(family)); + STATE(ignore_pool) = ignore_pool_create(); if (!STATE(ignore_pool)) { fprintf(stderr, "Can't create ignore pool!\n"); exit(EXIT_FAILURE); diff --git a/src/stats-mode.c b/src/stats-mode.c index 9e6089c..b6ae2bd 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -38,7 +38,6 @@ static int init_stats(void) STATE_STATS(cache) = cache_create("stats", LIFETIME, - CONFIG(family), NULL); if (!STATE_STATS(cache)) { dlog(LOG_ERR, "can't allocate memory for the " diff --git a/src/sync-mode.c b/src/sync-mode.c index b9fc25c..a81309f 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -151,7 +151,6 @@ static int init_sync(void) STATE_SYNC(internal) = cache_create("internal", STATE_SYNC(sync)->internal_cache_flags, - CONFIG(family), STATE_SYNC(sync)->internal_cache_extra); if (!STATE_SYNC(internal)) { @@ -167,7 +166,6 @@ static int init_sync(void) STATE_SYNC(external) = cache_create("external", STATE_SYNC(sync)->external_cache_flags, - CONFIG(family), NULL); if (!STATE_SYNC(external)) { -- cgit v1.2.3 From 13f4c15f214dd807899c10ebdff74ab5148d650f Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Tue, 19 Feb 2008 23:04:49 +0000 Subject: compose the file descriptor set at initialization stage to save some cycles --- ChangeLog | 1 + include/Makefile.am | 2 +- include/conntrackd.h | 4 ++- include/fds.h | 16 ++++++++++++ src/Makefile.am | 2 +- src/fds.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/run.c | 31 +++++++++++++--------- src/stats-mode.c | 2 +- src/sync-mode.c | 9 +++---- 9 files changed, 120 insertions(+), 21 deletions(-) create mode 100644 include/fds.h create mode 100644 src/fds.c (limited to 'src/stats-mode.c') diff --git a/ChangeLog b/ChangeLog index aa485a1..411118e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -47,6 +47,7 @@ o remove unix socket file on exit o use umask() to set up file permissions o add support for NAT sequence adjustment (requires Linux kernel >= 2.6.25) o remove TODO file from release tarballs +o compose the file descriptor set at initialization stage to save some cycles Max Kellermann : diff --git a/include/Makefile.am b/include/Makefile.am index d7f27a9..92ebbcc 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -3,5 +3,5 @@ noinst_HEADERS = alarm.h jhash.h slist.h cache.h linux_list.h linux_rbtree.h \ sync.h conntrackd.h local.h us-conntrack.h \ debug.h log.h hash.h mcast.h conntrack.h \ state_helper.h network.h ignore.h queue.h \ - traffic_stats.h netlink.h + traffic_stats.h netlink.h fds.h diff --git a/include/conntrackd.h b/include/conntrackd.h index 47898e2..69c1303 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -105,6 +105,8 @@ struct ct_general_state { struct nfct_handle *event; /* event handler */ struct nfct_handle *dump; /* dump handler */ + struct fds *fds; + /* statistics */ uint64_t malformed; uint64_t bytes[NFCT_DIR_MAX]; @@ -151,7 +153,7 @@ extern struct ct_general_state st; struct ct_mode { int (*init)(void); - int (*add_fds_to_set)(fd_set *readfds); + int (*register_fds)(struct fds *fds); void (*run)(fd_set *readfds); int (*local)(int fd, int type, void *data); void (*kill)(void); diff --git a/include/fds.h b/include/fds.h new file mode 100644 index 0000000..cc213fe --- /dev/null +++ b/include/fds.h @@ -0,0 +1,16 @@ +#ifndef _FDS_H_ +#define _FDS_H_ + +struct fds { + int maxfd; + int fd_array_len; + int fd_array_cur; + int *fd_array; + fd_set readfds; +}; + +struct fds *create_fds(void); +void destroy_fds(struct fds *); +int register_fd(int fd, struct fds *fds); + +#endif diff --git a/src/Makefile.am b/src/Makefile.am index 7274a14..494da4f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,7 +12,7 @@ conntrack_LDFLAGS = $(all_libraries) @LIBNETFILTER_CONNTRACK_LIBS@ conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c rbtree.c \ local.c log.c mcast.c netlink.c \ - ignore_pool.c \ + ignore_pool.c fds.c \ cache.c cache_iterators.c \ cache_lifetime.c cache_timer.c cache_wt.c \ sync-mode.c sync-alarm.c sync-ftfw.c \ diff --git a/src/fds.c b/src/fds.c new file mode 100644 index 0000000..908f048 --- /dev/null +++ b/src/fds.c @@ -0,0 +1,74 @@ +/* + * (C) 2006-2008 by Pablo Neira Ayuso + * + * 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 +#include +#include "fds.h" + +/* we don't handle that many descriptors so eight is just fine */ +#define FDS_ARRAY_LEN 8 +#define FDS_ARRAY_SIZE (sizeof(int) * FDS_ARRAY_LEN) + +struct fds *create_fds(void) +{ + struct fds *fds; + + fds = (struct fds *) malloc(sizeof(struct fds)); + if (fds == NULL) + return NULL; + + memset(fds, 0, sizeof(struct fds)); + + fds->fd_array = (int *) malloc(FDS_ARRAY_SIZE); + if (fds->fd_array == NULL) { + free(fds); + return NULL; + } + + memset(fds->fd_array, 0, FDS_ARRAY_SIZE); + fds->fd_array_len = FDS_ARRAY_LEN; + + return fds; +} + +void destroy_fds(struct fds *fds) +{ + free(fds->fd_array); + free(fds); +} + +int register_fd(int fd, struct fds *fds) +{ + FD_SET(fd, &fds->readfds); + + if (fd > fds->maxfd) + fds->maxfd = fd; + + if (fds->fd_array_cur >= fds->fd_array_len) { + fds->fd_array_len += FDS_ARRAY_LEN; + fds->fd_array = realloc(fds->fd_array, + fds->fd_array_len * sizeof(int)); + if (fds->fd_array == NULL) { + fds->fd_array_len -= FDS_ARRAY_LEN; + return -1; + } + } + + fds->fd_array[fds->fd_array_cur++] = fd; + + return 0; +} diff --git a/src/run.c b/src/run.c index 6cf259d..b259f2e 100644 --- a/src/run.c +++ b/src/run.c @@ -23,6 +23,7 @@ #include "ignore.h" #include "log.h" #include "alarm.h" +#include "fds.h" #include #include @@ -128,6 +129,21 @@ init(void) return -1; } + STATE(fds) = create_fds(); + if (STATE(fds) == NULL) { + dlog(LOG_ERR, "can't create file descriptor pool"); + return -1; + } + + register_fd(STATE(local).fd, STATE(fds)); + register_fd(nfct_fd(STATE(event)), STATE(fds)); + + if (STATE(mode)->register_fds && + STATE(mode)->register_fds(STATE(fds)) == -1) { + dlog(LOG_ERR, "fds registration failed"); + return -1; + } + /* Signals handling */ sigemptyset(&STATE(block)); sigaddset(&STATE(block), SIGTERM); @@ -154,19 +170,10 @@ init(void) static void __run(struct timeval *next_alarm) { - int max, ret; - fd_set readfds; - - FD_ZERO(&readfds); - FD_SET(STATE(local).fd, &readfds); - FD_SET(nfct_fd(STATE(event)), &readfds); - - max = MAX(STATE(local).fd, nfct_fd(STATE(event))); - - if (STATE(mode)->add_fds_to_set) - max = MAX(max, STATE(mode)->add_fds_to_set(&readfds)); + int ret; + fd_set readfds = STATE(fds)->readfds; - ret = select(max+1, &readfds, NULL, NULL, next_alarm); + ret = select(STATE(fds)->maxfd + 1, &readfds, NULL, NULL, next_alarm); if (ret == -1) { /* interrupted syscall, retry */ if (errno == EINTR) diff --git a/src/stats-mode.c b/src/stats-mode.c index b6ae2bd..42fa35a 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -181,7 +181,7 @@ static int event_destroy_stats(struct nf_conntrack *ct) struct ct_mode stats_mode = { .init = init_stats, - .add_fds_to_set = NULL, + .register_fds = NULL, .run = NULL, .local = local_handler_stats, .kill = kill_stats, diff --git a/src/sync-mode.c b/src/sync-mode.c index a81309f..79afcdf 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -25,6 +25,7 @@ #include "conntrackd.h" #include "us-conntrack.h" #include "network.h" +#include "fds.h" #include "debug.h" #include @@ -202,11 +203,9 @@ static int init_sync(void) return 0; } -static int add_fds_to_set_sync(fd_set *readfds) +static int register_fds_sync(struct fds *fds) { - FD_SET(STATE_SYNC(mcast_server->fd), readfds); - - return STATE_SYNC(mcast_server->fd); + return register_fd(STATE_SYNC(mcast_server->fd), fds); } static void run_sync(fd_set *readfds) @@ -500,7 +499,7 @@ static int event_destroy_sync(struct nf_conntrack *ct) struct ct_mode sync_mode = { .init = init_sync, - .add_fds_to_set = add_fds_to_set_sync, + .register_fds = register_fds_sync, .run = run_sync, .local = local_handler_sync, .kill = kill_sync, -- cgit v1.2.3 From 2d92fdb0912f3546492b114485951287fca4e5ab Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Sat, 8 Mar 2008 11:28:05 +0000 Subject: relicense conntrack-tools as GPLv3+, so far the most significant contributor has been Max Kellermann and has no issues with relicensing their contributions. --- COPYING | 913 +++++++++++++++++++++++++++++++++---------------- src/alarm.c | 2 +- src/build.c | 2 +- src/cache.c | 2 +- src/cache_iterators.c | 2 +- src/cache_lifetime.c | 2 +- src/cache_timer.c | 2 +- src/cache_wt.c | 2 +- src/conntrack.c | 2 +- src/fds.c | 2 +- src/hash.c | 2 +- src/ignore_pool.c | 2 +- src/local.c | 2 +- src/log.c | 2 +- src/main.c | 2 +- src/mcast.c | 2 +- src/netlink.c | 2 +- src/network.c | 2 +- src/parse.c | 2 +- src/queue.c | 2 +- src/rbtree.c | 2 +- src/read_config_lex.l | 2 +- src/read_config_yy.y | 2 +- src/run.c | 2 +- src/state_helper.c | 2 +- src/state_helper_tcp.c | 2 +- src/stats-mode.c | 2 +- src/sync-alarm.c | 2 +- src/sync-ftfw.c | 2 +- src/sync-mode.c | 2 +- src/traffic_stats.c | 2 +- 31 files changed, 654 insertions(+), 319 deletions(-) (limited to 'src/stats-mode.c') diff --git a/COPYING b/COPYING index a43ea21..94a9ed0 100644 --- a/COPYING +++ b/COPYING @@ -1,285 +1,626 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA + Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of this License. - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - Appendix: How to Apply These Terms to Your New Programs + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it @@ -287,15 +628,15 @@ free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least +state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. - Copyright (C) 19yy + Copyright (C) - This program is free software; you can redistribute it and/or modify + 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 + the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -304,36 +645,30 @@ the "copyright" line and a pointer to where the full notice is found. 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. + along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/src/alarm.c b/src/alarm.c index 91ee2ca..db3f105 100644 --- a/src/alarm.c +++ b/src/alarm.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/build.c b/src/build.c index 6363458..1ab0ed4 100644 --- a/src/build.c +++ b/src/build.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/cache.c b/src/cache.c index 73d539a..6f81725 100644 --- a/src/cache.c +++ b/src/cache.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/cache_iterators.c b/src/cache_iterators.c index 92b7b7f..662e4a9 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/cache_lifetime.c b/src/cache_lifetime.c index ad3416a..989e069 100644 --- a/src/cache_lifetime.c +++ b/src/cache_lifetime.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/cache_timer.c b/src/cache_timer.c index 6619c2c..aba342c 100644 --- a/src/cache_timer.c +++ b/src/cache_timer.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/cache_wt.c b/src/cache_wt.c index 8ff8fae..bf683b0 100644 --- a/src/cache_wt.c +++ b/src/cache_wt.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/conntrack.c b/src/conntrack.c index 82ff544..e0ff92d 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/fds.c b/src/fds.c index 908f048..ccb639b 100644 --- a/src/fds.c +++ b/src/fds.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/hash.c b/src/hash.c index cf64df4..5df33dd 100644 --- a/src/hash.c +++ b/src/hash.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/ignore_pool.c b/src/ignore_pool.c index 027d628..7540b3a 100644 --- a/src/ignore_pool.c +++ b/src/ignore_pool.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/local.c b/src/local.c index e2c3599..a67b2fb 100644 --- a/src/local.c +++ b/src/local.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/log.c b/src/log.c index 51e757f..1638dc2 100644 --- a/src/log.c +++ b/src/log.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/main.c b/src/main.c index 2e1ccd8..fa05da0 100644 --- a/src/main.c +++ b/src/main.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/mcast.c b/src/mcast.c index f945511..30313bc 100644 --- a/src/mcast.c +++ b/src/mcast.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/netlink.c b/src/netlink.c index f6a2378..8ac6f93 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/network.c b/src/network.c index 92999a1..f5b0909 100644 --- a/src/network.c +++ b/src/network.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/parse.c b/src/parse.c index 8ef2e8d..1e5fdf6 100644 --- a/src/parse.c +++ b/src/parse.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/queue.c b/src/queue.c index 7b20e83..22460e3 100644 --- a/src/queue.c +++ b/src/queue.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/rbtree.c b/src/rbtree.c index 199e2bb..2228f98 100644 --- a/src/rbtree.c +++ b/src/rbtree.c @@ -5,7 +5,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/src/read_config_lex.l b/src/read_config_lex.l index 65df1e7..4f0d864 100644 --- a/src/read_config_lex.l +++ b/src/read_config_lex.l @@ -4,7 +4,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/read_config_yy.y b/src/read_config_yy.y index 86fee9b..f89677a 100644 --- a/src/read_config_yy.y +++ b/src/read_config_yy.y @@ -4,7 +4,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/run.c b/src/run.c index b259f2e..0d91f4d 100644 --- a/src/run.c +++ b/src/run.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/state_helper.c b/src/state_helper.c index 9034864..2fa0e02 100644 --- a/src/state_helper.c +++ b/src/state_helper.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/state_helper_tcp.c b/src/state_helper_tcp.c index 88af35e..625928c 100644 --- a/src/state_helper_tcp.c +++ b/src/state_helper_tcp.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/stats-mode.c b/src/stats-mode.c index 42fa35a..06962d2 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/sync-alarm.c b/src/sync-alarm.c index 4473af2..709e27b 100644 --- a/src/sync-alarm.c +++ b/src/sync-alarm.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/sync-ftfw.c b/src/sync-ftfw.c index cac25d0..4ed8928 100644 --- a/src/sync-ftfw.c +++ b/src/sync-ftfw.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/sync-mode.c b/src/sync-mode.c index 79afcdf..86ac5e8 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/src/traffic_stats.c b/src/traffic_stats.c index 9e40d53..b5a97ec 100644 --- a/src/traffic_stats.c +++ b/src/traffic_stats.c @@ -3,7 +3,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, -- cgit v1.2.3 From 4f0edbba3cca03e4816c015cbf2c1a29fb62d073 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Sat, 8 Mar 2008 11:35:02 +0000 Subject: revert relicensing... still we use linux_list.h code which seems to be GPLv2 only which is incompatible AFAIK --- COPYING | 913 ++++++++++++++++--------------------------------- src/alarm.c | 2 +- src/build.c | 2 +- src/cache.c | 2 +- src/cache_iterators.c | 2 +- src/cache_lifetime.c | 2 +- src/cache_timer.c | 2 +- src/cache_wt.c | 2 +- src/conntrack.c | 2 +- src/fds.c | 2 +- src/hash.c | 2 +- src/ignore_pool.c | 2 +- src/local.c | 2 +- src/log.c | 2 +- src/main.c | 2 +- src/mcast.c | 2 +- src/netlink.c | 2 +- src/network.c | 2 +- src/parse.c | 2 +- src/queue.c | 2 +- src/rbtree.c | 2 +- src/read_config_lex.l | 2 +- src/read_config_yy.y | 2 +- src/run.c | 2 +- src/state_helper.c | 2 +- src/state_helper_tcp.c | 2 +- src/stats-mode.c | 2 +- src/sync-alarm.c | 2 +- src/sync-ftfw.c | 2 +- src/sync-mode.c | 2 +- src/traffic_stats.c | 2 +- 31 files changed, 319 insertions(+), 654 deletions(-) (limited to 'src/stats-mode.c') diff --git a/COPYING b/COPYING index 94a9ed0..a43ea21 100644 --- a/COPYING +++ b/COPYING @@ -1,626 +1,285 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to this License. - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it @@ -628,15 +287,15 @@ free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least +convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. - Copyright (C) + Copyright (C) 19yy - This program is free software: you can redistribute it and/or modify + 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 3 of the License, or + 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, @@ -645,30 +304,36 @@ the "copyright" line and a pointer to where the full notice is found. 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, see . + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/src/alarm.c b/src/alarm.c index db3f105..91ee2ca 100644 --- a/src/alarm.c +++ b/src/alarm.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/build.c b/src/build.c index 1ab0ed4..6363458 100644 --- a/src/build.c +++ b/src/build.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/cache.c b/src/cache.c index 6f81725..73d539a 100644 --- a/src/cache.c +++ b/src/cache.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/cache_iterators.c b/src/cache_iterators.c index 662e4a9..92b7b7f 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/cache_lifetime.c b/src/cache_lifetime.c index 989e069..ad3416a 100644 --- a/src/cache_lifetime.c +++ b/src/cache_lifetime.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/cache_timer.c b/src/cache_timer.c index aba342c..6619c2c 100644 --- a/src/cache_timer.c +++ b/src/cache_timer.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/cache_wt.c b/src/cache_wt.c index bf683b0..8ff8fae 100644 --- a/src/cache_wt.c +++ b/src/cache_wt.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/conntrack.c b/src/conntrack.c index e0ff92d..82ff544 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/fds.c b/src/fds.c index ccb639b..908f048 100644 --- a/src/fds.c +++ b/src/fds.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/hash.c b/src/hash.c index 5df33dd..cf64df4 100644 --- a/src/hash.c +++ b/src/hash.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/ignore_pool.c b/src/ignore_pool.c index 7540b3a..027d628 100644 --- a/src/ignore_pool.c +++ b/src/ignore_pool.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/local.c b/src/local.c index a67b2fb..e2c3599 100644 --- a/src/local.c +++ b/src/local.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/log.c b/src/log.c index 1638dc2..51e757f 100644 --- a/src/log.c +++ b/src/log.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/main.c b/src/main.c index fa05da0..2e1ccd8 100644 --- a/src/main.c +++ b/src/main.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/mcast.c b/src/mcast.c index 30313bc..f945511 100644 --- a/src/mcast.c +++ b/src/mcast.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/netlink.c b/src/netlink.c index 8ac6f93..f6a2378 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/network.c b/src/network.c index f5b0909..92999a1 100644 --- a/src/network.c +++ b/src/network.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/parse.c b/src/parse.c index 1e5fdf6..8ef2e8d 100644 --- a/src/parse.c +++ b/src/parse.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/queue.c b/src/queue.c index 22460e3..7b20e83 100644 --- a/src/queue.c +++ b/src/queue.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/rbtree.c b/src/rbtree.c index 2228f98..199e2bb 100644 --- a/src/rbtree.c +++ b/src/rbtree.c @@ -5,7 +5,7 @@ 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 3 of the License, or + 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, diff --git a/src/read_config_lex.l b/src/read_config_lex.l index 4f0d864..65df1e7 100644 --- a/src/read_config_lex.l +++ b/src/read_config_lex.l @@ -4,7 +4,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/read_config_yy.y b/src/read_config_yy.y index f89677a..86fee9b 100644 --- a/src/read_config_yy.y +++ b/src/read_config_yy.y @@ -4,7 +4,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/run.c b/src/run.c index 0d91f4d..b259f2e 100644 --- a/src/run.c +++ b/src/run.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/state_helper.c b/src/state_helper.c index 2fa0e02..9034864 100644 --- a/src/state_helper.c +++ b/src/state_helper.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/state_helper_tcp.c b/src/state_helper_tcp.c index 625928c..88af35e 100644 --- a/src/state_helper_tcp.c +++ b/src/state_helper_tcp.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/stats-mode.c b/src/stats-mode.c index 06962d2..42fa35a 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/sync-alarm.c b/src/sync-alarm.c index 709e27b..4473af2 100644 --- a/src/sync-alarm.c +++ b/src/sync-alarm.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/sync-ftfw.c b/src/sync-ftfw.c index 4ed8928..cac25d0 100644 --- a/src/sync-ftfw.c +++ b/src/sync-ftfw.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/sync-mode.c b/src/sync-mode.c index 86ac5e8..79afcdf 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, diff --git a/src/traffic_stats.c b/src/traffic_stats.c index b5a97ec..9e40d53 100644 --- a/src/traffic_stats.c +++ b/src/traffic_stats.c @@ -3,7 +3,7 @@ * * 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 3 of the License, or + * 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, -- cgit v1.2.3 From 5e5d8cdb3cfed98f1af3f3e265220c90df684674 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Wed, 9 Apr 2008 15:25:59 +0000 Subject: improve netlink overrun handling --- ChangeLog | 1 + include/conntrackd.h | 8 ++++- include/netlink.h | 4 +++ src/netlink.c | 21 +++++++++++++ src/run.c | 27 ++++++++++++++-- src/stats-mode.c | 36 ++++++++++----------- src/sync-mode.c | 89 +++++++++++++++++++++------------------------------- 7 files changed, 111 insertions(+), 75 deletions(-) (limited to 'src/stats-mode.c') diff --git a/ChangeLog b/ChangeLog index 4bd878b..4ca2af1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ Pablo Neira Ayuso : o remove .svn directory from make distcheck tarballs (reported by B.Benjamini) o fix minor compilation issue in amd64 with gcc4.3 (reported by Daniel Schepler) o fix asymmetric path support (reported by Gary Richards) +o improve netlink overrun handling Krzysztof Oledzki : o fix minor compilation warning diff --git a/include/conntrackd.h b/include/conntrackd.h index 69c1303..57ac7e4 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -3,6 +3,7 @@ #include "mcast.h" #include "local.h" +#include "alarm.h" #include #include @@ -104,6 +105,8 @@ struct ct_general_state { struct nfct_handle *event; /* event handler */ struct nfct_handle *dump; /* dump handler */ + struct nfct_handle *overrun; /* overrun handler */ + struct alarm_block overrun_alarm; struct fds *fds; @@ -158,7 +161,10 @@ struct ct_mode { int (*local)(int fd, int type, void *data); void (*kill)(void); void (*dump)(struct nf_conntrack *ct); - void (*overrun)(void); + int (*overrun)(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data); + int (*purge)(void); void (*event_new)(struct nf_conntrack *ct); void (*event_upd)(struct nf_conntrack *ct); int (*event_dst)(struct nf_conntrack *ct); diff --git a/include/netlink.h b/include/netlink.h index d345656..a46fe11 100644 --- a/include/netlink.h +++ b/include/netlink.h @@ -10,6 +10,10 @@ int nl_init_event_handler(void); int nl_init_dump_handler(void); +int nl_init_overrun_handler(void); + +int nl_overrun_request_resync(void); + void nl_resize_socket_buffer(struct nfct_handle *h); int nl_dump_conntrack_table(void); diff --git a/src/netlink.c b/src/netlink.c index 1ab75e4..10c4643 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -158,6 +158,21 @@ int nl_init_dump_handler(void) return 0; } +int nl_init_overrun_handler(void) +{ + STATE(overrun) = nfct_open(CONNTRACK, 0); + if (!STATE(overrun)) + return -1; + + fcntl(nfct_fd(STATE(overrun)), F_SETFL, O_NONBLOCK); + + nfct_callback_register(STATE(overrun), + NFCT_T_ALL, + STATE(mode)->overrun, + NULL); + return 0; +} + static int warned = 0; void nl_resize_socket_buffer(struct nfct_handle *h) @@ -195,6 +210,12 @@ int nl_dump_conntrack_table(void) return nfct_query(STATE(dump), NFCT_Q_DUMP, &CONFIG(family)); } +int nl_overrun_request_resync(void) +{ + int family = CONFIG(family); + return nfct_send(STATE(overrun), NFCT_Q_DUMP, &family); +} + int nl_exist_conntrack(struct nf_conntrack *ct) { int ret; diff --git a/src/run.c b/src/run.c index b259f2e..63761b4 100644 --- a/src/run.c +++ b/src/run.c @@ -89,6 +89,12 @@ void local_handler(int fd, void *data) dlog(LOG_WARNING, "unknown local request %d", type); } +static void do_overrun_alarm(struct alarm_block *a, void *data) +{ + nl_overrun_request_resync(); + add_alarm(&STATE(overrun_alarm), 2, 0); +} + int init(void) { @@ -129,6 +135,15 @@ init(void) return -1; } + if (nl_init_overrun_handler() == -1) { + dlog(LOG_ERR, "can't open netlink handler: %s", + strerror(errno)); + dlog(LOG_ERR, "no ctnetlink kernel support?"); + return -1; + } + + init_alarm(&STATE(overrun_alarm), NULL, do_overrun_alarm); + STATE(fds) = create_fds(); if (STATE(fds) == NULL) { dlog(LOG_ERR, "can't create file descriptor pool"); @@ -137,6 +152,7 @@ init(void) register_fd(STATE(local).fd, STATE(fds)); register_fd(nfct_fd(STATE(event)), STATE(fds)); + register_fd(nfct_fd(STATE(overrun)), STATE(fds)); if (STATE(mode)->register_fds && STATE(mode)->register_fds(STATE(fds)) == -1) { @@ -203,8 +219,8 @@ static void __run(struct timeval *next_alarm) * size and resync with master conntrack table. */ nl_resize_socket_buffer(STATE(event)); - /* XXX: schedule overrun call via alarm */ - STATE(mode)->overrun(); + nl_overrun_request_resync(); + add_alarm(&STATE(overrun_alarm), 2, 0); break; case ENOENT: /* @@ -223,6 +239,13 @@ static void __run(struct timeval *next_alarm) } } + if (FD_ISSET(nfct_fd(STATE(overrun)), &readfds)) { + del_alarm(&STATE(overrun_alarm)); + nfct_catch(STATE(overrun)); + if (STATE(mode)->purge) + STATE(mode)->purge(); + } + if (STATE(mode)->run) STATE(mode)->run(&readfds); diff --git a/src/stats-mode.c b/src/stats-mode.c index 42fa35a..3773feb 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -22,10 +22,12 @@ #include "cache.h" #include "log.h" #include "conntrackd.h" +#include "us-conntrack.h" #include #include #include +#include static int init_stats(void) { @@ -93,9 +95,9 @@ static void dump_stats(struct nf_conntrack *ct) debug_ct(ct, "resync entry"); } -static int overrun_cb(enum nf_conntrack_msg_type type, - struct nf_conntrack *ct, - void *data) +static int overrun_stats(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data) { if (ignore_conntrack(ct)) return NFCT_CB_CONTINUE; @@ -115,28 +117,25 @@ static int overrun_cb(enum nf_conntrack_msg_type type, return NFCT_CB_CONTINUE; } -static void overrun_stats(void) +static int purge_step(void *data1, void *data2) { int ret; - struct nfct_handle *h; - int family = CONFIG(family); + struct us_conntrack *u = data2; - h = nfct_open(CONNTRACK, 0); - if (!h) { - dlog(LOG_ERR, "can't open overrun handler"); - return; + ret = nfct_query(STATE(dump), NFCT_Q_GET, u->ct); + if (ret == -1 && errno == ENOENT) { + debug_ct(u->ct, "overrun purge stats"); + cache_del(STATE_STATS(cache), u->ct); } - nfct_callback_register(h, NFCT_T_ALL, overrun_cb, NULL); - - cache_flush(STATE_STATS(cache)); + return 0; +} - ret = nfct_query(h, NFCT_Q_DUMP, &family); - if (ret == -1) - dlog(LOG_ERR, - "overrun query error %s", strerror(errno)); +static int purge_stats(void) +{ + cache_iterate(STATE_STATS(cache), NULL, purge_step); - nfct_close(h); + return 0; } static void event_new_stats(struct nf_conntrack *ct) @@ -187,6 +186,7 @@ struct ct_mode stats_mode = { .kill = kill_stats, .dump = dump_stats, .overrun = overrun_stats, + .purge = purge_stats, .event_new = event_new_stats, .event_upd = event_update_stats, .event_dst = event_destroy_stats diff --git a/src/sync-mode.c b/src/sync-mode.c index 79afcdf..3851e4a 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -350,9 +350,40 @@ static void mcast_send_sync(struct us_conntrack *u, STATE_SYNC(sync)->send(net, u); } -static int overrun_cb(enum nf_conntrack_msg_type type, - struct nf_conntrack *ct, - void *data) +static int purge_step(void *data1, void *data2) +{ + int ret; + struct nfct_handle *h = STATE(dump); + struct us_conntrack *u = data2; + + ret = nfct_query(h, NFCT_Q_GET, u->ct); + if (ret == -1 && errno == ENOENT) { + size_t len; + struct nethdr *net = BUILD_NETMSG(u->ct, NFCT_Q_DESTROY); + + debug_ct(u->ct, "overrun purge resync"); + + len = prepare_send_netmsg(STATE_SYNC(mcast_client), net); + mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), net, len); + if (STATE_SYNC(sync)->send) + STATE_SYNC(sync)->send(net, u); + + cache_del(STATE_SYNC(internal), u->ct); + } + + return 0; +} + +static int purge_sync(void) +{ + cache_iterate(STATE_SYNC(internal), NULL, purge_step); + + return 0; +} + +static int overrun_sync(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data) { struct us_conntrack *u; @@ -387,57 +418,6 @@ static int overrun_cb(enum nf_conntrack_msg_type type, return NFCT_CB_CONTINUE; } -static int overrun_purge_step(void *data1, void *data2) -{ - int ret; - struct nfct_handle *h = data1; - struct us_conntrack *u = data2; - - ret = nfct_query(h, NFCT_Q_GET, u->ct); - if (ret == -1 && errno == ENOENT) { - size_t len; - struct nethdr *net = BUILD_NETMSG(u->ct, NFCT_Q_DESTROY); - - debug_ct(u->ct, "overrun purge resync"); - - len = prepare_send_netmsg(STATE_SYNC(mcast_client), net); - mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), net, len); - if (STATE_SYNC(sync)->send) - STATE_SYNC(sync)->send(net, u); - - cache_del(STATE_SYNC(internal), u->ct); - } - - return 0; -} - -/* it's likely that we're losing events, just try to do our best here */ -static void overrun_sync(void) -{ - int ret; - struct nfct_handle *h; - int family = CONFIG(family); - - h = nfct_open(CONNTRACK, 0); - if (!h) { - dlog(LOG_ERR, "can't open overrun handler"); - return; - } - - nfct_callback_register(h, NFCT_T_ALL, overrun_cb, NULL); - - ret = nfct_query(h, NFCT_Q_DUMP, &family); - if (ret == -1) - dlog(LOG_ERR, - "overrun query error %s", strerror(errno)); - - nfct_callback_unregister(h); - - cache_iterate(STATE_SYNC(internal), h, overrun_purge_step); - - nfct_close(h); -} - static void event_new_sync(struct nf_conntrack *ct) { struct us_conntrack *u; @@ -505,6 +485,7 @@ struct ct_mode sync_mode = { .kill = kill_sync, .dump = dump_sync, .overrun = overrun_sync, + .purge = purge_sync, .event_new = event_new_sync, .event_upd = event_update_sync, .event_dst = event_destroy_sync -- cgit v1.2.3 From 07a3a6fe92c98e251a464a5744421ce211030003 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Wed, 16 Apr 2008 15:37:39 +0000 Subject: add more verbose error notification when the injection of a conntrack fails --- ChangeLog | 1 + include/log.h | 2 +- src/cache_iterators.c | 2 ++ src/cache_wt.c | 13 ++++++++++--- src/log.c | 28 ++++++++++++++++++++-------- src/stats-mode.c | 2 +- 6 files changed, 35 insertions(+), 13 deletions(-) (limited to 'src/stats-mode.c') diff --git a/ChangeLog b/ChangeLog index d6fbe30..045988a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -23,6 +23,7 @@ o minor cleanups = conntrackd = o fix asymmetric path support (reported by Gary Richards) o improve netlink overrun handling +o add more verbose error notification when we fail to inject a conntrack version 0.9.6 (2008/03/08) ------------------------------ diff --git a/include/log.h b/include/log.h index b258633..f5c5b4f 100644 --- a/include/log.h +++ b/include/log.h @@ -7,7 +7,7 @@ struct nf_conntrack; int init_log(void); void dlog(int priority, const char *format, ...); -void dlog_ct(struct nf_conntrack *ct); +void dlog_ct(FILE *fd, struct nf_conntrack *ct, unsigned int type); void close_log(void); #endif diff --git a/src/cache_iterators.c b/src/cache_iterators.c index 92b7b7f..c26d349 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -98,6 +98,8 @@ static int do_commit(void *data1, void *data2) c->commit_exist++; break; default: + dlog(LOG_ERR, "commit: %s", strerror(errno)); + dlog_ct(STATE(log), u->ct, NFCT_O_PLAIN); c->commit_fail++; break; } diff --git a/src/cache_wt.c b/src/cache_wt.c index 65eb3fe..65a1fc4 100644 --- a/src/cache_wt.c +++ b/src/cache_wt.c @@ -35,16 +35,21 @@ static void add_wt(struct us_conntrack *u) switch (ret) { case -1: dlog(LOG_ERR, "cache_wt problem: %s", strerror(errno)); + dlog_ct(STATE(log), u->ct, NFCT_O_PLAIN); break; case 0: memcpy(ct, u->ct, nfct_maxsize()); - if (nl_create_conntrack(ct) == -1) + if (nl_create_conntrack(ct) == -1) { dlog(LOG_ERR, "cache_wt create: %s", strerror(errno)); + dlog_ct(STATE(log), u->ct, NFCT_O_PLAIN); + } break; case 1: memcpy(ct, u->ct, nfct_maxsize()); - if (nl_update_conntrack(ct) == -1) + if (nl_update_conntrack(ct) == -1) { dlog(LOG_ERR, "cache_wt crt-upd: %s", strerror(errno)); + dlog_ct(STATE(log), u->ct, NFCT_O_PLAIN); + } break; } } @@ -56,8 +61,10 @@ static void upd_wt(struct us_conntrack *u) memcpy(ct, u->ct, nfct_maxsize()); - if (nl_update_conntrack(ct) == -1) + if (nl_update_conntrack(ct) == -1) { dlog(LOG_ERR, "cache_wt update:%s", strerror(errno)); + dlog_ct(STATE(log), u->ct, NFCT_O_PLAIN); + } } static void writethrough_add(struct us_conntrack *u, void *data) diff --git a/src/log.c b/src/log.c index 51e757f..d97a69f 100644 --- a/src/log.c +++ b/src/log.c @@ -104,18 +104,30 @@ void dlog(int priority, const char *format, ...) } } -void dlog_ct(struct nf_conntrack *ct) +void dlog_ct(FILE *fd, struct nf_conntrack *ct, unsigned int type) { - FILE *fd = STATE(stats_log); time_t t; char buf[1024]; char *tmp; - - t = time(NULL); - ctime_r(&t, buf); - tmp = buf + strlen(buf); - buf[strlen(buf)-1]='\t'; - nfct_snprintf(buf+strlen(buf), 1024-strlen(buf), ct, 0, 0, 0); + unsigned int flags = 0; + + buf[0]='\0'; + + switch(type) { + case NFCT_O_PLAIN: + t = time(NULL); + ctime_r(&t, buf); + tmp = buf + strlen(buf); + buf[strlen(buf)-1]='\t'; + break; + case NFCT_O_XML: + tmp = buf; + flags |= NFCT_OF_TIME; + break; + default: + return; + } + nfct_snprintf(buf+strlen(buf), 1024-strlen(buf), ct, 0, type, flags); if (fd) { snprintf(buf+strlen(buf), 1024-strlen(buf), "\n"); diff --git a/src/stats-mode.c b/src/stats-mode.c index 3773feb..5808320 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -170,7 +170,7 @@ static int event_destroy_stats(struct nf_conntrack *ct) if (cache_del(STATE_STATS(cache), ct)) { debug_ct(ct, "cache destroy"); - dlog_ct(ct); + dlog_ct(STATE(stats_log), ct, NFCT_O_PLAIN); return 1; } else { debug_ct(ct, "can't destroy!"); -- cgit v1.2.3 From be2450f37f2ce56eadc78793efc4a54ced4315c6 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 16 May 2008 17:05:17 +0200 Subject: - remove (misleading) counters and use information from the statistics mode - use generic nfct_copy() from libnetfilter_conntrack to update objects - use generic nfct_cmp() to compare objects --- ChangeLog | 3 +++ configure.in | 4 +-- src/cache.c | 75 ++------------------------------------------------------ src/stats-mode.c | 5 ++++ 4 files changed, 12 insertions(+), 75 deletions(-) (limited to 'src/stats-mode.c') diff --git a/ChangeLog b/ChangeLog index 02ac75a..d67ad30 100644 --- a/ChangeLog +++ b/ChangeLog @@ -26,6 +26,9 @@ o improve netlink overrun handling o add more verbose error notification when we fail to inject a conntrack o rework of the FT-FW approach o minor fix of the manpage (Max Wilhelm) +o remove (misleading) counters and use information from the statistics mode +o use generic nfct_copy() from libnetfilter_conntrack to update objects +o use generic nfct_cmp() to compare objects version 0.9.6 (2008/03/08) ------------------------------ diff --git a/configure.in b/configure.in index 17101e9..f3b8785 100644 --- a/configure.in +++ b/configure.in @@ -17,8 +17,8 @@ case $target in esac dnl Dependencies -LIBNFNETLINK_REQUIRED=0.0.32 -LIBNETFILTER_CONNTRACK_REQUIRED=0.0.92 +LIBNFNETLINK_REQUIRED=0.0.33 +LIBNETFILTER_CONNTRACK_REQUIRED=0.0.94 AC_CHECK_PROG(HAVE_PKG_CONFIG, pkg-config, yes) if test "x$HAVE_PKG_CONFIG" = "x" diff --git a/src/cache.c b/src/cache.c index eac9a78..4162661 100644 --- a/src/cache.c +++ b/src/cache.c @@ -85,75 +85,12 @@ static uint32_t hash(const void *data, struct hashtable *table) return ret; } -static int __compare(const struct nf_conntrack *ct1, - const struct nf_conntrack *ct2) -{ - return ((nfct_get_attr_u8(ct1, ATTR_ORIG_L4PROTO) == - nfct_get_attr_u8(ct2, ATTR_ORIG_L4PROTO)) && - (nfct_get_attr_u16(ct1, ATTR_ORIG_PORT_SRC) == - nfct_get_attr_u16(ct2, ATTR_ORIG_PORT_SRC)) && - (nfct_get_attr_u16(ct1, ATTR_ORIG_PORT_DST) == - nfct_get_attr_u16(ct2, ATTR_ORIG_PORT_DST)) && - (nfct_get_attr_u16(ct1, ATTR_REPL_PORT_SRC) == - nfct_get_attr_u16(ct2, ATTR_REPL_PORT_SRC)) && - (nfct_get_attr_u16(ct1, ATTR_REPL_PORT_DST) == - nfct_get_attr_u16(ct2, ATTR_REPL_PORT_DST))); -} - -static int -__compare4(const struct us_conntrack *u1, const struct us_conntrack *u2) -{ - return ((nfct_get_attr_u32(u1->ct, ATTR_ORIG_IPV4_SRC) == - nfct_get_attr_u32(u2->ct, ATTR_ORIG_IPV4_SRC)) && - (nfct_get_attr_u32(u1->ct, ATTR_ORIG_IPV4_DST) == - nfct_get_attr_u32(u2->ct, ATTR_ORIG_IPV4_DST)) && - (nfct_get_attr_u32(u1->ct, ATTR_REPL_IPV4_SRC) == - nfct_get_attr_u32(u2->ct, ATTR_REPL_IPV4_SRC)) && - (nfct_get_attr_u32(u1->ct, ATTR_REPL_IPV4_DST) == - nfct_get_attr_u32(u2->ct, ATTR_REPL_IPV4_DST)) && - __compare(u1->ct, u2->ct)); -} - -static int -__compare6(const struct us_conntrack *u1, const struct us_conntrack *u2) -{ - return ((memcmp(nfct_get_attr(u1->ct, ATTR_ORIG_IPV6_SRC), - nfct_get_attr(u2->ct, ATTR_ORIG_IPV6_SRC), - sizeof(uint32_t)*4) == 0) && - (memcmp(nfct_get_attr(u1->ct, ATTR_ORIG_IPV6_DST), - nfct_get_attr(u2->ct, ATTR_ORIG_IPV6_DST), - sizeof(uint32_t)*4) == 0) && - (memcmp(nfct_get_attr(u1->ct, ATTR_REPL_IPV6_SRC), - nfct_get_attr(u2->ct, ATTR_REPL_IPV6_SRC), - sizeof(uint32_t)*4) == 0) && - (memcmp(nfct_get_attr(u1->ct, ATTR_REPL_IPV6_DST), - nfct_get_attr(u2->ct, ATTR_REPL_IPV6_DST), - sizeof(uint32_t)*4) == 0) && - __compare(u1->ct, u2->ct)); -} - static int compare(const void *data1, const void *data2) { - int ret = 0; const struct us_conntrack *u1 = data1; const struct us_conntrack *u2 = data2; - if (nfct_get_attr_u8(u1->ct, ATTR_L3PROTO) != - nfct_get_attr_u8(u2->ct, ATTR_L3PROTO)) - return ret; - - switch(nfct_get_attr_u8(u1->ct, ATTR_L3PROTO)) { - case AF_INET: - ret = __compare4(u1, u2); - break; - case AF_INET6: - ret = __compare6(u1, u2); - break; - default: - dlog(LOG_ERR, "unknown layer 3 in compare"); - break; - } - return ret; + return nfct_cmp(u1->ct, u2->ct, NFCT_CMP_ORIG | NFCT_CMP_REPL); } struct cache_feature *cache_feature[CACHE_MAX_FEATURE] = { @@ -305,15 +242,7 @@ static struct us_conntrack *__update(struct cache *c, struct nf_conntrack *ct) unsigned i; char *data = u->data; - if (nfct_attr_is_set(ct, ATTR_STATUS)) - nfct_set_attr_u32(u->ct, ATTR_STATUS, - nfct_get_attr_u32(ct, ATTR_STATUS)); - if (nfct_attr_is_set(ct, ATTR_TCP_STATE)) - nfct_set_attr_u8(u->ct, ATTR_TCP_STATE, - nfct_get_attr_u8(ct, ATTR_TCP_STATE)); - if (nfct_attr_is_set(ct, ATTR_TIMEOUT)) - nfct_set_attr_u32(u->ct, ATTR_TIMEOUT, - nfct_get_attr_u32(ct, ATTR_TIMEOUT)); + nfct_copy(u->ct, ct, NFCT_CP_META); for (i = 0; i < c->num_features; i++) { c->features[i]->update(u, data); diff --git a/src/stats-mode.c b/src/stats-mode.c index 5808320..1650d5d 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -89,7 +89,12 @@ static int local_handler_stats(int fd, int type, void *data) static void dump_stats(struct nf_conntrack *ct) { + nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES); + nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS); + nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES); + nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); nfct_attr_unset(ct, ATTR_TIMEOUT); + nfct_attr_unset(ct, ATTR_USE); if (cache_update_force(STATE_STATS(cache), ct)) debug_ct(ct, "resync entry"); -- cgit v1.2.3 From 50162d3c19e38a491d95ec26767438ec25bab0dc Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 21 Oct 2008 19:11:42 +0200 Subject: filter: do not filter in user-space if kernel supports BSF This patch avoids a double filtering in user-space and kernel-space if the kernel support BSF. Since we do not use BSF for dumps and resyncs, we add a new parameter to ignore_conntrack to indicate if we have to perform the filtering in user-space or not. Signed-off-by: Pablo Neira Ayuso --- include/netlink.h | 2 +- src/netlink.c | 11 ++++++----- src/stats-mode.c | 2 +- src/sync-mode.c | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) (limited to 'src/stats-mode.c') diff --git a/include/netlink.h b/include/netlink.h index 6d28ac6..d13d33d 100644 --- a/include/netlink.h +++ b/include/netlink.h @@ -6,7 +6,7 @@ struct nf_conntrack; struct nfct_handle; -int ignore_conntrack(struct nf_conntrack *ct); +int ignore_conntrack(struct nf_conntrack *ct, int userspace); int nl_init_event_handler(void); diff --git a/src/netlink.c b/src/netlink.c index c0a0805..89a4ebc 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -60,14 +60,14 @@ static int sanity_check(struct nf_conntrack *ct) return 1; } -int ignore_conntrack(struct nf_conntrack *ct) +/* we do user-space filtering for dump and resyncs */ +int ignore_conntrack(struct nf_conntrack *ct, int userspace) { /* missing mandatory attributes in object */ if (!sanity_check(ct)) return 1; - /* Ignore traffic */ - if (!ct_filter_check(STATE(us_filter), ct)) { + if (userspace && !ct_filter_check(STATE(us_filter), ct)) { debug_ct(ct, "ignore traffic"); return 1; } @@ -79,7 +79,8 @@ static int event_handler(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data) { - if (ignore_conntrack(ct)) + /* skip user-space filtering if already do it in the kernel */ + if (ignore_conntrack(ct, !CONFIG(kernel_support_netlink_bsf))) return NFCT_CB_STOP; switch(type) { @@ -155,7 +156,7 @@ static int dump_handler(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data) { - if (ignore_conntrack(ct)) + if (ignore_conntrack(ct, 1)) return NFCT_CB_CONTINUE; switch(type) { diff --git a/src/stats-mode.c b/src/stats-mode.c index 1650d5d..763afe0 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -104,7 +104,7 @@ static int overrun_stats(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data) { - if (ignore_conntrack(ct)) + if (ignore_conntrack(ct, 1)) return NFCT_CB_CONTINUE; /* This is required by kernels < 2.6.20 */ diff --git a/src/sync-mode.c b/src/sync-mode.c index db199bc..4c22745 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -432,7 +432,7 @@ static int overrun_sync(enum nf_conntrack_msg_type type, { struct us_conntrack *u; - if (ignore_conntrack(ct)) + if (ignore_conntrack(ct, 1)) return NFCT_CB_CONTINUE; /* This is required by kernels < 2.6.20 */ -- cgit v1.2.3 From 9aba3974d60bfbc773ac366ad6b8859a5c000377 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 27 Nov 2008 23:40:13 +0100 Subject: src: move callbacks to run.c for better readability This patch is a cleanup. It moves the callbacks from netlink.c to run.c where they are actually invoked. This is better for code readability as I usually have to switch from run.c to netlink.c to remember what the callbacks actually do. Signed-off-by: Pablo Neira Ayuso --- include/filter.h | 2 +- include/netlink.h | 10 ++-- src/filter.c | 49 +++++++++++++++- src/netlink.c | 166 +++++++++++------------------------------------------- src/run.c | 72 +++++++++++++++++++++-- src/stats-mode.c | 2 +- src/sync-mode.c | 2 +- 7 files changed, 154 insertions(+), 149 deletions(-) (limited to 'src/stats-mode.c') diff --git a/include/filter.h b/include/filter.h index 567be34..9c2cf66 100644 --- a/include/filter.h +++ b/include/filter.h @@ -39,6 +39,6 @@ void ct_filter_add_state(struct ct_filter *f, int protonum, int state); void ct_filter_set_logic(struct ct_filter *f, enum ct_filter_type type, enum ct_filter_logic logic); -int ct_filter_check(struct ct_filter *filter, struct nf_conntrack *ct); +int ct_filter_conntrack(struct nf_conntrack *ct, int userspace); #endif diff --git a/include/netlink.h b/include/netlink.h index d13d33d..52482c1 100644 --- a/include/netlink.h +++ b/include/netlink.h @@ -6,15 +6,13 @@ struct nf_conntrack; struct nfct_handle; -int ignore_conntrack(struct nf_conntrack *ct, int userspace); +struct nfct_handle *nl_init_event_handler(void); -int nl_init_event_handler(void); +struct nfct_handle *nl_init_dump_handler(void); -int nl_init_dump_handler(void); +struct nfct_handle *nl_init_request_handler(void); -int nl_init_request_handler(void); - -int nl_init_overrun_handler(void); +struct nfct_handle *nl_init_overrun_handler(void); int nl_overrun_request_resync(void); diff --git a/src/filter.c b/src/filter.c index 905d10f..5a8b5d8 100644 --- a/src/filter.c +++ b/src/filter.c @@ -279,7 +279,7 @@ static int __ct_filter_test_state(struct ct_filter *f, struct nf_conntrack *ct) return test_bit_u16(val, &f->statemap[protonum]); } -int ct_filter_check(struct ct_filter *f, struct nf_conntrack *ct) +static int ct_filter_check(struct ct_filter *f, struct nf_conntrack *ct) { int ret, protonum = nfct_get_attr_u8(ct, ATTR_L4PROTO); @@ -324,3 +324,50 @@ int ct_filter_check(struct ct_filter *f, struct nf_conntrack *ct) return 1; } + +static inline int ct_filter_sanity_check(struct nf_conntrack *ct) +{ + if (!nfct_attr_is_set(ct, ATTR_L3PROTO)) { + dlog(LOG_ERR, "missing layer 3 protocol"); + return 0; + } + + switch(nfct_get_attr_u8(ct, ATTR_L3PROTO)) { + case AF_INET: + if (!nfct_attr_is_set(ct, ATTR_IPV4_SRC) || + !nfct_attr_is_set(ct, ATTR_IPV4_DST) || + !nfct_attr_is_set(ct, ATTR_REPL_IPV4_SRC) || + !nfct_attr_is_set(ct, ATTR_REPL_IPV4_DST)) { + dlog(LOG_ERR, "missing IPv4 address. " + "You forgot to load " + "nf_conntrack_ipv4?"); + return 0; + } + break; + case AF_INET6: + if (!nfct_attr_is_set(ct, ATTR_IPV6_SRC) || + !nfct_attr_is_set(ct, ATTR_IPV6_DST) || + !nfct_attr_is_set(ct, ATTR_REPL_IPV6_SRC) || + !nfct_attr_is_set(ct, ATTR_REPL_IPV6_DST)) { + dlog(LOG_ERR, "missing IPv6 address. " + "You forgot to load " + "nf_conntrack_ipv6?"); + return 0; + } + break; + } + return 1; +} + +/* we do user-space filtering for dump and resyncs */ +int ct_filter_conntrack(struct nf_conntrack *ct, int userspace) +{ + /* missing mandatory attributes in object */ + if (!ct_filter_sanity_check(ct)) + return 1; + + if (userspace && !ct_filter_check(STATE(us_filter), ct)) + return 1; + + return 0; +} diff --git a/src/netlink.c b/src/netlink.c index b8a2a02..81ac7a1 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -18,103 +18,27 @@ #include "netlink.h" #include "conntrackd.h" -#include "traffic_stats.h" #include "filter.h" #include "log.h" #include "debug.h" #include #include - -static int sanity_check(struct nf_conntrack *ct) -{ - if (!nfct_attr_is_set(ct, ATTR_L3PROTO)) { - dlog(LOG_ERR, "missing layer 3 protocol"); - return 0; - } - - switch(nfct_get_attr_u8(ct, ATTR_L3PROTO)) { - case AF_INET: - if (!nfct_attr_is_set(ct, ATTR_IPV4_SRC) || - !nfct_attr_is_set(ct, ATTR_IPV4_DST) || - !nfct_attr_is_set(ct, ATTR_REPL_IPV4_SRC) || - !nfct_attr_is_set(ct, ATTR_REPL_IPV4_DST)) { - dlog(LOG_ERR, "missing IPv4 address. " - "You forgot to load " - "nf_conntrack_ipv4?"); - return 0; - } - break; - case AF_INET6: - if (!nfct_attr_is_set(ct, ATTR_IPV6_SRC) || - !nfct_attr_is_set(ct, ATTR_IPV6_DST) || - !nfct_attr_is_set(ct, ATTR_REPL_IPV6_SRC) || - !nfct_attr_is_set(ct, ATTR_REPL_IPV6_DST)) { - dlog(LOG_ERR, "missing IPv6 address. " - "You forgot to load " - "nf_conntrack_ipv6?"); - return 0; - } - break; - } - return 1; -} - -/* we do user-space filtering for dump and resyncs */ -int ignore_conntrack(struct nf_conntrack *ct, int userspace) -{ - /* missing mandatory attributes in object */ - if (!sanity_check(ct)) - return 1; - - if (userspace && !ct_filter_check(STATE(us_filter), ct)) { - debug_ct(ct, "ignore traffic"); - return 1; - } - - return 0; -} - -static int event_handler(enum nf_conntrack_msg_type type, - struct nf_conntrack *ct, - void *data) -{ - /* skip user-space filtering if already do it in the kernel */ - if (ignore_conntrack(ct, !CONFIG(filter_from_kernelspace))) - return NFCT_CB_STOP; - - switch(type) { - case NFCT_T_NEW: - STATE(mode)->event_new(ct); - break; - case NFCT_T_UPDATE: - STATE(mode)->event_upd(ct); - break; - case NFCT_T_DESTROY: - if (STATE(mode)->event_dst(ct)) - update_traffic_stats(ct); - break; - default: - dlog(LOG_WARNING, "unknown msg from ctnetlink\n"); - break; - } - - return NFCT_CB_CONTINUE; -} - #include #include #include -int nl_init_event_handler(void) +struct nfct_handle *nl_init_event_handler(void) { - STATE(event) = nfct_open(CONNTRACK, NFCT_ALL_CT_GROUPS); - if (!STATE(event)) - return -1; + struct nfct_handle *h; + + h = nfct_open(CONNTRACK, NFCT_ALL_CT_GROUPS); + if (h == NULL) + return NULL; if (STATE(filter)) { if (CONFIG(filter_from_kernelspace)) { - if (nfct_filter_attach(nfct_fd(STATE(event)), + if (nfct_filter_attach(nfct_fd(h), STATE(filter)) == -1) { dlog(LOG_ERR, "cannot set event filtering: %s", strerror(errno)); @@ -126,18 +50,18 @@ int nl_init_event_handler(void) nfct_filter_destroy(STATE(filter)); } - fcntl(nfct_fd(STATE(event)), F_SETFL, O_NONBLOCK); + fcntl(nfct_fd(h), F_SETFL, O_NONBLOCK); /* set up socket buffer size */ if (CONFIG(netlink_buffer_size)) - nfnl_rcvbufsiz(nfct_nfnlh(STATE(event)), + nfnl_rcvbufsiz(nfct_nfnlh(h), CONFIG(netlink_buffer_size)); else { socklen_t socklen = sizeof(unsigned int); unsigned int read_size; /* get current buffer size */ - getsockopt(nfct_fd(STATE(event)), SOL_SOCKET, + getsockopt(nfct_fd(h), SOL_SOCKET, SO_RCVBUF, &read_size, &socklen); CONFIG(netlink_buffer_size) = read_size; @@ -148,69 +72,43 @@ int nl_init_event_handler(void) CONFIG(netlink_buffer_size_max_grown) = CONFIG(netlink_buffer_size); - /* register callback for events */ - nfct_callback_register(STATE(event), NFCT_T_ALL, event_handler, NULL); - - return 0; + return h; } -static int dump_handler(enum nf_conntrack_msg_type type, - struct nf_conntrack *ct, - void *data) +struct nfct_handle *nl_init_dump_handler(void) { - if (ignore_conntrack(ct, 1)) - return NFCT_CB_CONTINUE; - - switch(type) { - case NFCT_T_UPDATE: - STATE(mode)->dump(ct); - break; - default: - dlog(LOG_WARNING, "unknown msg from ctnetlink"); - break; - } - return NFCT_CB_CONTINUE; -} + struct nfct_handle *h; -int nl_init_dump_handler(void) -{ /* open dump netlink socket */ - STATE(dump) = nfct_open(CONNTRACK, 0); - if (!STATE(dump)) - return -1; - - /* register callback for dumped entries */ - nfct_callback_register(STATE(dump), NFCT_T_ALL, dump_handler, NULL); + h = nfct_open(CONNTRACK, 0); + if (h == NULL) + return NULL; - if (nl_dump_conntrack_table() == -1) - return -1; - - return 0; + return h; } -int nl_init_overrun_handler(void) +struct nfct_handle *nl_init_overrun_handler(void) { - STATE(overrun) = nfct_open(CONNTRACK, 0); - if (!STATE(overrun)) - return -1; + struct nfct_handle *h; + + h = nfct_open(CONNTRACK, 0); + if (h == NULL) + return NULL; - fcntl(nfct_fd(STATE(overrun)), F_SETFL, O_NONBLOCK); + fcntl(nfct_fd(h), F_SETFL, O_NONBLOCK); - nfct_callback_register(STATE(overrun), - NFCT_T_ALL, - STATE(mode)->overrun, - NULL); - return 0; + return h; } -/* no callback, it does not do anything with the output */ -int nl_init_request_handler(void) +struct nfct_handle *nl_init_request_handler(void) { - STATE(request) = nfct_open(CONNTRACK, 0); - if (!STATE(request)) - return -1; + struct nfct_handle *h; + + h = nfct_open(CONNTRACK, 0); + if (h == NULL) + return NULL; - return 0; + return h; } static int warned = 0; diff --git a/src/run.c b/src/run.c index ec110d7..6515e62 100644 --- a/src/run.c +++ b/src/run.c @@ -24,6 +24,7 @@ #include "log.h" #include "alarm.h" #include "fds.h" +#include "traffic_stats.h" #include #include @@ -100,6 +101,51 @@ static void do_overrun_alarm(struct alarm_block *a, void *data) add_alarm(&STATE(overrun_alarm), 2, 0); } +static int event_handler(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data) +{ + /* skip user-space filtering if already do it in the kernel */ + if (ct_filter_conntrack(ct, !CONFIG(filter_from_kernelspace))) + return NFCT_CB_STOP; + + switch(type) { + case NFCT_T_NEW: + STATE(mode)->event_new(ct); + break; + case NFCT_T_UPDATE: + STATE(mode)->event_upd(ct); + break; + case NFCT_T_DESTROY: + if (STATE(mode)->event_dst(ct)) + update_traffic_stats(ct); + break; + default: + dlog(LOG_WARNING, "unknown msg from ctnetlink\n"); + break; + } + + return NFCT_CB_CONTINUE; +} + +static int dump_handler(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data) +{ + if (ct_filter_conntrack(ct, 1)) + return NFCT_CB_CONTINUE; + + switch(type) { + case NFCT_T_UPDATE: + STATE(mode)->dump(ct); + break; + default: + dlog(LOG_WARNING, "unknown msg from ctnetlink"); + break; + } + return NFCT_CB_CONTINUE; +} + int init(void) { @@ -126,28 +172,44 @@ init(void) return -1; } - if (nl_init_event_handler() == -1) { + STATE(event) = nl_init_event_handler(); + if (STATE(event) == NULL) { dlog(LOG_ERR, "can't open netlink handler: %s", strerror(errno)); dlog(LOG_ERR, "no ctnetlink kernel support?"); return -1; } + nfct_callback_register(STATE(event), NFCT_T_ALL, event_handler, NULL); - if (nl_init_dump_handler() == -1) { + STATE(dump) = nl_init_dump_handler(); + if (STATE(dump) == NULL) { dlog(LOG_ERR, "can't open netlink handler: %s", strerror(errno)); dlog(LOG_ERR, "no ctnetlink kernel support?"); return -1; } + nfct_callback_register(STATE(dump), NFCT_T_ALL, dump_handler, NULL); - if (nl_init_overrun_handler() == -1) { + if (nl_dump_conntrack_table() == -1) { + dlog(LOG_ERR, "can't get kernel conntrack table"); + return -1; + } + + STATE(overrun) = nl_init_overrun_handler(); + if (STATE(overrun)== NULL) { dlog(LOG_ERR, "can't open netlink handler: %s", strerror(errno)); dlog(LOG_ERR, "no ctnetlink kernel support?"); return -1; } - - if (nl_init_request_handler() == -1) { + nfct_callback_register(STATE(overrun), + NFCT_T_ALL, + STATE(mode)->overrun, + NULL); + + /* no callback, it does not do anything with the output */ + STATE(request) = nl_init_request_handler(); + if (STATE(request) == NULL) { dlog(LOG_ERR, "can't open netlink handler: %s", strerror(errno)); dlog(LOG_ERR, "no ctnetlink kernel support?"); diff --git a/src/stats-mode.c b/src/stats-mode.c index 763afe0..ad28008 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -104,7 +104,7 @@ static int overrun_stats(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data) { - if (ignore_conntrack(ct, 1)) + if (ct_filter_conntrack(ct, 1)) return NFCT_CB_CONTINUE; /* This is required by kernels < 2.6.20 */ diff --git a/src/sync-mode.c b/src/sync-mode.c index 152a8e2..e613111 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -438,7 +438,7 @@ static int overrun_sync(enum nf_conntrack_msg_type type, { struct us_conntrack *u; - if (ignore_conntrack(ct, 1)) + if (ct_filter_conntrack(ct, 1)) return NFCT_CB_CONTINUE; /* This is required by kernels < 2.6.20 */ -- cgit v1.2.3 From 036a0a65c6a3ba95cff48035a25e0bdba6aa0452 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 21 Dec 2008 19:47:02 +0100 Subject: src: add cache statistics via `-s cache' This patch adds cache statistics that you can check via `conntrackd -s cache'. This information is useful for trouble-shooting. This patch replaces several log messages that can be triggered in runtime. The idea behind this patch is to avoid log message flooding under errors. Signed-off-by: Pablo Neira Ayuso --- conntrackd.8 | 3 +- include/cache.h | 38 +++++++++++++--------- include/conntrackd.h | 1 + src/cache.c | 89 +++++++++++++++++++++++++++++++++++++++------------ src/cache_iterators.c | 26 +++++++-------- src/main.c | 6 +++- src/stats-mode.c | 3 ++ src/sync-mode.c | 7 ++-- 8 files changed, 119 insertions(+), 54 deletions(-) (limited to 'src/stats-mode.c') diff --git a/conntrackd.8 b/conntrackd.8 index ab834fb..7d38740 100644 --- a/conntrackd.8 +++ b/conntrackd.8 @@ -44,9 +44,10 @@ option will not flush your internal and external cache). .BI "-k " Kill the daemon .TP -.BI "-s " "[|network]" +.BI "-s " "[|network|cache]" Dump statistics. If no parameter is passed, it displays the general statistics. If "network" is passed as parameter it displays the networking statistics. +If "cache" is passed as parameter, it shows the extended cache statistics. .TP .BI "-R " Force a resync against the kernel connection tracking table diff --git a/include/cache.h b/include/cache.h index 45c3b7e..ebed70a 100644 --- a/include/cache.h +++ b/include/cache.h @@ -50,21 +50,28 @@ struct cache { unsigned int extra_offset; /* statistics */ - unsigned int active; - - unsigned int add_ok; - unsigned int del_ok; - unsigned int upd_ok; - - unsigned int add_fail; - unsigned int del_fail; - unsigned int upd_fail; - - unsigned int commit_ok; - unsigned int commit_exist; - unsigned int commit_fail; - - unsigned int flush; + struct { + uint32_t active; + + uint32_t add_ok; + uint32_t del_ok; + uint32_t upd_ok; + + uint32_t add_fail; + uint32_t del_fail; + uint32_t upd_fail; + + uint32_t add_fail_enomem; + uint32_t add_fail_enospc; + uint32_t del_fail_enoent; + uint32_t upd_fail_enoent; + + uint32_t commit_ok; + uint32_t commit_exist; + uint32_t commit_fail; + + uint32_t flush; + } stats; }; struct cache_extra { @@ -88,6 +95,7 @@ int __cache_del_timer(struct cache *c, struct us_conntrack *u, int timeout); struct us_conntrack *cache_find(struct cache *c, struct nf_conntrack *ct); int cache_test(struct cache *c, struct nf_conntrack *ct); void cache_stats(const struct cache *c, int fd); +void cache_stats_extended(const struct cache *c, int fd); struct us_conntrack *cache_get_conntrack(struct cache *, void *); void *cache_get_extra(struct cache *, void *); void cache_iterate(struct cache *c, void *data, int (*iterate)(void *data1, void *data2)); diff --git a/include/conntrackd.h b/include/conntrackd.h index 7199985..98934ce 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -27,6 +27,7 @@ #define RESET_TIMERS 26 /* reset kernel timers */ #define DEBUG_INFO 27 /* show debug info (if any) */ #define STATS_NETWORK 28 /* extended network stats */ +#define STATS_CACHE 29 /* extended cache stats */ #define DEFAULT_CONFIGFILE "/etc/conntrackd/conntrackd.conf" #define DEFAULT_LOCKFILE "/var/lock/conntrackd.lock" diff --git a/src/cache.c b/src/cache.c index 40c7b1d..5e7d738 100644 --- a/src/cache.c +++ b/src/cache.c @@ -206,7 +206,7 @@ static struct us_conntrack *__add(struct cache *c, struct nf_conntrack *ct) if (c->extra && c->extra->add) c->extra->add(u, ((char *) u) + c->extra_offset); - c->active++; + c->stats.active++; return u; } free(newct); @@ -220,11 +220,16 @@ struct us_conntrack *cache_add(struct cache *c, struct nf_conntrack *ct) u = __add(c, ct); if (u) { - c->add_ok++; + c->stats.add_ok++; return u; } - if (errno != EEXIST) - c->add_fail++; + if (errno != EEXIST) { + c->stats.add_fail++; + if (errno == ENOSPC) + c->stats.add_fail_enospc++; + if (errno == ENOMEM) + c->stats.add_fail_enomem++; + } return NULL; } @@ -268,10 +273,12 @@ struct us_conntrack *cache_update(struct cache *c, struct nf_conntrack *ct) u = __update(c, ct); if (u) { - c->upd_ok++; + c->stats.upd_ok++; return u; } - c->upd_fail++; + c->stats.upd_fail++; + if (errno == ENOENT) + c->stats.upd_fail_enoent++; return NULL; } @@ -302,8 +309,8 @@ static void __cache_del(struct cache *c, struct us_conntrack *u) * __cache_del_timer. */ if (!alarm_pending(&u->alarm)) { - c->del_ok++; - c->active--; + c->stats.del_ok++; + c->stats.active--; } del_alarm(&u->alarm); __del(c, u); @@ -317,7 +324,7 @@ struct us_conntrack *cache_update_force(struct cache *c, u = cache_find(c, ct); if (u) { if (!alarm_pending(&u->alarm)) { - c->upd_ok++; + c->stats.upd_ok++; __cache_update(c, u, ct); return u; } else { @@ -325,10 +332,15 @@ struct us_conntrack *cache_update_force(struct cache *c, } } if ((u = __add(c, ct)) != NULL) { - c->add_ok++; + c->stats.add_ok++; return u; } - c->add_fail++; + c->stats.add_fail++; + if (errno == ENOSPC) + c->stats.add_fail_enospc++; + if (errno == ENOMEM) + c->stats.add_fail_enomem++; + return NULL; } @@ -359,7 +371,9 @@ int cache_del(struct cache *c, struct nf_conntrack *ct) __cache_del(c, u); return 1; } - c->del_fail++; + c->stats.del_fail++; + if (errno == ENOENT) + c->stats.del_fail_enoent++; return 0; } @@ -386,8 +400,8 @@ __cache_del_timer(struct cache *c, struct us_conntrack *u, int timeout) * that the replication protocol does not work * properly. */ - c->del_ok++; - c->active--; + c->stats.del_ok++; + c->stats.active--; return 1; } return 0; @@ -425,13 +439,46 @@ void cache_stats(const struct cache *c, int fd) "connections updated:\t\t%12u\tfailed:\t%12u\n" "connections destroyed:\t\t%12u\tfailed:\t%12u\n\n", c->name, - c->active, - c->add_ok, - c->add_fail, - c->upd_ok, - c->upd_fail, - c->del_ok, - c->del_fail); + c->stats.active, + c->stats.add_ok, + c->stats.add_fail, + c->stats.upd_ok, + c->stats.upd_fail, + c->stats.del_ok, + c->stats.del_fail); + send(fd, buf, size, 0); +} + +void cache_stats_extended(const struct cache *c, int fd) +{ + char buf[512]; + int size; + + size = snprintf(buf, sizeof(buf), + "cache:%s\tactive connections:\t%12u\n" + "\tcreation OK:\t\t\t%12u\n" + "\tcreation failed:\t\t%12u\n" + "\t\tno memory available:\t%12u\n" + "\t\tno space left in cache:\t%12u\n" + "\tupdate OK:\t\t\t%12u\n" + "\tupdate failed:\t\t\t%12u\n" + "\t\tentry not found:\t%12u\n" + "\tdeletion created:\t\t%12u\n" + "\tdeletion failed:\t\t%12u\n" + "\t\tentry not found:\t%12u\n", + c->name, + c->stats.active, + c->stats.add_ok, + c->stats.add_fail, + c->stats.add_fail_enomem, + c->stats.add_fail_enospc, + c->stats.upd_ok, + c->stats.upd_fail, + c->stats.upd_fail_enoent, + c->stats.del_ok, + c->stats.del_fail, + c->stats.del_fail_enoent); + send(fd, buf, size, 0); } diff --git a/src/cache_iterators.c b/src/cache_iterators.c index 12ffcff..8ad9612 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -130,12 +130,12 @@ try_again: } dlog(LOG_ERR, "commit-create: %s", strerror(errno)); dlog_ct(STATE(log), ct, NFCT_O_PLAIN); - tmp->c->commit_fail++; + tmp->c->stats.commit_fail++; } else - tmp->c->commit_ok++; + tmp->c->stats.commit_ok++; break; case 1: - tmp->c->commit_exist++; + tmp->c->stats.commit_exist++; if (nl_update_conntrack(tmp->h, ct) == -1) { if (errno == ENOMEM || errno == ETIME) { if (retry) { @@ -154,14 +154,14 @@ try_again: } dlog(LOG_ERR, "commit-rm: %s", strerror(errno)); dlog_ct(STATE(log), ct, NFCT_O_PLAIN); - tmp->c->commit_fail++; + tmp->c->stats.commit_fail++; break; } dlog(LOG_ERR, "commit-update: %s", strerror(errno)); dlog_ct(STATE(log), ct, NFCT_O_PLAIN); - tmp->c->commit_fail++; + tmp->c->stats.commit_fail++; } else - tmp->c->commit_ok++; + tmp->c->stats.commit_ok++; break; } } @@ -191,9 +191,9 @@ static int do_commit_master(void *data1, void *data2) /* no need to clone, called from child process */ void cache_commit(struct cache *c) { - unsigned int commit_ok = c->commit_ok; - unsigned int commit_exist = c->commit_exist; - unsigned int commit_fail = c->commit_fail; + unsigned int commit_ok = c->stats.commit_ok; + unsigned int commit_exist = c->stats.commit_exist; + unsigned int commit_fail = c->stats.commit_fail; struct __commit_container tmp; tmp.h = nfct_open(CONNTRACK, 0); @@ -208,9 +208,9 @@ void cache_commit(struct cache *c) hashtable_iterate(c->h, &tmp, do_commit_related); /* calculate new entries committed */ - commit_ok = c->commit_ok - commit_ok; - commit_fail = c->commit_fail - commit_fail; - commit_exist = c->commit_exist - commit_exist; + commit_ok = c->stats.commit_ok - commit_ok; + commit_fail = c->stats.commit_fail - commit_fail; + commit_exist = c->stats.commit_exist - commit_exist; /* log results */ dlog(LOG_NOTICE, "Committed %u new entries", commit_ok); @@ -292,5 +292,5 @@ static int do_flush(void *data1, void *data2) void cache_flush(struct cache *c) { hashtable_iterate(c->h, c, do_flush); - c->flush++; + c->stats.flush++; } diff --git a/src/main.c b/src/main.c index 022915d..f621a2e 100644 --- a/src/main.c +++ b/src/main.c @@ -43,7 +43,7 @@ static const char usage_client_commands[] = " -i, display content of the internal cache\n" " -e, display the content of the external cache\n" " -k, kill conntrack daemon\n" - " -s [|network], dump statistics\n" + " -s [|network|cache], dump statistics\n" " -R, resync with kernel conntrack table\n" " -n, request resync with other node (only FT-FW and NOTRACK modes)\n" " -x, dump cache in XML format (requires -i or -e)" @@ -161,6 +161,10 @@ int main(int argc, char *argv[]) strlen(argv[i+1])) == 0) { action = STATS_NETWORK; i++; + } else if (strncmp(argv[i+1], "cache", + strlen(argv[i+1])) == 0) { + action = STATS_CACHE; + i++; } else { fprintf(stderr, "ERROR: unknown " "parameter `%s' for " diff --git a/src/stats-mode.c b/src/stats-mode.c index ad28008..d340b0d 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -79,6 +79,9 @@ static int local_handler_stats(int fd, int type, void *data) cache_stats(STATE_STATS(cache), fd); dump_traffic_stats(fd); break; + case STATS_CACHE: + cache_stats_extended(STATE_STATS(cache), fd); + break; default: ret = 0; break; diff --git a/src/sync-mode.c b/src/sync-mode.c index e7b9359..6779487 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -418,6 +418,10 @@ static int local_handler_sync(int fd, int type, void *data) mcast_dump_stats(fd, STATE_SYNC(mcast_client), STATE_SYNC(mcast_server)); break; + case STATS_CACHE: + cache_stats_extended(STATE_SYNC(internal), fd); + cache_stats_extended(STATE_SYNC(external), fd); + break; default: if (STATE_SYNC(sync)->local) ret = STATE_SYNC(sync)->local(fd, type, data); @@ -519,9 +523,6 @@ retry: cache_del(STATE_SYNC(internal), ct); goto retry; } - - dlog(LOG_ERR, "can't add to internal cache: " - "%s\n", strerror(errno)); debug_ct(ct, "can't add"); } } -- cgit v1.2.3 From 50339f96638eed35dac2b673b64cc6f1eb96406c Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 15 Jan 2009 23:19:57 +0100 Subject: src: rework of the hash-cache infrastructure Currently, the caching system is implemented in a two layer architecture: hashtable (inner layer) and cache (upper layer). This patch reworks the hash-cache infrastructure to solve some initial design problems to make it more flexible, the main strong points of this patch are: * Memory handling is done in the cache layer, not in the inner hashtable layer. This removes one of the main dependencies between the hashtable and the cache classes. * Remove excessive encapsulation: the former cache used to hide a lot of details of the inner hashtable implementation. * Fix over-hashing of some operations: lookup-delete-add required three hash calculations. Similarly, the update-or-add operation required two hash calculations. Now, we calculate the hash once and re-use the value how many times as we need. This patch simplifies the caching system. As a result, we save ~130 lines of code. Small code means and less complexity means less chance to have bugs. Signed-off-by: Pablo Neira Ayuso --- include/Makefile.am | 4 +- include/cache.h | 43 +++++--- include/filter.h | 11 ++ include/hash.h | 22 ++-- include/network.h | 1 - include/slist.h | 41 -------- include/sync.h | 4 +- include/us-conntrack.h | 14 --- src/cache.c | 273 +++++++++++++++++++------------------------------ src/cache_iterators.c | 65 ++++++------ src/cache_lifetime.c | 10 +- src/cache_timer.c | 36 +++---- src/cache_wt.c | 33 +++--- src/filter.c | 57 +++++++++-- src/hash.c | 136 +++++++----------------- src/stats-mode.c | 55 +++++----- src/sync-alarm.c | 27 +++-- src/sync-ftfw.c | 40 ++++---- src/sync-mode.c | 116 +++++++++++---------- src/sync-notrack.c | 19 ++-- 20 files changed, 440 insertions(+), 567 deletions(-) delete mode 100644 include/slist.h delete mode 100644 include/us-conntrack.h (limited to 'src/stats-mode.c') diff --git a/include/Makefile.am b/include/Makefile.am index 13f7e37..c3f8904 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,6 +1,6 @@ -noinst_HEADERS = alarm.h jhash.h slist.h cache.h linux_list.h linux_rbtree.h \ - sync.h conntrackd.h local.h us-conntrack.h \ +noinst_HEADERS = alarm.h jhash.h cache.h linux_list.h linux_rbtree.h \ + sync.h conntrackd.h local.h \ debug.h log.h hash.h mcast.h conntrack.h \ network.h filter.h queue.h vector.h cidr.h \ traffic_stats.h netlink.h fds.h event.h bitops.h diff --git a/include/cache.h b/include/cache.h index ebed70a..dcd6bcd 100644 --- a/include/cache.h +++ b/include/cache.h @@ -3,6 +3,8 @@ #include #include +#include "hash.h" +#include "alarm.h" /* cache features */ enum { @@ -22,14 +24,20 @@ enum { #define CACHE_MAX_FEATURE __CACHE_MAX_FEATURE struct cache; -struct us_conntrack; +struct cache_object { + struct hashtable_node hashnode; + struct nf_conntrack *ct; + struct cache *cache; + struct alarm_block alarm; + char data[0]; +}; struct cache_feature { size_t size; - void (*add)(struct us_conntrack *u, void *data); - void (*update)(struct us_conntrack *u, void *data); - void (*destroy)(struct us_conntrack *u, void *data); - int (*dump)(struct us_conntrack *u, void *data, char *buf, int type); + void (*add)(struct cache_object *obj, void *data); + void (*update)(struct cache_object *obj, void *data); + void (*destroy)(struct cache_object *obj, void *data); + int (*dump)(struct cache_object *obj, void *data, char *buf, int type); }; extern struct cache_feature lifetime_feature; @@ -48,6 +56,7 @@ struct cache { unsigned int *feature_offset; struct cache_extra *extra; unsigned int extra_offset; + size_t object_size; /* statistics */ struct { @@ -77,9 +86,9 @@ struct cache { struct cache_extra { unsigned int size; - void (*add)(struct us_conntrack *u, void *data); - void (*update)(struct us_conntrack *u, void *data); - void (*destroy)(struct us_conntrack *u, void *data); + void (*add)(struct cache_object *obj, void *data); + void (*update)(struct cache_object *obj, void *data); + void (*destroy)(struct cache_object *obj, void *data); }; struct nf_conntrack; @@ -87,16 +96,18 @@ struct nf_conntrack; struct cache *cache_create(const char *name, unsigned int features, struct cache_extra *extra); void cache_destroy(struct cache *e); -struct us_conntrack *cache_add(struct cache *c, struct nf_conntrack *ct); -struct us_conntrack *cache_update(struct cache *c, struct nf_conntrack *ct); -struct us_conntrack *cache_update_force(struct cache *c, struct nf_conntrack *ct); -int cache_del(struct cache *c, struct nf_conntrack *ct); -int __cache_del_timer(struct cache *c, struct us_conntrack *u, int timeout); -struct us_conntrack *cache_find(struct cache *c, struct nf_conntrack *ct); -int cache_test(struct cache *c, struct nf_conntrack *ct); +struct cache_object *cache_object_new(struct cache *c, struct nf_conntrack *ct); +void cache_object_free(struct cache_object *obj); + +int cache_add(struct cache *c, struct cache_object *obj, int id); +void cache_update(struct cache *c, struct cache_object *obj, int id, struct nf_conntrack *ct); +struct cache_object *cache_update_force(struct cache *c, struct nf_conntrack *ct); +void cache_del(struct cache *c, struct cache_object *obj); +int cache_del_timer(struct cache *c, struct cache_object *obj, int timeout); +struct cache_object *cache_find(struct cache *c, struct nf_conntrack *ct, int *pos); void cache_stats(const struct cache *c, int fd); void cache_stats_extended(const struct cache *c, int fd); -struct us_conntrack *cache_get_conntrack(struct cache *, void *); +struct cache_object *cache_data_get_object(struct cache *c, void *data); void *cache_get_extra(struct cache *, void *); void cache_iterate(struct cache *c, void *data, int (*iterate)(void *data1, void *data2)); diff --git a/include/filter.h b/include/filter.h index 9c2cf66..72c2aa4 100644 --- a/include/filter.h +++ b/include/filter.h @@ -4,6 +4,7 @@ #include #include #include +#include enum ct_filter_type { CT_FILTER_L4PROTO, @@ -17,6 +18,16 @@ enum ct_filter_logic { CT_FILTER_POSITIVE = 1, }; +struct ct_filter_ipv4_hnode { + struct hashtable_node node; + uint32_t ip; +}; + +struct ct_filter_ipv6_hnode { + struct hashtable_node node; + uint32_t ipv6[4]; +}; + struct ct_filter_netmask_ipv4 { uint32_t ip; uint32_t mask; diff --git a/include/hash.h b/include/hash.h index 2fb0a27..68d618b 100644 --- a/include/hash.h +++ b/include/hash.h @@ -2,7 +2,6 @@ #define _NF_SET_HASH_H_ #include -#include "slist.h" #include "linux_list.h" #include @@ -15,35 +14,30 @@ struct hashtable { uint32_t limit; uint32_t count; uint32_t initval; - uint32_t datasize; uint32_t (*hash)(const void *data, const struct hashtable *table); int (*compare)(const void *data1, const void *data2); - struct slist_head members[0]; + struct list_head members[0]; }; struct hashtable_node { - struct slist_head head; - char data[0]; + struct list_head head; }; -struct hashtable_node *hashtable_alloc_node(int datasize, void *data); -void hashtable_destroy_node(struct hashtable_node *h); - struct hashtable * -hashtable_create(int hashsize, int limit, int datasize, +hashtable_create(int hashsize, int limit, uint32_t (*hash)(const void *data, const struct hashtable *table), int (*compare)(const void *data1, const void *data2)); void hashtable_destroy(struct hashtable *h); - -void *hashtable_add(struct hashtable *table, void *data); -void *hashtable_find(struct hashtable *table, const void *data); -int hashtable_del(struct hashtable *table, void *data); +int hashtable_hash(const struct hashtable *table, const void *data); +struct hashtable_node *hashtable_find(const struct hashtable *table, const void *data, int id); +int hashtable_add(struct hashtable *table, struct hashtable_node *n, int id); +void hashtable_del(struct hashtable *table, struct hashtable_node *node); int hashtable_flush(struct hashtable *table); int hashtable_iterate(struct hashtable *table, void *data, - int (*iterate)(void *data1, void *data2)); + int (*iterate)(void *data, struct hashtable_node *n)); unsigned int hashtable_counter(const struct hashtable *table); #endif diff --git a/include/network.h b/include/network.h index 40bb2b2..619ce3e 100644 --- a/include/network.h +++ b/include/network.h @@ -75,7 +75,6 @@ enum { __hdr; \ }) -struct us_conntrack; struct mcast_sock; enum { diff --git a/include/slist.h b/include/slist.h deleted file mode 100644 index 257b627..0000000 --- a/include/slist.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _SLIST_H_ -#define _SLIST_H_ - -#include "linux_list.h" - -#define INIT_SLIST_HEAD(ptr) ((ptr).next = NULL) - -struct slist_head { - struct slist_head *next; -}; - -static inline int slist_empty(const struct slist_head *h) -{ - return !h->next; -} - -static inline void slist_del(struct slist_head *t, struct slist_head *prev) -{ - prev->next = t->next; - t->next = LIST_POISON1; -} - -static inline void slist_add(struct slist_head *head, struct slist_head *t) -{ - struct slist_head *tmp = head->next; - head->next = t; - t->next = tmp; -} - -#define slist_entry(ptr, type, member) container_of(ptr,type,member) - -#define slist_for_each(pos, head) \ - for (pos = (head)->next; pos; \ - pos = pos->next) - -#define slist_for_each_safe(pos, prev, next, head) \ - for (pos = (head)->next, prev = (head); \ - pos && ({ next = pos->next; 1; }); \ - ({ prev = (prev->next != next) ? prev->next : prev; }), pos = next) - -#endif diff --git a/include/sync.h b/include/sync.h index fc06c93..60c9fae 100644 --- a/include/sync.h +++ b/include/sync.h @@ -2,7 +2,7 @@ #define _SYNC_HOOKS_H_ struct nethdr; -struct us_conntrack; +struct cache_object; struct sync_mode { int internal_cache_flags; @@ -14,7 +14,7 @@ struct sync_mode { void (*kill)(void); int (*local)(int fd, int type, void *data); int (*recv)(const struct nethdr *net); - void (*send)(struct nethdr *net, struct us_conntrack *u); + void (*send)(struct nethdr *net, struct cache_object *obj); void (*run)(void); }; diff --git a/include/us-conntrack.h b/include/us-conntrack.h deleted file mode 100644 index 9eafa3b..0000000 --- a/include/us-conntrack.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _US_CONNTRACK_H_ -#define _US_CONNTRACK_H_ - -#include "alarm.h" -#include - -struct us_conntrack { - struct nf_conntrack *ct; - struct cache *cache; - struct alarm_block alarm; - char data[0]; -}; - -#endif diff --git a/src/cache.c b/src/cache.c index 553dddf..621a3f4 100644 --- a/src/cache.c +++ b/src/cache.c @@ -1,5 +1,5 @@ /* - * (C) 2006-2007 by Pablo Neira Ayuso + * (C) 2006-2009 by Pablo Neira Ayuso * * 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 @@ -20,7 +20,6 @@ #include "jhash.h" #include "hash.h" #include "log.h" -#include "us-conntrack.h" #include "conntrackd.h" #include @@ -68,14 +67,14 @@ __hash6(const struct nf_conntrack *ct, const struct hashtable *table) static uint32_t hash(const void *data, const struct hashtable *table) { int ret = 0; - const struct us_conntrack *u = data; + const struct nf_conntrack *ct = data; - switch(nfct_get_attr_u8(u->ct, ATTR_L3PROTO)) { + switch(nfct_get_attr_u8(ct, ATTR_L3PROTO)) { case AF_INET: - ret = __hash4(u->ct, table); + ret = __hash4(ct, table); break; case AF_INET6: - ret = __hash6(u->ct, table); + ret = __hash6(ct, table); break; default: dlog(LOG_ERR, "unknown layer 3 proto in hash"); @@ -87,10 +86,10 @@ static uint32_t hash(const void *data, const struct hashtable *table) static int compare(const void *data1, const void *data2) { - const struct us_conntrack *u1 = data1; - const struct us_conntrack *u2 = data2; + const struct cache_object *obj = data1; + const struct nf_conntrack *ct = data2; - return nfct_cmp(u1->ct, u2->ct, NFCT_CMP_ORIG); + return nfct_cmp(obj->ct, ct, NFCT_CMP_ORIG); } struct cache_feature *cache_feature[CACHE_MAX_FEATURE] = { @@ -103,7 +102,7 @@ struct cache *cache_create(const char *name, unsigned int features, struct cache_extra *extra) { - size_t size = sizeof(struct us_conntrack); + size_t size = sizeof(struct cache_object); int i, j = 0; struct cache *c; struct cache_feature *feature_array[CACHE_MAX_FEATURE] = {}; @@ -152,7 +151,6 @@ struct cache *cache_create(const char *name, c->h = hashtable_create(CONFIG(hashsize), CONFIG(limit), - size, hash, compare); @@ -162,6 +160,7 @@ struct cache *cache_create(const char *name, free(c); return NULL; } + c->object_size = size; return c; } @@ -177,225 +176,165 @@ void cache_destroy(struct cache *c) static void __del_timeout(struct alarm_block *a, void *data); -static struct us_conntrack *__add(struct cache *c, struct nf_conntrack *ct) +struct cache_object *cache_object_new(struct cache *c, struct nf_conntrack *ct) { - unsigned i; - size_t size = c->h->datasize; - char buf[size]; - struct us_conntrack *u = (struct us_conntrack *) buf; - struct nf_conntrack *newct; + struct cache_object *obj; - memset(u, 0, size); + obj = calloc(c->object_size, 1); + if (obj == NULL) { + errno = ENOMEM; + c->stats.add_fail_enomem++; + return NULL; + } + obj->cache = c; + init_alarm(&obj->alarm, obj, __del_timeout); - u->cache = c; - if ((u->ct = newct = nfct_new()) == NULL) { + if ((obj->ct = nfct_new()) == NULL) { + free(obj); errno = ENOMEM; - return 0; + c->stats.add_fail_enomem++; + return NULL; } - memcpy(u->ct, ct, nfct_sizeof(ct)); + memcpy(obj->ct, ct, nfct_sizeof(ct)); - u = hashtable_add(c->h, u); - if (u) { - char *data = u->data; + return obj; +} - init_alarm(&u->alarm, u, __del_timeout); +void cache_object_free(struct cache_object *obj) +{ + nfct_destroy(obj->ct); + free(obj); +} - for (i = 0; i < c->num_features; i++) { - c->features[i]->add(u, data); - data += c->features[i]->size; - } +static int __add(struct cache *c, struct cache_object *obj, int id) +{ + int ret; + unsigned int i; + char *data = obj->data; - if (c->extra && c->extra->add) - c->extra->add(u, ((char *) u) + c->extra_offset); + ret = hashtable_add(c->h, &obj->hashnode, id); + if (ret == -1) + return -1; - c->stats.active++; - return u; + for (i = 0; i < c->num_features; i++) { + c->features[i]->add(obj, data); + data += c->features[i]->size; } - free(newct); - return NULL; + if (c->extra && c->extra->add) + c->extra->add(obj, ((char *) obj) + c->extra_offset); + + c->stats.active++; + return 0; } -struct us_conntrack *cache_add(struct cache *c, struct nf_conntrack *ct) +int cache_add(struct cache *c, struct cache_object *obj, int id) { - struct us_conntrack *u; + int ret; - u = __add(c, ct); - if (u) { - c->stats.add_ok++; - return u; - } - if (errno != EEXIST) { + ret = __add(c, obj, id); + if (ret == -1) { c->stats.add_fail++; if (errno == ENOSPC) c->stats.add_fail_enospc++; - if (errno == ENOMEM) - c->stats.add_fail_enomem++; + return -1; } - - return NULL; + c->stats.add_ok++; + return 0; } -static void -__cache_update(struct cache *c, struct us_conntrack *u, struct nf_conntrack *ct) +void cache_update(struct cache *c, struct cache_object *obj, int id, + struct nf_conntrack *ct) { - unsigned i; - char *data = u->data; + char *data = obj->data; + unsigned int i; - nfct_copy(u->ct, ct, NFCT_CP_META); + nfct_copy(obj->ct, ct, NFCT_CP_META); for (i = 0; i < c->num_features; i++) { - c->features[i]->update(u, data); + c->features[i]->update(obj, data); data += c->features[i]->size; } if (c->extra && c->extra->update) - c->extra->update(u, ((char *) u) + c->extra_offset); -} - -static struct us_conntrack *__update(struct cache *c, struct nf_conntrack *ct) -{ - size_t size = c->h->datasize; - char buf[size]; - struct us_conntrack *u = (struct us_conntrack *) buf; - - u->ct = ct; - - u = (struct us_conntrack *) hashtable_find(c->h, u); - if (u) { - __cache_update(c, u, ct); - return u; - } - return NULL; -} + c->extra->update(obj, ((char *) obj) + c->extra_offset); -struct us_conntrack *cache_update(struct cache *c, struct nf_conntrack *ct) -{ - struct us_conntrack *u; - - u = __update(c, ct); - if (u) { - c->stats.upd_ok++; - return u; - } - c->stats.upd_fail++; - if (errno == ENOENT) - c->stats.upd_fail_enoent++; - - return NULL; + c->stats.upd_ok++; } -static void __del(struct cache *c, struct us_conntrack *u) +static void __del(struct cache *c, struct cache_object *obj) { unsigned i; - char *data = u->data; - struct nf_conntrack *p = u->ct; + char *data = obj->data; for (i = 0; i < c->num_features; i++) { - c->features[i]->destroy(u, data); + c->features[i]->destroy(obj, data); data += c->features[i]->size; } if (c->extra && c->extra->destroy) - c->extra->destroy(u, ((char *) u) + c->extra_offset); + c->extra->destroy(obj, ((char *) obj) + c->extra_offset); - hashtable_del(c->h, u); - free(p); + hashtable_del(c->h, &obj->hashnode); } -static void __cache_del(struct cache *c, struct us_conntrack *u) +void cache_del(struct cache *c, struct cache_object *obj) { /* * Do not increase stats if we are trying to * kill an entry was previously deleted via * __cache_del_timer. */ - if (!alarm_pending(&u->alarm)) { + if (!alarm_pending(&obj->alarm)) { c->stats.del_ok++; c->stats.active--; } - del_alarm(&u->alarm); - __del(c, u); + del_alarm(&obj->alarm); + __del(c, obj); } -struct us_conntrack *cache_update_force(struct cache *c, - struct nf_conntrack *ct) +struct cache_object * +cache_update_force(struct cache *c, struct nf_conntrack *ct) { - struct us_conntrack *u; - - u = cache_find(c, ct); - if (u) { - if (!alarm_pending(&u->alarm)) { - c->stats.upd_ok++; - __cache_update(c, u, ct); - return u; + struct cache_object *obj; + int id; + + obj = cache_find(c, ct, &id); + if (obj) { + if (!alarm_pending(&obj->alarm)) { + cache_update(c, obj, id, ct); + return obj; } else { - __cache_del(c, u); + cache_del(c, obj); + cache_object_free(obj); } } - if ((u = __add(c, ct)) != NULL) { - c->stats.add_ok++; - return u; - } - c->stats.add_fail++; - if (errno == ENOSPC) - c->stats.add_fail_enospc++; - if (errno == ENOMEM) - c->stats.add_fail_enomem++; - - return NULL; -} - -int cache_test(struct cache *c, struct nf_conntrack *ct) -{ - size_t size = c->h->datasize; - char buf[size]; - struct us_conntrack *u = (struct us_conntrack *) buf; - void *ret; - - u->ct = ct; - - ret = hashtable_find(c->h, u); - - return ret != NULL; -} - -int cache_del(struct cache *c, struct nf_conntrack *ct) -{ - size_t size = c->h->datasize; - char buf[size]; - struct us_conntrack *u = (struct us_conntrack *) buf; - - u->ct = ct; + obj = cache_object_new(c, ct); + if (obj == NULL) + return NULL; - u = (struct us_conntrack *) hashtable_find(c->h, u); - if (u) { - __cache_del(c, u); - return 1; - } - c->stats.del_fail++; - if (errno == ENOENT) - c->stats.del_fail_enoent++; + if (cache_add(c, obj, id) == -1) + return NULL; - return 0; + return obj; } static void __del_timeout(struct alarm_block *a, void *data) { - struct us_conntrack *u = (struct us_conntrack *) data; - - __del(u->cache, u); + struct cache_object *obj = (struct cache_object *) data; + __del(obj->cache, obj); + cache_object_free(obj); } -int -__cache_del_timer(struct cache *c, struct us_conntrack *u, int timeout) +int cache_del_timer(struct cache *c, struct cache_object *obj, int timeout) { if (timeout <= 0) { - __cache_del(c, u); + cache_del(c, obj); + cache_object_free(obj); return 1; } - if (!alarm_pending(&u->alarm)) { - add_alarm(&u->alarm, timeout, 0); + if (!alarm_pending(&obj->alarm)) { + add_alarm(&obj->alarm, timeout, 0); /* * increase stats even if this entry was not really * removed yet. We do not want to make people think @@ -409,20 +348,16 @@ __cache_del_timer(struct cache *c, struct us_conntrack *u, int timeout) return 0; } -struct us_conntrack *cache_find(struct cache *c, struct nf_conntrack *ct) +struct cache_object * +cache_find(struct cache *c, struct nf_conntrack *ct, int *id) { - size_t size = c->h->datasize; - char buf[size]; - struct us_conntrack *u = (struct us_conntrack *) buf; - - u->ct = ct; - - return ((struct us_conntrack *) hashtable_find(c->h, u)); + *id = hashtable_hash(c->h, ct); + return ((struct cache_object *) hashtable_find(c->h, ct, *id)); } -struct us_conntrack *cache_get_conntrack(struct cache *c, void *data) +struct cache_object *cache_data_get_object(struct cache *c, void *data) { - return (struct us_conntrack *)((char*)data - c->extra_offset); + return (struct cache_object *)((char*)data - c->extra_offset); } void *cache_get_extra(struct cache *c, void *data) diff --git a/src/cache_iterators.c b/src/cache_iterators.c index a14f428..4773889 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -21,7 +21,6 @@ #include "log.h" #include "conntrackd.h" #include "netlink.h" -#include "us-conntrack.h" #include #include @@ -33,13 +32,13 @@ struct __dump_container { int type; }; -static int do_dump(void *data1, void *data2) +static int do_dump(void *data1, struct hashtable_node *n) { char buf[1024]; int size; struct __dump_container *container = data1; - struct us_conntrack *u = data2; - char *data = u->data; + struct cache_object *obj = (struct cache_object *)n; + char *data = obj->data; unsigned i; /* @@ -52,28 +51,28 @@ static int do_dump(void *data1, void *data2) * specific and it breaks conntrackd modularity. Probably * there's a nicer way to do this but until I come up with it... */ - if (CONFIG(flags) & CTD_SYNC_FTFW && alarm_pending(&u->alarm)) + if (CONFIG(flags) & CTD_SYNC_FTFW && alarm_pending(&obj->alarm)) return 0; /* do not show cached timeout, this may confuse users */ - if (nfct_attr_is_set(u->ct, ATTR_TIMEOUT)) - nfct_attr_unset(u->ct, ATTR_TIMEOUT); + if (nfct_attr_is_set(obj->ct, ATTR_TIMEOUT)) + nfct_attr_unset(obj->ct, ATTR_TIMEOUT); memset(buf, 0, sizeof(buf)); size = nfct_snprintf(buf, sizeof(buf), - u->ct, + obj->ct, NFCT_T_UNKNOWN, container->type, 0); - for (i = 0; i < u->cache->num_features; i++) { - if (u->cache->features[i]->dump) { - size += u->cache->features[i]->dump(u, - data, - buf+size, - container->type); - data += u->cache->features[i]->size; + for (i = 0; i < obj->cache->num_features; i++) { + if (obj->cache->features[i]->dump) { + size += obj->cache->features[i]->dump(obj, + data, + buf+size, + container->type); + data += obj->cache->features[i]->size; } } size += sprintf(buf+size, "\n"); @@ -101,10 +100,10 @@ struct __commit_container { }; static void -__do_commit_step(struct __commit_container *tmp, struct us_conntrack *u) +__do_commit_step(struct __commit_container *tmp, struct cache_object *obj) { int ret, retry = 1; - struct nf_conntrack *ct = u->ct; + struct nf_conntrack *ct = obj->ct; /* * Set a reduced timeout for candidate-to-be-committed @@ -166,25 +165,25 @@ try_again: } } -static int do_commit_related(void *data1, void *data2) +static int do_commit_related(void *data, struct hashtable_node *n) { - struct us_conntrack *u = data2; + struct cache_object *obj = (struct cache_object *)n; - if (ct_is_related(u->ct)) - __do_commit_step(data1, u); + if (ct_is_related(obj->ct)) + __do_commit_step(data, obj); /* keep iterating even if we have found errors */ return 0; } -static int do_commit_master(void *data1, void *data2) +static int do_commit_master(void *data, struct hashtable_node *n) { - struct us_conntrack *u = data2; + struct cache_object *obj = (struct cache_object *)n; - if (ct_is_related(u->ct)) + if (ct_is_related(obj->ct)) return 0; - __do_commit_step(data1, u); + __do_commit_step(data, obj); return 0; } @@ -231,13 +230,13 @@ void cache_commit(struct cache *c) res.tv_sec, res.tv_usec); } -static int do_reset_timers(void *data1, void *data2) +static int do_reset_timers(void *data1, struct hashtable_node *n) { int ret; u_int32_t current_timeout; struct nfct_handle *h = data1; - struct us_conntrack *u = data2; - struct nf_conntrack *ct = u->ct; + struct cache_object *obj = (struct cache_object *)n; + struct nf_conntrack *ct = obj->ct; char __tmp[nfct_maxsize()]; struct nf_conntrack *tmp = (struct nf_conntrack *) (void *)__tmp; @@ -286,13 +285,13 @@ void cache_reset_timers(struct cache *c) nfct_close(h); } -static int do_flush(void *data1, void *data2) +static int do_flush(void *data, struct hashtable_node *n) { - struct cache *c = data1; - struct us_conntrack *u = data2; - - cache_del(c, u->ct); + struct cache *c = data; + struct cache_object *obj = (struct cache_object *)n; + cache_del(c, obj); + cache_object_free(obj); return 0; } diff --git a/src/cache_lifetime.c b/src/cache_lifetime.c index ad3416a..639d8c1 100644 --- a/src/cache_lifetime.c +++ b/src/cache_lifetime.c @@ -17,12 +17,12 @@ */ #include -#include "us-conntrack.h" #include "cache.h" #include #include +#include -static void lifetime_add(struct us_conntrack *u, void *data) +static void lifetime_add(struct cache_object *obj, void *data) { long *lifetime = data; struct timeval tv; @@ -32,15 +32,15 @@ static void lifetime_add(struct us_conntrack *u, void *data) *lifetime = tv.tv_sec; } -static void lifetime_update(struct us_conntrack *u, void *data) +static void lifetime_update(struct cache_object *obj, void *data) { } -static void lifetime_destroy(struct us_conntrack *u, void *data) +static void lifetime_destroy(struct cache_object *obj, void *data) { } -static int lifetime_dump(struct us_conntrack *u, +static int lifetime_dump(struct cache_object *obj, void *data, char *buf, int type) diff --git a/src/cache_timer.c b/src/cache_timer.c index 44482b7..a9e3e3d 100644 --- a/src/cache_timer.c +++ b/src/cache_timer.c @@ -18,7 +18,6 @@ #include "cache.h" #include "conntrackd.h" -#include "us-conntrack.h" #include "alarm.h" #include "debug.h" @@ -26,45 +25,46 @@ static void timeout(struct alarm_block *a, void *data) { - struct us_conntrack *u = data; + struct cache_object *obj = data; - debug_ct(u->ct, "expired timeout"); - cache_del(u->cache, u->ct); + debug_ct(obj->ct, "expired timeout"); + cache_del(obj->cache, obj); + cache_object_free(obj); } -static void timer_add(struct us_conntrack *u, void *data) +static void timer_add(struct cache_object *obj, void *data) { - struct alarm_block *alarm = data; + struct alarm_block *a = data; - init_alarm(alarm, u, timeout); - add_alarm(alarm, CONFIG(cache_timeout), 0); + init_alarm(a, obj, timeout); + add_alarm(a, CONFIG(cache_timeout), 0); } -static void timer_update(struct us_conntrack *u, void *data) +static void timer_update(struct cache_object *obj, void *data) { - struct alarm_block *alarm = data; - add_alarm(alarm, CONFIG(cache_timeout), 0); + struct alarm_block *a = data; + add_alarm(a, CONFIG(cache_timeout), 0); } -static void timer_destroy(struct us_conntrack *u, void *data) +static void timer_destroy(struct cache_object *obj, void *data) { - struct alarm_block *alarm = data; - del_alarm(alarm); + struct alarm_block *a = data; + del_alarm(a); } -static int timer_dump(struct us_conntrack *u, void *data, char *buf, int type) +static int timer_dump(struct cache_object *obj, void *data, char *buf, int type) { struct timeval tv, tmp; - struct alarm_block *alarm = data; + struct alarm_block *a = data; if (type == NFCT_O_XML) return 0; - if (!alarm_pending(alarm)) + if (!alarm_pending(a)) return 0; gettimeofday(&tv, NULL); - timersub(&alarm->tv, &tv, &tmp); + timersub(&a->tv, &tv, &tmp); return sprintf(buf, " [expires in %lds]", tmp.tv_sec); } diff --git a/src/cache_wt.c b/src/cache_wt.c index d0ae8bb..84a816f 100644 --- a/src/cache_wt.c +++ b/src/cache_wt.c @@ -19,67 +19,66 @@ #include "conntrackd.h" #include "cache.h" #include "netlink.h" -#include "us-conntrack.h" #include "log.h" #include #include -static void add_wt(struct us_conntrack *u) +static void add_wt(struct cache_object *obj) { int ret; char __ct[nfct_maxsize()]; struct nf_conntrack *ct = (struct nf_conntrack *)(void*) __ct; - ret = nl_exist_conntrack(STATE(request), u->ct); + ret = nl_exist_conntrack(STATE(request), obj->ct); switch (ret) { case -1: dlog(LOG_ERR, "cache_wt problem: %s", strerror(errno)); - dlog_ct(STATE(log), u->ct, NFCT_O_PLAIN); + dlog_ct(STATE(log), obj->ct, NFCT_O_PLAIN); break; case 0: - memcpy(ct, u->ct, nfct_maxsize()); + memcpy(ct, obj->ct, nfct_maxsize()); if (nl_create_conntrack(STATE(dump), ct) == -1) { dlog(LOG_ERR, "cache_wt create: %s", strerror(errno)); - dlog_ct(STATE(log), u->ct, NFCT_O_PLAIN); + dlog_ct(STATE(log), obj->ct, NFCT_O_PLAIN); } break; case 1: - memcpy(ct, u->ct, nfct_maxsize()); + memcpy(ct, obj->ct, nfct_maxsize()); if (nl_update_conntrack(STATE(dump), ct) == -1) { dlog(LOG_ERR, "cache_wt crt-upd: %s", strerror(errno)); - dlog_ct(STATE(log), u->ct, NFCT_O_PLAIN); + dlog_ct(STATE(log), obj->ct, NFCT_O_PLAIN); } break; } } -static void upd_wt(struct us_conntrack *u) +static void upd_wt(struct cache_object *obj) { char __ct[nfct_maxsize()]; struct nf_conntrack *ct = (struct nf_conntrack *)(void*) __ct; - memcpy(ct, u->ct, nfct_maxsize()); + memcpy(ct, obj->ct, nfct_maxsize()); if (nl_update_conntrack(STATE(dump), ct) == -1) { dlog(LOG_ERR, "cache_wt update:%s", strerror(errno)); - dlog_ct(STATE(log), u->ct, NFCT_O_PLAIN); + dlog_ct(STATE(log), obj->ct, NFCT_O_PLAIN); } } -static void writethrough_add(struct us_conntrack *u, void *data) +static void writethrough_add(struct cache_object *obj, void *data) { - add_wt(u); + add_wt(obj); } -static void writethrough_update(struct us_conntrack *u, void *data) +static void writethrough_update(struct cache_object *obj, void *data) { - upd_wt(u); + upd_wt(obj); } -static void writethrough_destroy(struct us_conntrack *u, void *data) +static void writethrough_destroy(struct cache_object *obj, void *data) { - nl_destroy_conntrack(STATE(dump), u->ct); + nl_destroy_conntrack(STATE(dump), obj->ct); } struct cache_feature writethrough_feature = { diff --git a/src/filter.c b/src/filter.c index c6e24a9..6a09c77 100644 --- a/src/filter.c +++ b/src/filter.c @@ -58,15 +58,17 @@ static uint32_t ct_filter_hash6(const void *data, const struct hashtable *table) static int ct_filter_compare(const void *data1, const void *data2) { - const uint32_t *f1 = data1; + const struct ct_filter_ipv4_hnode *f1 = data1; const uint32_t *f2 = data2; - return *f1 == *f2; + return f1->ip == *f2; } static int ct_filter_compare6(const void *data1, const void *data2) { - return memcmp(data1, data2, sizeof(uint32_t)*4) == 0; + const struct ct_filter_ipv6_hnode *f = data1; + + return memcmp(f->ipv6, data2, sizeof(uint32_t)*4) == 0; } struct ct_filter *ct_filter_create(void) @@ -80,7 +82,6 @@ struct ct_filter *ct_filter_create(void) filter->h = hashtable_create(FILTER_POOL_SIZE, FILTER_POOL_LIMIT, - sizeof(uint32_t), ct_filter_hash, ct_filter_compare); if (!filter->h) { @@ -90,7 +91,6 @@ struct ct_filter *ct_filter_create(void) filter->h6 = hashtable_create(FILTER_POOL_SIZE, FILTER_POOL_LIMIT, - sizeof(uint32_t)*4, ct_filter_hash6, ct_filter_compare6); if (!filter->h6) { @@ -155,16 +155,33 @@ void ct_filter_set_logic(struct ct_filter *filter, int ct_filter_add_ip(struct ct_filter *filter, void *data, uint8_t family) { + int id; filter = __filter_alloc(filter); switch(family) { case AF_INET: - if (!hashtable_add(filter->h, data)) + id = hashtable_hash(filter->h, data); + if (!hashtable_find(filter->h, data, id)) { + struct ct_filter_ipv4_hnode *n; + n = malloc(sizeof(struct ct_filter_ipv4_hnode)); + if (n == NULL) + return 0; + memcpy(&n->ip, data, sizeof(uint32_t)); + hashtable_add(filter->h, &n->node, id); return 0; + } break; case AF_INET6: - if (!hashtable_add(filter->h6, data)) + id = hashtable_hash(filter->h6, data); + if (!hashtable_find(filter->h6, data, id)) { + struct ct_filter_ipv6_hnode *n; + n = malloc(sizeof(struct ct_filter_ipv6_hnode)); + if (n == NULL) + return 0; + memcpy(n->ipv6, data, sizeof(uint32_t)*4); + hashtable_add(filter->h6, &n->node, id); return 0; + } break; } return 1; @@ -220,16 +237,34 @@ void ct_filter_add_state(struct ct_filter *f, int protonum, int val) static inline int __ct_filter_test_ipv4(struct ct_filter *f, struct nf_conntrack *ct) { + int id_src, id_dst; + uint32_t src, dst; + /* we only use the real source and destination address */ - return (hashtable_find(f->h, nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC)) || - hashtable_find(f->h, nfct_get_attr(ct, ATTR_REPL_IPV4_SRC))); + src = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC); + dst = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC); + + id_src = hashtable_hash(f->h, &src); + id_dst = hashtable_hash(f->h, &dst); + + return hashtable_find(f->h, &src, id_src) || + hashtable_find(f->h, &dst, id_dst); } static inline int __ct_filter_test_ipv6(struct ct_filter *f, struct nf_conntrack *ct) { - return (hashtable_find(f->h6, nfct_get_attr(ct, ATTR_ORIG_IPV6_SRC)) || - hashtable_find(f->h6, nfct_get_attr(ct, ATTR_REPL_IPV6_SRC))); + int id_src, id_dst; + const uint32_t *src, *dst; + + src = nfct_get_attr(ct, ATTR_ORIG_IPV6_SRC); + dst = nfct_get_attr(ct, ATTR_REPL_IPV6_SRC); + + id_src = hashtable_hash(f->h6, src); + id_dst = hashtable_hash(f->h6, dst); + + return hashtable_find(f->h6, src, id_src) || + hashtable_find(f->h6, dst, id_dst); } static int diff --git a/src/hash.c b/src/hash.c index 1edb977..9c9ea5b 100644 --- a/src/hash.c +++ b/src/hash.c @@ -1,5 +1,5 @@ /* - * (C) 2006-2007 by Pablo Neira Ayuso + * (C) 2006-2009 by Pablo Neira Ayuso * * 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 @@ -19,32 +19,13 @@ */ #include "hash.h" -#include "slist.h" #include #include #include -struct hashtable_node *hashtable_alloc_node(int datasize, void *data) -{ - struct hashtable_node *n; - int size = sizeof(struct hashtable_node) + datasize; - - n = calloc(size, 1); - if (n == NULL) - return NULL; - memcpy(n->data, data, datasize); - - return n; -} - -void hashtable_destroy_node(struct hashtable_node *h) -{ - free(h); -} - struct hashtable * -hashtable_create(int hashsize, int limit, int datasize, +hashtable_create(int hashsize, int limit, uint32_t (*hash)(const void *data, const struct hashtable *table), int (*compare)(const void *data1, const void *data2)) @@ -52,7 +33,7 @@ hashtable_create(int hashsize, int limit, int datasize, int i; struct hashtable *h; int size = sizeof(struct hashtable) - + hashsize * sizeof(struct slist_head); + + hashsize * sizeof(struct list_head); h = (struct hashtable *) calloc(size, 1); if (h == NULL) { @@ -61,11 +42,10 @@ hashtable_create(int hashsize, int limit, int datasize, } for (i=0; imembers[i]); + INIT_LIST_HEAD(&h->members[i]); h->hashsize = hashsize; h->limit = limit; - h->datasize = datasize; h->hash = hash; h->compare = compare; @@ -74,112 +54,74 @@ hashtable_create(int hashsize, int limit, int datasize, void hashtable_destroy(struct hashtable *h) { - hashtable_flush(h); free(h); } -void *hashtable_add(struct hashtable *table, void *data) +int hashtable_hash(const struct hashtable *table, const void *data) { - struct slist_head *e; - struct hashtable_node *n; - uint32_t id; - - /* hash table is full */ - if (table->count >= table->limit) { - errno = ENOSPC; - return NULL; - } - - id = table->hash(data, table); - - slist_for_each(e, &table->members[id]) { - n = slist_entry(e, struct hashtable_node, head); - if (table->compare(n->data, data)) { - errno = EEXIST; - return NULL; - } - } - - n = hashtable_alloc_node(table->datasize, data); - if (n == NULL) { - errno = ENOMEM; - return NULL; - } - - slist_add(&table->members[id], &n->head); - table->count++; - - return n->data; + return table->hash(data, table); } -void *hashtable_find(struct hashtable *table, const void *data) +struct hashtable_node * +hashtable_find(const struct hashtable *table, const void *data, int id) { - struct slist_head *e; - uint32_t id; + struct list_head *e; struct hashtable_node *n; - id = table->hash(data, table); - - slist_for_each(e, &table->members[id]) { - n = slist_entry(e, struct hashtable_node, head); - if (table->compare(n->data, data)) - return n->data; + list_for_each(e, &table->members[id]) { + n = list_entry(e, struct hashtable_node, head); + if (table->compare(n, data)) { + return n; + } } - errno = ENOENT; return NULL; } -int hashtable_del(struct hashtable *table, void *data) +int hashtable_add(struct hashtable *table, struct hashtable_node *n, int id) { - struct slist_head *e, *next, *prev; - uint32_t id; - struct hashtable_node *n; - - id = table->hash(data, table); - - slist_for_each_safe(e, prev, next, &table->members[id]) { - n = slist_entry(e, struct hashtable_node, head); - if (table->compare(n->data, data)) { - slist_del(e, prev); - hashtable_destroy_node(n); - table->count--; - return 0; - } + /* hash table is full */ + if (table->count >= table->limit) { + errno = ENOSPC; + return -1; } - errno = ENOENT; - return -1; + list_add(&n->head, &table->members[id]); + table->count++; + return 0; +} + +void hashtable_del(struct hashtable *table, struct hashtable_node *n) +{ + list_del(&n->head); + table->count--; } int hashtable_flush(struct hashtable *table) { uint32_t i; - struct slist_head *e, *next, *prev; + struct list_head *e, *tmp; struct hashtable_node *n; - for (i=0; i < table->hashsize; i++) - slist_for_each_safe(e, prev, next, &table->members[i]) { - n = slist_entry(e, struct hashtable_node, head); - slist_del(e, prev); - hashtable_destroy_node(n); + for (i=0; i < table->hashsize; i++) { + list_for_each_safe(e, tmp, &table->members[i]) { + n = list_entry(e, struct hashtable_node, head); + free(n); } - - table->count = 0; - + } return 0; } int hashtable_iterate(struct hashtable *table, void *data, - int (*iterate)(void *data1, void *data2)) + int (*iterate)(void *data1, struct hashtable_node *n)) { uint32_t i; - struct slist_head *e, *next, *prev; + struct list_head *e, *tmp; struct hashtable_node *n; for (i=0; i < table->hashsize; i++) { - slist_for_each_safe(e, prev, next, &table->members[i]) { - n = slist_entry(e, struct hashtable_node, head); - if (iterate(data, n->data) == -1) + list_for_each_safe(e, tmp, &table->members[i]) { + n = list_entry(e, struct hashtable_node, head); + if (iterate(data, n) == -1) return -1; } } diff --git a/src/stats-mode.c b/src/stats-mode.c index d340b0d..679a50c 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -22,7 +22,6 @@ #include "cache.h" #include "log.h" #include "conntrackd.h" -#include "us-conntrack.h" #include #include @@ -118,9 +117,8 @@ static int overrun_stats(enum nf_conntrack_msg_type type, nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); nfct_attr_unset(ct, ATTR_USE); - if (!cache_test(STATE_STATS(cache), ct)) - if (!cache_update_force(STATE_STATS(cache), ct)) - debug_ct(ct, "overrun stats resync"); + if (!cache_update_force(STATE_STATS(cache), ct)) + debug_ct(ct, "overrun stats resync"); return NFCT_CB_CONTINUE; } @@ -128,12 +126,13 @@ static int overrun_stats(enum nf_conntrack_msg_type type, static int purge_step(void *data1, void *data2) { int ret; - struct us_conntrack *u = data2; + struct cache_object *obj = data2; - ret = nfct_query(STATE(dump), NFCT_Q_GET, u->ct); + ret = nfct_query(STATE(dump), NFCT_Q_GET, obj->ct); if (ret == -1 && errno == ENOENT) { - debug_ct(u->ct, "overrun purge stats"); - cache_del(STATE_STATS(cache), u->ct); + debug_ct(obj->ct, "overrun purge stats"); + cache_del(STATE_STATS(cache), obj); + cache_object_free(obj); } return 0; @@ -148,42 +147,46 @@ static int purge_stats(void) static void event_new_stats(struct nf_conntrack *ct) { + int id; + struct cache_object *obj; + nfct_attr_unset(ct, ATTR_TIMEOUT); - if (cache_add(STATE_STATS(cache), ct)) { - debug_ct(ct, "cache new"); - } else { - if (errno != EEXIST) { - dlog(LOG_ERR, - "can't add to cache cache: %s\n", strerror(errno)); - debug_ct(ct, "can't add"); + obj = cache_find(STATE_STATS(cache), ct, &id); + if (obj == NULL) { + obj = cache_object_new(STATE_STATS(cache), ct); + if (obj == NULL) + return; + + if (cache_add(STATE_STATS(cache), obj, id) == -1) { + cache_object_free(obj); + return; } } + return; } static void event_update_stats(struct nf_conntrack *ct) { nfct_attr_unset(ct, ATTR_TIMEOUT); - - if (!cache_update_force(STATE_STATS(cache), ct)) { - debug_ct(ct, "can't update"); - return; - } - debug_ct(ct, "update"); + cache_update_force(STATE_STATS(cache), ct); } static int event_destroy_stats(struct nf_conntrack *ct) { + int id; + struct cache_object *obj; + nfct_attr_unset(ct, ATTR_TIMEOUT); - if (cache_del(STATE_STATS(cache), ct)) { - debug_ct(ct, "cache destroy"); + obj = cache_find(STATE_STATS(cache), ct, &id); + if (obj) { + cache_del(STATE_STATS(cache), obj); dlog_ct(STATE(stats_log), ct, NFCT_O_PLAIN); + cache_object_free(obj); return 1; - } else { - debug_ct(ct, "can't destroy!"); - return 0; } + return 0; } struct ct_mode stats_mode = { diff --git a/src/sync-alarm.c b/src/sync-alarm.c index d871b75..34937fe 100644 --- a/src/sync-alarm.c +++ b/src/sync-alarm.c @@ -19,7 +19,6 @@ #include "conntrackd.h" #include "sync.h" #include "network.h" -#include "us-conntrack.h" #include "alarm.h" #include "cache.h" #include "debug.h" @@ -30,40 +29,40 @@ static void refresher(struct alarm_block *a, void *data) { struct nethdr *net; - struct us_conntrack *u = data; + struct cache_object *obj = data; - debug_ct(u->ct, "persistence update"); + debug_ct(obj->ct, "persistence update"); add_alarm(a, random() % CONFIG(refresh) + 1, ((random() % 5 + 1) * 200000) - 1); - net = BUILD_NETMSG(u->ct, NET_T_STATE_UPD); + net = BUILD_NETMSG(obj->ct, NET_T_STATE_UPD); mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), net); } -static void cache_alarm_add(struct us_conntrack *u, void *data) +static void cache_alarm_add(struct cache_object *obj, void *data) { - struct alarm_block *alarm = data; + struct alarm_block *a = data; - init_alarm(alarm, u, refresher); - add_alarm(alarm, + init_alarm(a, obj, refresher); + add_alarm(a, random() % CONFIG(refresh) + 1, ((random() % 5 + 1) * 200000) - 1); } -static void cache_alarm_update(struct us_conntrack *u, void *data) +static void cache_alarm_update(struct cache_object *obj, void *data) { - struct alarm_block *alarm = data; - add_alarm(alarm, + struct alarm_block *a = data; + add_alarm(a, random() % CONFIG(refresh) + 1, ((random() % 5 + 1) * 200000) - 1); } -static void cache_alarm_destroy(struct us_conntrack *u, void *data) +static void cache_alarm_destroy(struct cache_object *obj, void *data) { - struct alarm_block *alarm = data; - del_alarm(alarm); + struct alarm_block *a = data; + del_alarm(a); } static struct cache_extra cache_alarm_extra = { diff --git a/src/sync-ftfw.c b/src/sync-ftfw.c index 44e8f2f..bddc18c 100644 --- a/src/sync-ftfw.c +++ b/src/sync-ftfw.c @@ -18,7 +18,6 @@ #include "conntrackd.h" #include "sync.h" -#include "us-conntrack.h" #include "queue.h" #include "debug.h" #include "network.h" @@ -64,7 +63,7 @@ struct cache_ftfw { uint32_t seq; }; -static void cache_ftfw_add(struct us_conntrack *u, void *data) +static void cache_ftfw_add(struct cache_object *obj, void *data) { struct cache_ftfw *cn = data; /* These nodes are not inserted in the list */ @@ -72,7 +71,7 @@ static void cache_ftfw_add(struct us_conntrack *u, void *data) INIT_LIST_HEAD(&cn->tx_list); } -static void cache_ftfw_del(struct us_conntrack *u, void *data) +static void cache_ftfw_del(struct cache_object *obj, void *data) { struct cache_ftfw *cn = data; @@ -190,8 +189,8 @@ static void ftfw_kill(void) static int do_cache_to_tx(void *data1, void *data2) { - struct us_conntrack *u = data2; - struct cache_ftfw *cn = cache_get_extra(STATE_SYNC(internal), u); + struct cache_object *obj = data2; + struct cache_ftfw *cn = cache_get_extra(STATE_SYNC(internal), obj); /* repeated request for resync? */ if (!list_empty(&cn->tx_list)) @@ -226,9 +225,6 @@ static void debug_rs_dump(int fd) size = sprintf(buf, "resent list (len=%u):\n", rs_list_len); send(fd, buf, size, 0); list_for_each_entry_safe(cn, tmp, &rs_list, rs_list) { - struct us_conntrack *u; - - u = cache_get_conntrack(STATE_SYNC(internal), cn); size = sprintf(buf, "seq:%u\n", cn->seq); send(fd, buf, size, 0); } @@ -305,9 +301,9 @@ static void rs_list_to_tx(struct cache *c, unsigned int from, unsigned int to) struct cache_ftfw *cn, *tmp; list_for_each_entry_safe(cn, tmp, &rs_list, rs_list) { - struct us_conntrack *u; + struct cache_object *obj;; - u = cache_get_conntrack(STATE_SYNC(internal), cn); + obj = cache_data_get_object(STATE_SYNC(internal), cn); if (before(cn->seq, from)) continue; else if (after(cn->seq, to)) @@ -330,9 +326,9 @@ static void rs_list_empty(struct cache *c, unsigned int from, unsigned int to) struct cache_ftfw *cn, *tmp; list_for_each_entry_safe(cn, tmp, &rs_list, rs_list) { - struct us_conntrack *u; + struct cache_object *obj; - u = cache_get_conntrack(STATE_SYNC(internal), cn); + obj = cache_data_get_object(STATE_SYNC(internal), cn); if (before(cn->seq, from)) continue; else if (after(cn->seq, to)) @@ -473,7 +469,7 @@ out: return ret; } -static void ftfw_send(struct nethdr *net, struct us_conntrack *u) +static void ftfw_send(struct nethdr *net, struct cache_object *obj) { struct cache_ftfw *cn; @@ -482,7 +478,7 @@ static void ftfw_send(struct nethdr *net, struct us_conntrack *u) case NET_T_STATE_UPD: case NET_T_STATE_DEL: cn = (struct cache_ftfw *) - cache_get_extra(STATE_SYNC(internal), u); + cache_get_extra(STATE_SYNC(internal), obj); if (!list_empty(&cn->rs_list)) { list_del_init(&cn->rs_list); @@ -538,10 +534,10 @@ static int tx_queue_xmit(void *data1, const void *data2) return 0; } -static int tx_list_xmit(struct list_head *i, struct us_conntrack *u, int type) +static int tx_list_xmit(struct list_head *i, struct cache_object *obj, int type) { int ret; - struct nethdr *net = BUILD_NETMSG(u->ct, type); + struct nethdr *net = BUILD_NETMSG(obj->ct, type); dp("tx_list sq: %u fl:%u len:%u\n", ntohl(net->seq), net->flags, ntohs(net->len)); @@ -550,7 +546,7 @@ static int tx_list_xmit(struct list_head *i, struct us_conntrack *u, int type) tx_list_len--; ret = mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), net); - ftfw_send(net, u); + ftfw_send(net, obj); return ret; } @@ -564,13 +560,13 @@ static void ftfw_run(void) /* send conntracks in the tx_list */ list_for_each_entry_safe(cn, tmp, &tx_list, tx_list) { - struct us_conntrack *u; + struct cache_object *obj; - u = cache_get_conntrack(STATE_SYNC(internal), cn); - if (alarm_pending(&u->alarm)) - tx_list_xmit(&cn->tx_list, u, NET_T_STATE_DEL); + obj = cache_data_get_object(STATE_SYNC(internal), cn); + if (alarm_pending(&obj->alarm)) + tx_list_xmit(&cn->tx_list, obj, NET_T_STATE_DEL); else - tx_list_xmit(&cn->tx_list, u, NET_T_STATE_UPD); + tx_list_xmit(&cn->tx_list, obj, NET_T_STATE_UPD); } /* reset alive alarm */ diff --git a/src/sync-mode.c b/src/sync-mode.c index ad2e2ff..368984f 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -22,7 +22,6 @@ #include "log.h" #include "cache.h" #include "conntrackd.h" -#include "us-conntrack.h" #include "network.h" #include "fds.h" #include "event.h" @@ -38,7 +37,8 @@ static void do_mcast_handler_step(struct nethdr *net, size_t remain) { char __ct[nfct_maxsize()]; struct nf_conntrack *ct = (struct nf_conntrack *)(void*) __ct; - struct us_conntrack *u; + struct cache_object *obj; + int id; if (net->version != CONNTRACKD_PROTOCOL_VERSION) { STATE_SYNC(error).msg_rcv_malformed++; @@ -75,33 +75,32 @@ static void do_mcast_handler_step(struct nethdr *net, size_t remain) switch(net->type) { case NET_T_STATE_NEW: -retry: - if ((u = cache_add(STATE_SYNC(external), ct))) { - debug_ct(u->ct, "external new"); - } else { - /* - * One certain connection A arrives to the cache but - * another existing connection B in the cache has - * the same configuration, therefore B clashes with A. - */ - if (errno == EEXIST) { - cache_del(STATE_SYNC(external), ct); - goto retry; + obj = cache_find(STATE_SYNC(external), ct, &id); + if (obj == NULL) { +retry: + obj = cache_object_new(STATE_SYNC(external), ct); + if (obj == NULL) + return; + + if (cache_add(STATE_SYNC(external), obj, id) == -1) { + cache_object_free(obj); + return; } - debug_ct(ct, "can't add"); + } else { + cache_del(STATE_SYNC(external), obj); + cache_object_free(obj); + goto retry; } break; case NET_T_STATE_UPD: - if ((u = cache_update_force(STATE_SYNC(external), ct))) { - debug_ct(u->ct, "external update"); - } else - debug_ct(ct, "can't update"); + cache_update_force(STATE_SYNC(external), ct); break; case NET_T_STATE_DEL: - if (cache_del(STATE_SYNC(external), ct)) - debug_ct(ct, "external destroy"); - else - debug_ct(ct, "can't destroy"); + obj = cache_find(STATE_SYNC(external), ct, &id); + if (obj) { + cache_del(STATE_SYNC(external), obj); + cache_object_free(obj); + } break; default: STATE_SYNC(error).msg_rcv_malformed++; @@ -441,14 +440,14 @@ static void dump_sync(struct nf_conntrack *ct) debug_ct(ct, "resync"); } -static void mcast_send_sync(struct us_conntrack *u, int query) +static void mcast_send_sync(struct cache_object *obj, int query) { struct nethdr *net; - net = BUILD_NETMSG(u->ct, query); + net = BUILD_NETMSG(obj->ct, query); if (STATE_SYNC(sync)->send) - STATE_SYNC(sync)->send(net, u); + STATE_SYNC(sync)->send(net, obj); mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), net); } @@ -457,13 +456,13 @@ static int purge_step(void *data1, void *data2) { int ret; struct nfct_handle *h = STATE(dump); - struct us_conntrack *u = data2; + struct cache_object *obj = data2; - ret = nfct_query(h, NFCT_Q_GET, u->ct); + ret = nfct_query(h, NFCT_Q_GET, obj->ct); if (ret == -1 && errno == ENOENT) { - debug_ct(u->ct, "overrun purge resync"); - mcast_send_sync(u, NET_T_STATE_DEL); - __cache_del_timer(STATE_SYNC(internal), u, CONFIG(del_timeout)); + debug_ct(obj->ct, "overrun purge resync"); + mcast_send_sync(obj, NET_T_STATE_DEL); + cache_del_timer(STATE_SYNC(internal), obj, CONFIG(del_timeout)); } return 0; @@ -480,7 +479,7 @@ static int overrun_sync(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data) { - struct us_conntrack *u; + struct cache_object *obj; if (ct_filter_conntrack(ct, 1)) return NFCT_CB_CONTINUE; @@ -492,11 +491,9 @@ static int overrun_sync(enum nf_conntrack_msg_type type, nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); nfct_attr_unset(ct, ATTR_USE); - if (!cache_test(STATE_SYNC(internal), ct)) { - if ((u = cache_update_force(STATE_SYNC(internal), ct))) { - debug_ct(u->ct, "overrun resync"); - mcast_send_sync(u, NET_T_STATE_UPD); - } + if ((obj = cache_update_force(STATE_SYNC(internal), ct))) { + debug_ct(obj->ct, "overrun resync"); + mcast_send_sync(obj, NET_T_STATE_UPD); } return NFCT_CB_CONTINUE; @@ -504,50 +501,59 @@ static int overrun_sync(enum nf_conntrack_msg_type type, static void event_new_sync(struct nf_conntrack *ct) { - struct us_conntrack *u; + struct cache_object *obj; + int id; /* required by linux kernel <= 2.6.20 */ nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES); nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS); nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES); nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); + + obj = cache_find(STATE_SYNC(internal), ct, &id); + if (obj == NULL) { retry: - if ((u = cache_add(STATE_SYNC(internal), ct))) { - mcast_send_sync(u, NET_T_STATE_NEW); - debug_ct(u->ct, "internal new"); - } else { - if (errno == EEXIST) { - cache_del(STATE_SYNC(internal), ct); - goto retry; + obj = cache_object_new(STATE_SYNC(internal), ct); + if (obj == NULL) + return; + if (cache_add(STATE_SYNC(internal), obj, id) == -1) { + cache_object_free(obj); + return; } + mcast_send_sync(obj, NET_T_STATE_NEW); + debug_ct(obj->ct, "internal new"); + } else { + cache_del(STATE_SYNC(internal), obj); + cache_object_free(obj); debug_ct(ct, "can't add"); + goto retry; } } static void event_update_sync(struct nf_conntrack *ct) { - struct us_conntrack *u; + struct cache_object *obj; - if ((u = cache_update_force(STATE_SYNC(internal), ct)) == NULL) { + if ((obj = cache_update_force(STATE_SYNC(internal), ct)) == NULL) { debug_ct(ct, "can't update"); return; } - debug_ct(u->ct, "internal update"); - mcast_send_sync(u, NET_T_STATE_UPD); + debug_ct(obj->ct, "internal update"); + mcast_send_sync(obj, NET_T_STATE_UPD); } static int event_destroy_sync(struct nf_conntrack *ct) { - struct us_conntrack *u; + struct cache_object *obj; + int id; - u = cache_find(STATE_SYNC(internal), ct); - if (u == NULL) { + obj = cache_find(STATE_SYNC(internal), ct, &id); + if (obj == NULL) { debug_ct(ct, "can't destroy"); return 0; } - - mcast_send_sync(u, NET_T_STATE_DEL); - __cache_del_timer(STATE_SYNC(internal), u, CONFIG(del_timeout)); + mcast_send_sync(obj, NET_T_STATE_DEL); + cache_del_timer(STATE_SYNC(internal), obj, CONFIG(del_timeout)); debug_ct(ct, "internal destroy"); return 1; } diff --git a/src/sync-notrack.c b/src/sync-notrack.c index 700e272..2d3783e 100644 --- a/src/sync-notrack.c +++ b/src/sync-notrack.c @@ -18,7 +18,6 @@ #include "conntrackd.h" #include "sync.h" -#include "us-conntrack.h" #include "queue.h" #include "debug.h" #include "network.h" @@ -36,13 +35,13 @@ struct cache_notrack { struct list_head tx_list; }; -static void cache_notrack_add(struct us_conntrack *u, void *data) +static void cache_notrack_add(struct cache_object *obj, void *data) { struct cache_notrack *cn = data; INIT_LIST_HEAD(&cn->tx_list); } -static void cache_notrack_del(struct us_conntrack *u, void *data) +static void cache_notrack_del(struct cache_object *obj, void *data) { struct cache_notrack *cn = data; @@ -89,8 +88,8 @@ static void notrack_kill(void) static int do_cache_to_tx(void *data1, void *data2) { - struct us_conntrack *u = data2; - struct cache_notrack *cn = cache_get_extra(STATE_SYNC(internal), u); + struct cache_object *obj = data2; + struct cache_notrack *cn = cache_get_extra(STATE_SYNC(internal), obj); if (!list_empty(&cn->tx_list)) return 0; @@ -164,10 +163,10 @@ static int tx_queue_xmit(void *data1, const void *data2) return 0; } -static int tx_list_xmit(struct list_head *i, struct us_conntrack *u, int type) +static int tx_list_xmit(struct list_head *i, struct cache_object *obj, int type) { int ret; - struct nethdr *net = BUILD_NETMSG(u->ct, type); + struct nethdr *net = BUILD_NETMSG(obj->ct, type); list_del_init(i); tx_list_len--; @@ -186,10 +185,10 @@ static void notrack_run(void) /* send conntracks in the tx_list */ list_for_each_entry_safe(cn, tmp, &tx_list, tx_list) { - struct us_conntrack *u; + struct cache_object *obj; - u = cache_get_conntrack(STATE_SYNC(internal), cn); - tx_list_xmit(&cn->tx_list, u, NET_T_STATE_UPD); + obj = cache_data_get_object(STATE_SYNC(internal), cn); + tx_list_xmit(&cn->tx_list, obj, NET_T_STATE_UPD); } } -- cgit v1.2.3 From c54c8c9287fc87177daf9b51933f92c7e6402904 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 17 Jan 2009 18:03:52 +0100 Subject: src: rename overrun handler to resync handler This patch is a cleanup. The overrun handler is actually a way to resynchronize against the conntrack kernel table. The name overrun was used because it was initially its purpose. The new naming shows its genericity. Signed-off-by: Pablo Neira Ayuso --- include/conntrackd.h | 10 +++++----- include/netlink.h | 4 ++-- src/netlink.c | 4 ++-- src/run.c | 22 +++++++++++----------- src/stats-mode.c | 12 ++++++------ src/sync-mode.c | 12 ++++++------ 6 files changed, 32 insertions(+), 32 deletions(-) (limited to 'src/stats-mode.c') diff --git a/include/conntrackd.h b/include/conntrackd.h index ab5d825..d5b61c6 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -111,8 +111,8 @@ struct ct_general_state { struct nfct_handle *dump; /* dump handler */ struct nfct_handle *request; /* request handler */ - struct nfct_handle *overrun; /* overrun handler */ - struct alarm_block overrun_alarm; + struct nfct_handle *resync; /* resync handler */ + struct alarm_block resync_alarm; struct fds *fds; @@ -204,9 +204,9 @@ struct ct_mode { int (*local)(int fd, int type, void *data); void (*kill)(void); void (*dump)(struct nf_conntrack *ct); - int (*overrun)(enum nf_conntrack_msg_type type, - struct nf_conntrack *ct, - void *data); + int (*resync)(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data); int (*purge)(void); void (*event_new)(struct nf_conntrack *ct); void (*event_upd)(struct nf_conntrack *ct); diff --git a/include/netlink.h b/include/netlink.h index 4bc5ee4..a8eb919 100644 --- a/include/netlink.h +++ b/include/netlink.h @@ -9,10 +9,10 @@ struct nfct_handle; struct nfct_handle *nl_init_event_handler(void); struct nfct_handle *nl_init_dump_handler(void); struct nfct_handle *nl_init_request_handler(void); -struct nfct_handle *nl_init_overrun_handler(void); +struct nfct_handle *nl_init_resync_handler(void); struct nlif_handle *nl_init_interface_handler(void); -int nl_overrun_request_resync(struct nfct_handle *h); +int nl_send_resync(struct nfct_handle *h); void nl_resize_socket_buffer(struct nfct_handle *h); int nl_dump_conntrack_table(struct nfct_handle *h); int nl_flush_conntrack_table(struct nfct_handle *h); diff --git a/src/netlink.c b/src/netlink.c index 2266201..15a30f6 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -90,7 +90,7 @@ struct nfct_handle *nl_init_dump_handler(void) return h; } -struct nfct_handle *nl_init_overrun_handler(void) +struct nfct_handle *nl_init_resync_handler(void) { struct nfct_handle *h; @@ -172,7 +172,7 @@ int nl_flush_conntrack_table(struct nfct_handle *h) return nfct_query(h, NFCT_Q_FLUSH, &CONFIG(family)); } -int nl_overrun_request_resync(struct nfct_handle *h) +int nl_send_resync(struct nfct_handle *h) { int family = CONFIG(family); return nfct_send(h, NFCT_Q_DUMP, &family); diff --git a/src/run.c b/src/run.c index 2e373ce..b436113 100644 --- a/src/run.c +++ b/src/run.c @@ -204,9 +204,9 @@ void local_handler(int fd, void *data) STATE(stats).local_unknown_request++; } -static void do_overrun_alarm(struct alarm_block *a, void *data) +static void do_resync_alarm(struct alarm_block *a, void *data) { - nl_overrun_request_resync(STATE(overrun)); + nl_send_resync(STATE(resync)); STATE(stats).nl_kernel_table_resync++; } @@ -313,16 +313,16 @@ init(void) return -1; } - STATE(overrun) = nl_init_overrun_handler(); - if (STATE(overrun)== NULL) { + STATE(resync) = nl_init_resync_handler(); + if (STATE(resync)== NULL) { dlog(LOG_ERR, "can't open netlink handler: %s", strerror(errno)); dlog(LOG_ERR, "no ctnetlink kernel support?"); return -1; } - nfct_callback_register(STATE(overrun), + nfct_callback_register(STATE(resync), NFCT_T_ALL, - STATE(mode)->overrun, + STATE(mode)->resync, NULL); /* no callback, it does not do anything with the output */ @@ -334,7 +334,7 @@ init(void) return -1; } - init_alarm(&STATE(overrun_alarm), NULL, do_overrun_alarm); + init_alarm(&STATE(resync_alarm), NULL, do_resync_alarm); STATE(fds) = create_fds(); if (STATE(fds) == NULL) { @@ -344,7 +344,7 @@ init(void) register_fd(STATE(local).fd, STATE(fds)); register_fd(nfct_fd(STATE(event)), STATE(fds)); - register_fd(nfct_fd(STATE(overrun)), STATE(fds)); + register_fd(nfct_fd(STATE(resync)), STATE(fds)); if (STATE(mode)->register_fds && STATE(mode)->register_fds(STATE(fds)) == -1) { @@ -435,7 +435,7 @@ static void __run(struct timeval *next_alarm) * we resync ourselves. */ nl_resize_socket_buffer(STATE(event)); - add_alarm(&STATE(overrun_alarm), OVRUN_INT, 0); + add_alarm(&STATE(resync_alarm), OVRUN_INT, 0); STATE(stats).nl_catch_event_failed++; STATE(stats).nl_overrun++; break; @@ -455,8 +455,8 @@ static void __run(struct timeval *next_alarm) } } - if (FD_ISSET(nfct_fd(STATE(overrun)), &readfds)) { - nfct_catch(STATE(overrun)); + if (FD_ISSET(nfct_fd(STATE(resync)), &readfds)) { + nfct_catch(STATE(resync)); if (STATE(mode)->purge) STATE(mode)->purge(); } diff --git a/src/stats-mode.c b/src/stats-mode.c index 679a50c..159bbef 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -102,9 +102,9 @@ static void dump_stats(struct nf_conntrack *ct) debug_ct(ct, "resync entry"); } -static int overrun_stats(enum nf_conntrack_msg_type type, - struct nf_conntrack *ct, - void *data) +static int resync_stats(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data) { if (ct_filter_conntrack(ct, 1)) return NFCT_CB_CONTINUE; @@ -118,7 +118,7 @@ static int overrun_stats(enum nf_conntrack_msg_type type, nfct_attr_unset(ct, ATTR_USE); if (!cache_update_force(STATE_STATS(cache), ct)) - debug_ct(ct, "overrun stats resync"); + debug_ct(ct, "stats resync"); return NFCT_CB_CONTINUE; } @@ -130,7 +130,7 @@ static int purge_step(void *data1, void *data2) ret = nfct_query(STATE(dump), NFCT_Q_GET, obj->ct); if (ret == -1 && errno == ENOENT) { - debug_ct(obj->ct, "overrun purge stats"); + debug_ct(obj->ct, "purge stats"); cache_del(STATE_STATS(cache), obj); cache_object_free(obj); } @@ -196,7 +196,7 @@ struct ct_mode stats_mode = { .local = local_handler_stats, .kill = kill_stats, .dump = dump_stats, - .overrun = overrun_stats, + .resync = resync_stats, .purge = purge_stats, .event_new = event_new_stats, .event_upd = event_update_stats, diff --git a/src/sync-mode.c b/src/sync-mode.c index 0dbd12d..2e189cb 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -518,7 +518,7 @@ static int purge_step(void *data1, void *data2) ret = nfct_query(h, NFCT_Q_GET, obj->ct); if (ret == -1 && errno == ENOENT) { - debug_ct(obj->ct, "overrun purge resync"); + debug_ct(obj->ct, "purge resync"); if (obj->status != C_OBJ_DEAD) { cache_object_set_status(obj, C_OBJ_DEAD); mcast_send_sync(obj, NET_T_STATE_DEL); @@ -536,9 +536,9 @@ static int purge_sync(void) return 0; } -static int overrun_sync(enum nf_conntrack_msg_type type, - struct nf_conntrack *ct, - void *data) +static int resync_sync(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data) { struct cache_object *obj; @@ -553,7 +553,7 @@ static int overrun_sync(enum nf_conntrack_msg_type type, nfct_attr_unset(ct, ATTR_USE); if ((obj = cache_update_force(STATE_SYNC(internal), ct))) { - debug_ct(obj->ct, "overrun resync"); + debug_ct(obj->ct, "resync"); mcast_send_sync(obj, NET_T_STATE_UPD); } @@ -629,7 +629,7 @@ struct ct_mode sync_mode = { .local = local_handler_sync, .kill = kill_sync, .dump = dump_sync, - .overrun = overrun_sync, + .resync = resync_sync, .purge = purge_sync, .event_new = event_new_sync, .event_upd = event_update_sync, -- cgit v1.2.3 From 05194422ee8fa038d99fe77a2e9d776d25623fd2 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 17 Jan 2009 18:03:53 +0100 Subject: src: remove register_fds hooks This patch moves the file descriptor registration after the initialization instead of having a specific hook for this. Signed-off-by: Pablo Neira Ayuso --- include/conntrackd.h | 1 - src/run.c | 25 +++++++++---------------- src/stats-mode.c | 1 - src/sync-mode.c | 31 ++++++++++++------------------- 4 files changed, 21 insertions(+), 37 deletions(-) (limited to 'src/stats-mode.c') diff --git a/include/conntrackd.h b/include/conntrackd.h index d5b61c6..fbf126a 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -199,7 +199,6 @@ extern struct ct_general_state st; struct ct_mode { int (*init)(void); - int (*register_fds)(struct fds *fds); void (*run)(fd_set *readfds); int (*local)(int fd, int type, void *data); void (*kill)(void); diff --git a/src/run.c b/src/run.c index b436113..a6dfe15 100644 --- a/src/run.c +++ b/src/run.c @@ -278,6 +278,12 @@ init(void) STATE(mode) = &stats_mode; } + STATE(fds) = create_fds(); + if (STATE(fds) == NULL) { + dlog(LOG_ERR, "can't create file descriptor pool"); + return -1; + } + /* Initialization */ if (STATE(mode)->init() == -1) { dlog(LOG_ERR, "initialization failed"); @@ -289,6 +295,7 @@ init(void) dlog(LOG_ERR, "can't open unix socket!"); return -1; } + register_fd(STATE(local).fd, STATE(fds)); STATE(event) = nl_init_event_handler(); if (STATE(event) == NULL) { @@ -298,6 +305,7 @@ init(void) return -1; } nfct_callback_register(STATE(event), NFCT_T_ALL, event_handler, NULL); + register_fd(nfct_fd(STATE(event)), STATE(fds)); STATE(dump) = nl_init_dump_handler(); if (STATE(dump) == NULL) { @@ -324,6 +332,7 @@ init(void) NFCT_T_ALL, STATE(mode)->resync, NULL); + register_fd(nfct_fd(STATE(resync)), STATE(fds)); /* no callback, it does not do anything with the output */ STATE(request) = nl_init_request_handler(); @@ -336,22 +345,6 @@ init(void) init_alarm(&STATE(resync_alarm), NULL, do_resync_alarm); - STATE(fds) = create_fds(); - if (STATE(fds) == NULL) { - dlog(LOG_ERR, "can't create file descriptor pool"); - return -1; - } - - register_fd(STATE(local).fd, STATE(fds)); - register_fd(nfct_fd(STATE(event)), STATE(fds)); - register_fd(nfct_fd(STATE(resync)), STATE(fds)); - - if (STATE(mode)->register_fds && - STATE(mode)->register_fds(STATE(fds)) == -1) { - dlog(LOG_ERR, "fds registration failed"); - return -1; - } - /* Signals handling */ sigemptyset(&STATE(block)); sigaddset(&STATE(block), SIGTERM); diff --git a/src/stats-mode.c b/src/stats-mode.c index 159bbef..b742c0c 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -191,7 +191,6 @@ static int event_destroy_stats(struct nf_conntrack *ct) struct ct_mode stats_mode = { .init = init_stats, - .register_fds = NULL, .run = NULL, .local = local_handler_stats, .kill = kill_stats, diff --git a/src/sync-mode.c b/src/sync-mode.c index 2e189cb..54d0ebb 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -207,6 +207,8 @@ static void mcast_iface_handler(void) static int init_sync(void) { + int i; + state.sync = malloc(sizeof(struct ct_sync_state)); if (!state.sync) { dlog(LOG_ERR, "can't allocate memory for sync"); @@ -261,6 +263,11 @@ static int init_sync(void) dlog(LOG_ERR, "can't open multicast server!"); return -1; } + for (i=0; inum_links; i++) { + int fd = mcast_get_fd(STATE_SYNC(mcast_server)->multi[i]); + if (register_fd(fd, STATE(fds)) == -1) + return -1; + } /* multicast client to send events on the wire */ STATE_SYNC(mcast_client) = @@ -286,12 +293,17 @@ static int init_sync(void) dlog(LOG_ERR, "can't open interface watcher"); return -1; } + if (register_fd(nlif_fd(STATE_SYNC(mcast_iface)), STATE(fds)) == -1) + return -1; STATE_SYNC(tx_queue) = queue_create(INT_MAX, QUEUE_F_EVFD); if (STATE_SYNC(tx_queue) == NULL) { dlog(LOG_ERR, "cannot create tx queue"); return -1; } + if (register_fd(queue_get_eventfd(STATE_SYNC(tx_queue)), + STATE(fds)) == -1) + return -1; /* initialization of multicast sequence generation */ STATE_SYNC(last_seq_sent) = time(NULL); @@ -299,24 +311,6 @@ static int init_sync(void) return 0; } -static int register_fds_sync(struct fds *fds) -{ - int i; - - for (i=0; inum_links; i++) { - int fd = mcast_get_fd(STATE_SYNC(mcast_server)->multi[i]); - if (register_fd(fd, fds) == -1) - return -1; - } - if (register_fd(nlif_fd(STATE_SYNC(mcast_iface)), fds) == -1) - return -1; - - if (register_fd(queue_get_eventfd(STATE_SYNC(tx_queue)), fds) == -1) - return -1; - - return 0; -} - static void run_sync(fd_set *readfds) { int i; @@ -624,7 +618,6 @@ static int event_destroy_sync(struct nf_conntrack *ct) struct ct_mode sync_mode = { .init = init_sync, - .register_fds = register_fds_sync, .run = run_sync, .local = local_handler_sync, .kill = kill_sync, -- cgit v1.2.3 From 1c9faf8c218bc7ff4617557383e4116f1adb11e5 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 25 Jan 2009 17:53:02 +0100 Subject: cache: move lifetime feature to main cache code The lifetime feature is used by all working modes, it is useful to know how long it has been an entry living in the cache. This patch moves the lifetime feature to the main caching code. Signed-off-by: Pablo Neira Ayuso --- include/cache.h | 6 ++--- src/Makefile.am | 2 +- src/cache.c | 3 ++- src/cache_iterators.c | 6 +++++ src/cache_lifetime.c | 65 --------------------------------------------------- src/stats-mode.c | 4 +--- src/sync-alarm.c | 4 ++-- src/sync-ftfw.c | 4 ++-- src/sync-notrack.c | 4 ++-- 9 files changed, 18 insertions(+), 80 deletions(-) delete mode 100644 src/cache_lifetime.c (limited to 'src/stats-mode.c') diff --git a/include/cache.h b/include/cache.h index 5e96dd3..1fd3881 100644 --- a/include/cache.h +++ b/include/cache.h @@ -12,10 +12,7 @@ enum { TIMER_FEATURE = 0, TIMER = (1 << TIMER_FEATURE), - LIFETIME_FEATURE = 2, - LIFETIME = (1 << LIFETIME_FEATURE), - - WRITE_THROUGH_FEATURE = 3, + WRITE_THROUGH_FEATURE = 1, WRITE_THROUGH = (1 << WRITE_THROUGH_FEATURE), __CACHE_MAX_FEATURE @@ -36,6 +33,7 @@ struct cache_object { struct cache *cache; int status; int refcnt; + long lifetime; char data[0]; }; diff --git a/src/Makefile.am b/src/Makefile.am index 64ed2b5..8ba09e1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,7 +14,7 @@ conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c rbtree.c \ local.c log.c mcast.c netlink.c vector.c \ filter.c fds.c event.c \ cache.c cache_iterators.c \ - cache_lifetime.c cache_timer.c cache_wt.c \ + cache_timer.c cache_wt.c \ sync-mode.c sync-alarm.c sync-ftfw.c sync-notrack.c \ traffic_stats.c stats-mode.c \ network.c cidr.c \ diff --git a/src/cache.c b/src/cache.c index a5f37dd..71825e1 100644 --- a/src/cache.c +++ b/src/cache.c @@ -26,6 +26,7 @@ #include #include #include +#include static uint32_t __hash4(const struct nf_conntrack *ct, const struct hashtable *table) @@ -94,7 +95,6 @@ static int compare(const void *data1, const void *data2) struct cache_feature *cache_feature[CACHE_MAX_FEATURE] = { [TIMER_FEATURE] = &timer_feature, - [LIFETIME_FEATURE] = &lifetime_feature, [WRITE_THROUGH_FEATURE] = &writethrough_feature, }; @@ -249,6 +249,7 @@ static int __add(struct cache *c, struct cache_object *obj, int id) c->extra->add(obj, ((char *) obj) + c->extra_offset); c->stats.active++; + obj->lifetime = time(NULL); obj->status = C_OBJ_NEW; obj->refcnt++; return 0; diff --git a/src/cache_iterators.c b/src/cache_iterators.c index 4bf518a..3a1ec72 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -26,6 +26,7 @@ #include #include #include +#include struct __dump_container { int fd; @@ -75,6 +76,11 @@ static int do_dump(void *data1, struct hashtable_node *n) data += obj->cache->features[i]->size; } } + if (container->type != NFCT_O_XML) { + long tm = time(NULL); + size += sprintf(buf+size, " [active since %lds]", + tm - obj->lifetime); + } size += sprintf(buf+size, "\n"); if (send(container->fd, buf, size, 0) == -1) { if (errno != EPIPE) diff --git a/src/cache_lifetime.c b/src/cache_lifetime.c deleted file mode 100644 index 639d8c1..0000000 --- a/src/cache_lifetime.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * (C) 2006 by Pablo Neira Ayuso - * - * 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 -#include "cache.h" -#include -#include -#include - -static void lifetime_add(struct cache_object *obj, void *data) -{ - long *lifetime = data; - struct timeval tv; - - gettimeofday(&tv, NULL); - - *lifetime = tv.tv_sec; -} - -static void lifetime_update(struct cache_object *obj, void *data) -{ -} - -static void lifetime_destroy(struct cache_object *obj, void *data) -{ -} - -static int lifetime_dump(struct cache_object *obj, - void *data, - char *buf, - int type) -{ - long *lifetime = data; - struct timeval tv; - - if (type == NFCT_O_XML) - return 0; - - gettimeofday(&tv, NULL); - - return sprintf(buf, " [active since %lds]", tv.tv_sec - *lifetime); -} - -struct cache_feature lifetime_feature = { - .size = sizeof(long), - .add = lifetime_add, - .update = lifetime_update, - .destroy = lifetime_destroy, - .dump = lifetime_dump -}; diff --git a/src/stats-mode.c b/src/stats-mode.c index b742c0c..226a6b8 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -37,9 +37,7 @@ static int init_stats(void) } memset(state.stats, 0, sizeof(struct ct_stats_state)); - STATE_STATS(cache) = cache_create("stats", - LIFETIME, - NULL); + STATE_STATS(cache) = cache_create("stats", NO_FEATURES, NULL); if (!STATE_STATS(cache)) { dlog(LOG_ERR, "can't allocate memory for the " "external cache"); diff --git a/src/sync-alarm.c b/src/sync-alarm.c index a2f17ac..1815447 100644 --- a/src/sync-alarm.c +++ b/src/sync-alarm.c @@ -154,8 +154,8 @@ static void alarm_xmit(void) } struct sync_mode sync_alarm = { - .internal_cache_flags = LIFETIME, - .external_cache_flags = TIMER | LIFETIME, + .internal_cache_flags = NO_FEATURES, + .external_cache_flags = TIMER, .internal_cache_extra = &cache_alarm_extra, .recv = alarm_recv, .enqueue = alarm_enqueue, diff --git a/src/sync-ftfw.c b/src/sync-ftfw.c index fd6c350..91ce25d 100644 --- a/src/sync-ftfw.c +++ b/src/sync-ftfw.c @@ -561,8 +561,8 @@ static void ftfw_enqueue(struct cache_object *obj, int type) } struct sync_mode sync_ftfw = { - .internal_cache_flags = LIFETIME, - .external_cache_flags = LIFETIME, + .internal_cache_flags = NO_FEATURES, + .external_cache_flags = NO_FEATURES, .internal_cache_extra = &cache_ftfw_extra, .init = ftfw_init, .kill = ftfw_kill, diff --git a/src/sync-notrack.c b/src/sync-notrack.c index 3b547ee..7bd4351 100644 --- a/src/sync-notrack.c +++ b/src/sync-notrack.c @@ -173,8 +173,8 @@ static void notrack_enqueue(struct cache_object *obj, int query) } struct sync_mode sync_notrack = { - .internal_cache_flags = LIFETIME, - .external_cache_flags = LIFETIME, + .internal_cache_flags = NO_FEATURES, + .external_cache_flags = NO_FEATURES, .internal_cache_extra = &cache_notrack_extra, .local = notrack_local, .recv = notrack_recv, -- cgit v1.2.3 From ba2f8458ecfa0827e09a1c40c9e29868239fafa1 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 6 Feb 2009 17:43:40 +0100 Subject: src: re-work polling strategy This patch improves the polling support included in 0.9.10. The polling now consists of getting the state table, wait for PollSecs, then purge obsolete entries, and so on. Signed-off-by: Pablo Neira Ayuso --- include/conntrackd.h | 4 +++ src/run.c | 85 ++++++++++++++++++++++++++++++++++++---------------- src/stats-mode.c | 6 ++-- src/sync-mode.c | 28 ++++++++++------- 4 files changed, 83 insertions(+), 40 deletions(-) (limited to 'src/stats-mode.c') diff --git a/include/conntrackd.h b/include/conntrackd.h index 3e10a2f..34c7629 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -114,7 +114,11 @@ struct ct_general_state { struct nfct_handle *dump; /* dump handler */ struct nfct_handle *request; /* request handler */ struct nfct_handle *resync; /* resync handler */ + struct nfct_handle *get; /* get handler */ + int get_retval; /* hackish */ + struct alarm_block resync_alarm; + struct alarm_block polling_alarm; struct fds *fds; diff --git a/src/run.c b/src/run.c index 7d48865..81f2590 100644 --- a/src/run.c +++ b/src/run.c @@ -1,5 +1,5 @@ /* - * (C) 2006-2007 by Pablo Neira Ayuso + * (C) 2006-2009 by Pablo Neira Ayuso * * 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 @@ -40,8 +40,11 @@ void killer(int foo) /* no signals while handling signals */ sigprocmask(SIG_BLOCK, &STATE(block), NULL); - if (!(CONFIG(flags) & CTD_POLL)) + if (!(CONFIG(flags) & CTD_POLL)) { nfct_close(STATE(event)); + nfct_close(STATE(resync)); + } + nfct_close(STATE(get)); nfct_close(STATE(request)); if (STATE(us_filter)) @@ -212,10 +215,13 @@ static void do_overrun_resync_alarm(struct alarm_block *a, void *data) STATE(stats).nl_kernel_table_resync++; } -static void do_poll_resync_alarm(struct alarm_block *a, void *data) +static void do_polling_alarm(struct alarm_block *a, void *data) { - nl_send_resync(STATE(resync)); - add_alarm(&STATE(resync_alarm), CONFIG(poll_kernel_secs), 0); + if (STATE(mode)->purge) + STATE(mode)->purge(); + + nl_send_resync(STATE(dump)); + add_alarm(&STATE(polling_alarm), CONFIG(poll_kernel_secs), 0); } static int event_handler(enum nf_conntrack_msg_type type, @@ -272,6 +278,17 @@ static int dump_handler(enum nf_conntrack_msg_type type, return NFCT_CB_CONTINUE; } +static int get_handler(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data) +{ + if (ct_filter_conntrack(ct, 1)) + return NFCT_CB_CONTINUE; + + STATE(get_retval) = 1; + return NFCT_CB_CONTINUE; +} + int init(void) { @@ -316,6 +333,20 @@ init(void) nfct_callback_register(STATE(event), NFCT_T_ALL, event_handler, NULL); register_fd(nfct_fd(STATE(event)), STATE(fds)); + + STATE(resync) = nfct_open(CONNTRACK, 0); + if (STATE(resync)== NULL) { + dlog(LOG_ERR, "can't open netlink handler: %s", + strerror(errno)); + dlog(LOG_ERR, "no ctnetlink kernel support?"); + return -1; + } + nfct_callback_register(STATE(resync), + NFCT_T_ALL, + STATE(mode)->resync, + NULL); + register_fd(nfct_fd(STATE(resync)), STATE(fds)); + fcntl(nfct_fd(STATE(resync)), F_SETFL, O_NONBLOCK); } STATE(dump) = nfct_open(CONNTRACK, 0); @@ -326,25 +357,22 @@ init(void) return -1; } nfct_callback_register(STATE(dump), NFCT_T_ALL, dump_handler, NULL); + if (CONFIG(flags) & CTD_POLL) + register_fd(nfct_fd(STATE(dump)), STATE(fds)); if (nl_dump_conntrack_table(STATE(dump)) == -1) { dlog(LOG_ERR, "can't get kernel conntrack table"); return -1; } - STATE(resync) = nfct_open(CONNTRACK, 0); - if (STATE(resync)== NULL) { + STATE(get) = nfct_open(CONNTRACK, 0); + if (STATE(get) == NULL) { dlog(LOG_ERR, "can't open netlink handler: %s", strerror(errno)); dlog(LOG_ERR, "no ctnetlink kernel support?"); return -1; } - nfct_callback_register(STATE(resync), - NFCT_T_ALL, - STATE(mode)->resync, - NULL); - register_fd(nfct_fd(STATE(resync)), STATE(fds)); - fcntl(nfct_fd(STATE(resync)), F_SETFL, O_NONBLOCK); + nfct_callback_register(STATE(get), NFCT_T_ALL, get_handler, NULL); /* no callback, it does not do anything with the output */ STATE(request) = nfct_open(CONNTRACK, 0); @@ -356,8 +384,8 @@ init(void) } if (CONFIG(flags) & CTD_POLL) { - init_alarm(&STATE(resync_alarm), NULL, do_poll_resync_alarm); - add_alarm(&STATE(resync_alarm), CONFIG(poll_kernel_secs), 0); + init_alarm(&STATE(polling_alarm), NULL, do_polling_alarm); + add_alarm(&STATE(polling_alarm), CONFIG(poll_kernel_secs), 0); dlog(LOG_NOTICE, "running in polling mode"); } else { init_alarm(&STATE(resync_alarm), NULL, do_overrun_resync_alarm); @@ -414,11 +442,11 @@ static void __run(struct timeval *next_alarm) if (FD_ISSET(STATE(local).fd, &readfds)) do_local_server_step(&STATE(local), NULL, local_handler); - /* conntrack event has happened */ - if (!(CONFIG(flags) & CTD_POLL) && - FD_ISSET(nfct_fd(STATE(event)), &readfds)) { - ret = nfct_catch(STATE(event)); - if (ret == -1) { + if (!(CONFIG(flags) & CTD_POLL)) { + /* conntrack event has happened */ + if (FD_ISSET(nfct_fd(STATE(event)), &readfds)) { + ret = nfct_catch(STATE(event)); + if (ret == -1) { switch(errno) { case ENOBUFS: /* We have hit ENOBUFS, it's likely that we are @@ -464,13 +492,18 @@ static void __run(struct timeval *next_alarm) STATE(stats).nl_catch_event_failed++; break; } + } + } + if (FD_ISSET(nfct_fd(STATE(resync)), &readfds)) { + nfct_catch(STATE(resync)); + if (STATE(mode)->purge) + STATE(mode)->purge(); + } + } else { + /* using polling mode */ + if (FD_ISSET(nfct_fd(STATE(dump)), &readfds)) { + nfct_catch(STATE(dump)); } - } - - if (FD_ISSET(nfct_fd(STATE(resync)), &readfds)) { - nfct_catch(STATE(resync)); - if (STATE(mode)->purge) - STATE(mode)->purge(); } if (STATE(mode)->run) diff --git a/src/stats-mode.c b/src/stats-mode.c index 226a6b8..bd20253 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -123,11 +123,11 @@ static int resync_stats(enum nf_conntrack_msg_type type, static int purge_step(void *data1, void *data2) { - int ret; struct cache_object *obj = data2; - ret = nfct_query(STATE(dump), NFCT_Q_GET, obj->ct); - if (ret == -1 && errno == ENOENT) { + STATE(get_retval) = 0; + nl_get_conntrack(STATE(get), obj->ct); /* modifies STATE(get_retval) */ + if (!STATE(get_retval)) { debug_ct(obj->ct, "purge stats"); cache_del(STATE_STATS(cache), obj); cache_object_free(obj); diff --git a/src/sync-mode.c b/src/sync-mode.c index 84a4de0..8174681 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -499,8 +499,15 @@ static int local_handler_sync(int fd, int type, void *data) return ret; } +static void mcast_send_sync(struct cache_object *obj, int query) +{ + STATE_SYNC(sync)->enqueue(obj, query); +} + static void dump_sync(struct nf_conntrack *ct) { + struct cache_object *obj; + /* This is required by kernels < 2.6.20 */ nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES); nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS); @@ -508,23 +515,22 @@ static void dump_sync(struct nf_conntrack *ct) nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); nfct_attr_unset(ct, ATTR_USE); - if (cache_update_force(STATE_SYNC(internal), ct)) - debug_ct(ct, "resync"); -} - -static void mcast_send_sync(struct cache_object *obj, int query) -{ - STATE_SYNC(sync)->enqueue(obj, query); + obj = cache_update_force(STATE_SYNC(internal), ct); + if ((CONFIG(flags) & CTD_POLL)) { + if (obj != NULL && obj->status == C_OBJ_NEW) { + debug_ct(ct, "poll"); + mcast_send_sync(obj, NET_T_STATE_NEW); + } + } } static int purge_step(void *data1, void *data2) { - int ret; - struct nfct_handle *h = STATE(dump); struct cache_object *obj = data2; - ret = nfct_query(h, NFCT_Q_GET, obj->ct); - if (ret == -1 && errno == ENOENT) { + STATE(get_retval) = 0; + nl_get_conntrack(STATE(get), obj->ct); /* modifies STATE(get_reval) */ + if (!STATE(get_retval)) { debug_ct(obj->ct, "purge resync"); if (obj->status != C_OBJ_DEAD) { cache_object_set_status(obj, C_OBJ_DEAD); -- cgit v1.2.3 From fe42b4085b7dab5847bb29155ebc70b4d7880ebe Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 14 Feb 2009 21:54:50 +0100 Subject: stats-mode: fix polling based logging This patch fixes statistics logging based on polling. Signed-off-by: Pablo Neira Ayuso --- src/stats-mode.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/stats-mode.c') diff --git a/src/stats-mode.c b/src/stats-mode.c index bd20253..d561409 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -130,6 +130,7 @@ static int purge_step(void *data1, void *data2) if (!STATE(get_retval)) { debug_ct(obj->ct, "purge stats"); cache_del(STATE_STATS(cache), obj); + dlog_ct(STATE(stats_log), obj->ct, NFCT_O_PLAIN); cache_object_free(obj); } -- cgit v1.2.3 From c4ef74420bc09b82146190870186fb067ac163e9 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 15 Feb 2009 15:40:47 +0100 Subject: conntrackd: add `-f internal' and `-f external' options This patch allows flushing the internal and/or the external cache. The `-f' with no extra parameters still works to flush both the internal and the external cache. Signed-off-by: Pablo Neira Ayuso --- conntrackd.8 | 4 ++-- include/conntrackd.h | 2 ++ src/main.c | 23 +++++++++++++++++++++-- src/stats-mode.c | 1 + src/sync-mode.c | 10 ++++++++++ 5 files changed, 36 insertions(+), 4 deletions(-) (limited to 'src/stats-mode.c') diff --git a/conntrackd.8 b/conntrackd.8 index cd1e2bd..2002738 100644 --- a/conntrackd.8 +++ b/conntrackd.8 @@ -34,8 +34,8 @@ Dump the external cache, i.e. show foreign states Display output in XML format. This option is only valid in combination with "-i" and "-e" parameters. .TP -.BI "-f " -Flush the internal and the external cache +.BI "-f " "[|internal|external]" +Flush the internal and/or external cache .TP .BI "-F " Flush the kernel conntrack table (if you use a Linux kernel >= 2.6.29, this diff --git a/include/conntrackd.h b/include/conntrackd.h index bb038a9..9b3cdf2 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -31,6 +31,8 @@ #define STATS_RUNTIME 30 /* extended runtime stats */ #define STATS_MULTICAST 31 /* multicast network stats */ #define STATS_QUEUE 32 /* queue stats */ +#define FLUSH_INT_CACHE 33 /* flush internal cache */ +#define FLUSH_EXT_CACHE 34 /* flush external cache */ #define DEFAULT_CONFIGFILE "/etc/conntrackd/conntrackd.conf" #define DEFAULT_LOCKFILE "/var/lock/conntrackd.lock" diff --git a/src/main.c b/src/main.c index 8f75904..82f0d27 100644 --- a/src/main.c +++ b/src/main.c @@ -38,7 +38,7 @@ static const char usage_daemon_commands[] = static const char usage_client_commands[] = "Client mode commands:\n" " -c, commit external cache to conntrack table\n" - " -f, flush internal and external cache\n" + " -f [|internal|external], flush internal and external cache\n" " -F, flush kernel conntrack table\n" " -i, display content of the internal cache\n" " -e, display the content of the external cache\n" @@ -144,7 +144,26 @@ int main(int argc, char *argv[]) break; case 'f': set_operation_mode(&type, REQUEST, argv); - action = FLUSH_CACHE; + if (i+1 < argc && argv[i+1][0] != '-') { + if (strncmp(argv[i+1], "internal", + strlen(argv[i+1])) == 0) { + action = FLUSH_INT_CACHE; + i++; + } else if (strncmp(argv[i+1], "external", + strlen(argv[i+1])) == 0) { + action = FLUSH_EXT_CACHE; + i++; + } else { + fprintf(stderr, "ERROR: unknown " + "parameter `%s' for " + "option `-f'\n", + argv[i+1]); + exit(EXIT_FAILURE); + } + } else { + /* default to general flushing */ + action = FLUSH_CACHE; + } break; case 'R': set_operation_mode(&type, REQUEST, argv); diff --git a/src/stats-mode.c b/src/stats-mode.c index d561409..94fc45b 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -66,6 +66,7 @@ static int local_handler_stats(int fd, int type, void *data) cache_dump(STATE_STATS(cache), fd, NFCT_O_XML); break; case FLUSH_CACHE: + case FLUSH_INT_CACHE: dlog(LOG_NOTICE, "flushing caches"); cache_flush(STATE_STATS(cache)); break; diff --git a/src/sync-mode.c b/src/sync-mode.c index 74eb36e..866b313 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -466,6 +466,16 @@ static int local_handler_sync(int fd, int type, void *data) cache_flush(STATE_SYNC(internal)); cache_flush(STATE_SYNC(external)); break; + case FLUSH_INT_CACHE: + /* inmediate flush, remove pending flush scheduled if any */ + del_alarm(&STATE_SYNC(reset_cache_alarm)); + dlog(LOG_NOTICE, "flushing internal cache"); + cache_flush(STATE_SYNC(internal)); + break; + case FLUSH_EXT_CACHE: + dlog(LOG_NOTICE, "flushing external cache"); + cache_flush(STATE_SYNC(external)); + break; case KILL: killer(0); break; -- cgit v1.2.3 From e83250c0381bbff232011b67c87a5b9f3a0de09a Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 20 Feb 2009 20:42:22 +0100 Subject: src: remove obsolete debug() and debug_ct() calls This patch removes debug() and debug_ct(), I haven't use the debugging information that these functions provide in years. Signed-off-by: Pablo Neira Ayuso --- src/cache_timer.c | 2 -- src/mcast.c | 17 ----------------- src/netlink.c | 1 - src/network.c | 1 - src/stats-mode.c | 8 ++------ src/sync-alarm.c | 3 --- src/sync-ftfw.c | 1 - src/sync-mode.c | 26 ++++++-------------------- src/sync-notrack.c | 1 - 9 files changed, 8 insertions(+), 52 deletions(-) (limited to 'src/stats-mode.c') diff --git a/src/cache_timer.c b/src/cache_timer.c index a9e3e3d..5881236 100644 --- a/src/cache_timer.c +++ b/src/cache_timer.c @@ -19,7 +19,6 @@ #include "cache.h" #include "conntrackd.h" #include "alarm.h" -#include "debug.h" #include @@ -27,7 +26,6 @@ static void timeout(struct alarm_block *a, void *data) { struct cache_object *obj = data; - debug_ct(obj->ct, "expired timeout"); cache_del(obj->cache, obj); cache_object_free(obj); } diff --git a/src/mcast.c b/src/mcast.c index 70205d8..bc530d3 100644 --- a/src/mcast.c +++ b/src/mcast.c @@ -19,7 +19,6 @@ */ #include "mcast.h" -#include "debug.h" #include #include @@ -73,7 +72,6 @@ struct mcast_sock *mcast_server_create(struct mcast_conf *conf) } if ((m->fd = socket(conf->ipproto, SOCK_DGRAM, 0)) == -1) { - debug("mcast_sock_server_create:socket"); free(m); return NULL; } @@ -84,7 +82,6 @@ struct mcast_sock *mcast_server_create(struct mcast_conf *conf) strncpy(ifr.ifr_name, conf->iface, sizeof(ifr.ifr_name)); if (ioctl(m->fd, SIOCGIFMTU, &ifr) == -1) { - debug("ioctl"); close(m->fd); free(m); return NULL; @@ -94,7 +91,6 @@ struct mcast_sock *mcast_server_create(struct mcast_conf *conf) if (setsockopt(m->fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { - debug("mcast_sock_server_create:setsockopt1"); close(m->fd); free(m); return NULL; @@ -109,7 +105,6 @@ struct mcast_sock *mcast_server_create(struct mcast_conf *conf) sizeof(int)) == -1) { /* not supported in linux kernel < 2.6.14 */ if (errno != ENOPROTOOPT) { - debug("mcast_sock_server_create:setsockopt2"); close(m->fd); free(m); return NULL; @@ -119,7 +114,6 @@ struct mcast_sock *mcast_server_create(struct mcast_conf *conf) getsockopt(m->fd, SOL_SOCKET, SO_RCVBUF, &conf->rcvbuf, &socklen); if (bind(m->fd, (struct sockaddr *) &m->addr, m->sockaddr_len) == -1) { - debug("mcast_sock_server_create:bind"); close(m->fd); free(m); return NULL; @@ -129,7 +123,6 @@ struct mcast_sock *mcast_server_create(struct mcast_conf *conf) case AF_INET: if (setsockopt(m->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq.ipv4, sizeof(mreq.ipv4)) < 0) { - debug("mcast_sock_server_create:setsockopt2"); close(m->fd); free(m); return NULL; @@ -138,7 +131,6 @@ struct mcast_sock *mcast_server_create(struct mcast_conf *conf) case AF_INET6: if (setsockopt(m->fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq.ipv6, sizeof(mreq.ipv6)) < 0) { - debug("mcast_sock_server_create:setsockopt2"); close(m->fd); free(m); return NULL; @@ -207,7 +199,6 @@ __mcast_client_create_ipv4(struct mcast_sock *m, struct mcast_conf *conf) if (setsockopt(m->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &no, sizeof(int)) < 0) { - debug("mcast_sock_client_create:setsockopt2"); close(m->fd); return -1; } @@ -215,7 +206,6 @@ __mcast_client_create_ipv4(struct mcast_sock *m, struct mcast_conf *conf) if (setsockopt(m->fd, IPPROTO_IP, IP_MULTICAST_IF, &conf->ifa.interface_addr, sizeof(struct in_addr)) == -1) { - debug("mcast_sock_client_create:setsockopt3"); close(m->fd); return -1; } @@ -237,7 +227,6 @@ __mcast_client_create_ipv6(struct mcast_sock *m, struct mcast_conf *conf) if (setsockopt(m->fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &no, sizeof(int)) < 0) { - debug("mcast_sock_client_create:setsockopt2"); close(m->fd); return -1; } @@ -245,7 +234,6 @@ __mcast_client_create_ipv6(struct mcast_sock *m, struct mcast_conf *conf) if (setsockopt(m->fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &conf->ifa.interface_index6, sizeof(unsigned int)) == -1) { - debug("mcast_sock_client_create:setsockopt3"); close(m->fd); return -1; } @@ -267,14 +255,12 @@ struct mcast_sock *mcast_client_create(struct mcast_conf *conf) m->interface_idx = conf->interface_idx; if ((m->fd = socket(conf->ipproto, SOCK_DGRAM, 0)) == -1) { - debug("mcast_sock_client_create:socket"); free(m); return NULL; } if (setsockopt(m->fd, SOL_SOCKET, SO_NO_CHECK, &conf->checksum, sizeof(int)) == -1) { - debug("mcast_sock_client_create:setsockopt1"); close(m->fd); free(m); return NULL; @@ -289,7 +275,6 @@ struct mcast_sock *mcast_client_create(struct mcast_conf *conf) sizeof(int)) == -1) { /* not supported in linux kernel < 2.6.14 */ if (errno != ENOPROTOOPT) { - debug("mcast_sock_server_create:setsockopt2"); close(m->fd); free(m); return NULL; @@ -376,7 +361,6 @@ ssize_t mcast_send(struct mcast_sock *m, void *data, int size) (struct sockaddr *) &m->addr, m->sockaddr_len); if (ret == -1) { - debug("mcast_sock_send"); m->stats.error++; return ret; } @@ -399,7 +383,6 @@ ssize_t mcast_recv(struct mcast_sock *m, void *data, int size) (struct sockaddr *)&m->addr, &sin_size); if (ret == -1) { - debug("mcast_sock_recv"); m->stats.error++; return ret; } diff --git a/src/netlink.c b/src/netlink.c index 78cc466..ef729c1 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -20,7 +20,6 @@ #include "conntrackd.h" #include "filter.h" #include "log.h" -#include "debug.h" #include #include diff --git a/src/network.c b/src/network.c index f71aef0..690b28e 100644 --- a/src/network.c +++ b/src/network.c @@ -19,7 +19,6 @@ #include "conntrackd.h" #include "network.h" #include "log.h" -#include "debug.h" #include #include diff --git a/src/stats-mode.c b/src/stats-mode.c index 94fc45b..af1c136 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -18,7 +18,6 @@ #include "netlink.h" #include "traffic_stats.h" -#include "debug.h" #include "cache.h" #include "log.h" #include "conntrackd.h" @@ -97,8 +96,7 @@ static void dump_stats(struct nf_conntrack *ct) nfct_attr_unset(ct, ATTR_TIMEOUT); nfct_attr_unset(ct, ATTR_USE); - if (cache_update_force(STATE_STATS(cache), ct)) - debug_ct(ct, "resync entry"); + cache_update_force(STATE_STATS(cache), ct); } static int resync_stats(enum nf_conntrack_msg_type type, @@ -116,8 +114,7 @@ static int resync_stats(enum nf_conntrack_msg_type type, nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); nfct_attr_unset(ct, ATTR_USE); - if (!cache_update_force(STATE_STATS(cache), ct)) - debug_ct(ct, "stats resync"); + cache_update_force(STATE_STATS(cache), ct); return NFCT_CB_CONTINUE; } @@ -129,7 +126,6 @@ static int purge_step(void *data1, void *data2) STATE(get_retval) = 0; nl_get_conntrack(STATE(get), obj->ct); /* modifies STATE(get_retval) */ if (!STATE(get_retval)) { - debug_ct(obj->ct, "purge stats"); cache_del(STATE_STATS(cache), obj); dlog_ct(STATE(stats_log), obj->ct, NFCT_O_PLAIN); cache_object_free(obj); diff --git a/src/sync-alarm.c b/src/sync-alarm.c index 1815447..a59ae11 100644 --- a/src/sync-alarm.c +++ b/src/sync-alarm.c @@ -22,7 +22,6 @@ #include "alarm.h" #include "cache.h" #include "queue.h" -#include "debug.h" #include #include @@ -38,8 +37,6 @@ static void refresher(struct alarm_block *a, void *data) { struct cache_object *obj = data; - debug_ct(obj->ct, "persistence update"); - add_alarm(a, random() % CONFIG(refresh) + 1, ((random() % 5 + 1) * 200000) - 1); diff --git a/src/sync-ftfw.c b/src/sync-ftfw.c index 91ce25d..d608e5b 100644 --- a/src/sync-ftfw.c +++ b/src/sync-ftfw.c @@ -19,7 +19,6 @@ #include "conntrackd.h" #include "sync.h" #include "queue.h" -#include "debug.h" #include "network.h" #include "alarm.h" #include "log.h" diff --git a/src/sync-mode.c b/src/sync-mode.c index 02a5a46..d1a941b 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -25,7 +25,6 @@ #include "network.h" #include "fds.h" #include "event.h" -#include "debug.h" #include "queue.h" #include @@ -166,10 +165,6 @@ static void mcast_handler(struct mcast_sock *m, int if_idx) } } - debug("recv sq: %u fl:%u len:%u (rem:%d)\n", - ntohl(net->seq), net->flags, - ntohs(net->len), remain); - HDR_NETWORK2HOST(net); do_mcast_handler_step(if_idx, net, remain); @@ -531,8 +526,7 @@ static void dump_sync(struct nf_conntrack *ct) nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); nfct_attr_unset(ct, ATTR_USE); - if (cache_update_force(STATE_SYNC(internal), ct)) - debug_ct(ct, "dump"); + cache_update_force(STATE_SYNC(internal), ct); } static int purge_step(void *data1, void *data2) @@ -542,7 +536,6 @@ static int purge_step(void *data1, void *data2) STATE(get_retval) = 0; nl_get_conntrack(STATE(get), obj->ct); /* modifies STATE(get_reval) */ if (!STATE(get_retval)) { - debug_ct(obj->ct, "purge resync"); if (obj->status != C_OBJ_DEAD) { cache_object_set_status(obj, C_OBJ_DEAD); mcast_send_sync(obj, NET_T_STATE_DEL); @@ -582,11 +575,9 @@ static int resync_sync(enum nf_conntrack_msg_type type, switch (obj->status) { case C_OBJ_NEW: - debug_ct(ct, "resync"); mcast_send_sync(obj, NET_T_STATE_NEW); break; case C_OBJ_ALIVE: - debug_ct(ct, "resync"); mcast_send_sync(obj, NET_T_STATE_UPD); break; } @@ -615,11 +606,9 @@ retry: return; } mcast_send_sync(obj, NET_T_STATE_NEW); - debug_ct(obj->ct, "internal new"); } else { cache_del(STATE_SYNC(internal), obj); cache_object_free(obj); - debug_ct(ct, "can't add"); goto retry; } } @@ -628,11 +617,10 @@ static void event_update_sync(struct nf_conntrack *ct) { struct cache_object *obj; - if ((obj = cache_update_force(STATE_SYNC(internal), ct)) == NULL) { - debug_ct(ct, "can't update"); + obj = cache_update_force(STATE_SYNC(internal), ct); + if (obj == NULL) return; - } - debug_ct(obj->ct, "internal update"); + mcast_send_sync(obj, NET_T_STATE_UPD); } @@ -642,16 +630,14 @@ static int event_destroy_sync(struct nf_conntrack *ct) int id; obj = cache_find(STATE_SYNC(internal), ct, &id); - if (obj == NULL) { - debug_ct(ct, "can't destroy"); + if (obj == NULL) return 0; - } + if (obj->status != C_OBJ_DEAD) { cache_object_set_status(obj, C_OBJ_DEAD); mcast_send_sync(obj, NET_T_STATE_DEL); cache_object_put(obj); } - debug_ct(ct, "internal destroy"); return 1; } diff --git a/src/sync-notrack.c b/src/sync-notrack.c index 7bd4351..57c3368 100644 --- a/src/sync-notrack.c +++ b/src/sync-notrack.c @@ -19,7 +19,6 @@ #include "conntrackd.h" #include "sync.h" #include "queue.h" -#include "debug.h" #include "network.h" #include "log.h" #include "cache.h" -- cgit v1.2.3 From ef047d03613bf9fa105db009773136817e2ec4c6 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 23 May 2009 12:54:51 +0200 Subject: conntrackd: detect where the events comes from Since Linux kernel 2.6.29, ctnetlink reports the changes that have been done using ctnetlink. With this patch, conntrackd can recognize who is the origin of the event messages. For example, this is interesting to avoid a messy implicit bulk send during the commit of entries. Signed-off-by: Pablo Neira Ayuso --- include/Makefile.am | 2 +- include/cache.h | 4 ++- include/conntrackd.h | 6 ++--- include/origin.h | 14 +++++++++++ src/Makefile.am | 2 +- src/cache_iterators.c | 15 ++++------- src/origin.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/run.c | 18 ++++++++----- src/stats-mode.c | 9 ++++--- src/sync-mode.c | 51 ++++++++++++++++++++++++++++++------- 10 files changed, 157 insertions(+), 34 deletions(-) create mode 100644 include/origin.h create mode 100644 src/origin.c (limited to 'src/stats-mode.c') diff --git a/include/Makefile.am b/include/Makefile.am index 0ea056c..b72fb36 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -4,5 +4,5 @@ noinst_HEADERS = alarm.h jhash.h cache.h linux_list.h linux_rbtree.h \ debug.h log.h hash.h mcast.h conntrack.h \ network.h filter.h queue.h vector.h cidr.h \ traffic_stats.h netlink.h fds.h event.h bitops.h channel.h \ - process.h + process.h origin.h diff --git a/include/cache.h b/include/cache.h index 371170d..b6facdc 100644 --- a/include/cache.h +++ b/include/cache.h @@ -121,8 +121,10 @@ void *cache_get_extra(struct cache *, void *); void cache_iterate(struct cache *c, void *data, int (*iterate)(void *data1, void *data2)); /* iterators */ +struct nfct_handle; + void cache_dump(struct cache *c, int fd, int type); -void cache_commit(struct cache *c); +void cache_commit(struct cache *c, struct nfct_handle *h); void cache_flush(struct cache *c); void cache_bulk(struct cache *c); diff --git a/include/conntrackd.h b/include/conntrackd.h index 013ec4f..81cfd51 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -218,9 +218,9 @@ struct ct_mode { struct nf_conntrack *ct, void *data); int (*purge)(void); - void (*event_new)(struct nf_conntrack *ct); - void (*event_upd)(struct nf_conntrack *ct); - int (*event_dst)(struct nf_conntrack *ct); + void (*event_new)(struct nf_conntrack *ct, int origin); + void (*event_upd)(struct nf_conntrack *ct, int origin); + int (*event_dst)(struct nf_conntrack *ct, int origin); }; /* conntrackd modes */ diff --git a/include/origin.h b/include/origin.h new file mode 100644 index 0000000..b2d1823 --- /dev/null +++ b/include/origin.h @@ -0,0 +1,14 @@ +#ifndef _ORIGIN_H_ +#define _ORIGIN_H_ + +enum { + CTD_ORIGIN_NOT_ME = 0, /* this event comes from the kernel or + any process, but not conntrackd */ + CTD_ORIGIN_COMMIT, /* event comes from committer */ +}; + +int origin_register(struct nfct_handle *h, int origin_type); +int origin_find(const struct nlmsghdr *nlh); +int origin_unregister(struct nfct_handle *h); + +#endif diff --git a/src/Makefile.am b/src/Makefile.am index decc545..c338fee 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,7 +12,7 @@ conntrack_LDFLAGS = $(all_libraries) @LIBNETFILTER_CONNTRACK_LIBS@ conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c rbtree.c \ local.c log.c mcast.c udp.c netlink.c vector.c \ - filter.c fds.c event.c process.c \ + filter.c fds.c event.c process.c origin.c \ cache.c cache_iterators.c \ cache_timer.c cache_wt.c \ sync-mode.c sync-alarm.c sync-ftfw.c sync-notrack.c \ diff --git a/src/cache_iterators.c b/src/cache_iterators.c index dfccc68..542ab91 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -175,20 +175,16 @@ static int do_commit_master(void *data, struct hashtable_node *n) } /* no need to clone, called from child process */ -void cache_commit(struct cache *c) +void cache_commit(struct cache *c, struct nfct_handle *h) { unsigned int commit_ok = c->stats.commit_ok; unsigned int commit_fail = c->stats.commit_fail; - struct __commit_container tmp; + struct __commit_container tmp = { + .h = h, + .c = c, + }; struct timeval commit_start, commit_stop, res; - tmp.h = nfct_open(CONNTRACK, 0); - if (tmp.h == NULL) { - dlog(LOG_ERR, "can't create handler to commit entries"); - return; - } - tmp.c = c; - gettimeofday(&commit_start, NULL); /* commit master conntrack first, then related ones */ hashtable_iterate(c->h, &tmp, do_commit_master); @@ -206,7 +202,6 @@ void cache_commit(struct cache *c) if (commit_fail) dlog(LOG_NOTICE, "%u entries can't be " "committed", commit_fail); - nfct_close(tmp.h); dlog(LOG_NOTICE, "commit has taken %lu.%06lu seconds", res.tv_sec, res.tv_usec); diff --git a/src/origin.c b/src/origin.c new file mode 100644 index 0000000..3c65f3d --- /dev/null +++ b/src/origin.c @@ -0,0 +1,70 @@ +/* + * (C) 2009 by Pablo Neira Ayuso + * + * 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 "conntrackd.h" +#include "origin.h" + +static LIST_HEAD(origin_list); + +struct origin { + struct list_head head; + unsigned int nl_portid; + int type; +}; + +/* register a Netlink socket as origin of possible events */ +int origin_register(struct nfct_handle *h, int origin_type) +{ + struct origin *nlp; + + nlp = calloc(sizeof(struct origin), 1); + if (nlp == NULL) + return -1; + + nlp->nl_portid = nfnl_portid(nfct_nfnlh(h)); + nlp->type = origin_type; + + list_add(&nlp->head, &origin_list); + return 0; +} + +/* look up for the origin of this Netlink event */ +int origin_find(const struct nlmsghdr *nlh) +{ + struct origin *this; + + list_for_each_entry(this, &origin_list, head) { + if (this->nl_portid == nlh->nlmsg_pid) { + return this->type; + } + } + return CTD_ORIGIN_NOT_ME; +} + +int origin_unregister(struct nfct_handle *h) +{ + struct origin *this, *tmp; + + list_for_each_entry_safe(this, tmp, &origin_list, head) { + if (this->nl_portid == nfnl_portid(nfct_nfnlh(h))) { + list_del(&this->head); + free(this); + return 1; + } + } + return 0; +} diff --git a/src/run.c b/src/run.c index 09e2ae9..e54764c 100644 --- a/src/run.c +++ b/src/run.c @@ -26,6 +26,7 @@ #include "fds.h" #include "traffic_stats.h" #include "process.h" +#include "origin.h" #include #include @@ -228,10 +229,13 @@ static void do_polling_alarm(struct alarm_block *a, void *data) add_alarm(&STATE(polling_alarm), CONFIG(poll_kernel_secs), 0); } -static int event_handler(enum nf_conntrack_msg_type type, +static int event_handler(const struct nlmsghdr *nlh, + enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data) { + int origin_type; + STATE(stats).nl_events_received++; /* skip user-space filtering if already do it in the kernel */ @@ -240,15 +244,17 @@ static int event_handler(enum nf_conntrack_msg_type type, goto out; } + origin_type = origin_find(nlh); + switch(type) { case NFCT_T_NEW: - STATE(mode)->event_new(ct); + STATE(mode)->event_new(ct, origin_type); break; case NFCT_T_UPDATE: - STATE(mode)->event_upd(ct); + STATE(mode)->event_upd(ct, origin_type); break; case NFCT_T_DESTROY: - if (STATE(mode)->event_dst(ct)) + if (STATE(mode)->event_dst(ct, origin_type)) update_traffic_stats(ct); break; default: @@ -334,8 +340,8 @@ init(void) dlog(LOG_ERR, "no ctnetlink kernel support?"); return -1; } - nfct_callback_register(STATE(event), NFCT_T_ALL, - event_handler, NULL); + nfct_callback_register2(STATE(event), NFCT_T_ALL, + event_handler, NULL); register_fd(nfct_fd(STATE(event)), STATE(fds)); } diff --git a/src/stats-mode.c b/src/stats-mode.c index af1c136..b84c7a1 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -141,7 +141,8 @@ static int purge_stats(void) return 0; } -static void event_new_stats(struct nf_conntrack *ct) +static void +event_new_stats(struct nf_conntrack *ct, int origin) { int id; struct cache_object *obj; @@ -162,13 +163,15 @@ static void event_new_stats(struct nf_conntrack *ct) return; } -static void event_update_stats(struct nf_conntrack *ct) +static void +event_update_stats(struct nf_conntrack *ct, int origin) { nfct_attr_unset(ct, ATTR_TIMEOUT); cache_update_force(STATE_STATS(cache), ct); } -static int event_destroy_stats(struct nf_conntrack *ct) +static int +event_destroy_stats(struct nf_conntrack *ct, int origin) { int id; struct cache_object *obj; diff --git a/src/sync-mode.c b/src/sync-mode.c index 0d35923..91e028e 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -27,6 +27,7 @@ #include "event.h" #include "queue.h" #include "process.h" +#include "origin.h" #include #include @@ -385,6 +386,14 @@ static void dump_stats_sync_extended(int fd) send(fd, buf, size, 0); } +/* this is called once the committer process has finished */ +static void commit_done_cb(void *data) +{ + struct nfct_handle *h = data; + origin_unregister(h); + nfct_close(h); +} + /* handler for requests coming via UNIX socket */ static int local_handler_sync(int fd, int type, void *data) { @@ -419,16 +428,29 @@ static int local_handler_sync(int fd, int type, void *data) exit(EXIT_SUCCESS); } break; - case COMMIT: + case COMMIT: { + struct nfct_handle *h; + /* delete the reset alarm if any before committing */ del_alarm(&STATE_SYNC(reset_cache_alarm)); - ret = fork_process_new(NULL, NULL); + + /* disposable handler for commit operations */ + h = nfct_open(CONNTRACK, 0); + if (h == NULL) { + dlog(LOG_ERR, "can't create handler to commit"); + break; + } + origin_register(h, CTD_ORIGIN_COMMIT); + + /* fork new process and insert it the process list */ + ret = fork_process_new(commit_done_cb, h); if (ret == 0) { dlog(LOG_NOTICE, "committing external cache"); - cache_commit(STATE_SYNC(external)); + cache_commit(STATE_SYNC(external), h); exit(EXIT_SUCCESS); } break; + } case RESET_TIMERS: if (!alarm_pending(&STATE_SYNC(reset_cache_alarm))) { dlog(LOG_NOTICE, "flushing conntrack table in %d secs", @@ -557,7 +579,8 @@ static int resync_sync(enum nf_conntrack_msg_type type, return NFCT_CB_CONTINUE; } -static void event_new_sync(struct nf_conntrack *ct) +static void +event_new_sync(struct nf_conntrack *ct, int origin) { struct cache_object *obj; int id; @@ -578,7 +601,11 @@ retry: cache_object_free(obj); return; } - sync_send(obj, NET_T_STATE_NEW); + /* only synchronize events that have been triggered by other + * processes or the kernel, but don't propagate events that + * have been triggered by conntrackd itself, eg. commits. */ + if (origin == CTD_ORIGIN_NOT_ME) + sync_send(obj, NET_T_STATE_NEW); } else { cache_del(STATE_SYNC(internal), obj); cache_object_free(obj); @@ -586,7 +613,8 @@ retry: } } -static void event_update_sync(struct nf_conntrack *ct) +static void +event_update_sync(struct nf_conntrack *ct, int origin) { struct cache_object *obj; @@ -594,21 +622,26 @@ static void event_update_sync(struct nf_conntrack *ct) if (obj == NULL) return; - sync_send(obj, NET_T_STATE_UPD); + if (origin == CTD_ORIGIN_NOT_ME) + sync_send(obj, NET_T_STATE_UPD); } -static int event_destroy_sync(struct nf_conntrack *ct) +static int +event_destroy_sync(struct nf_conntrack *ct, int origin) { struct cache_object *obj; int id; + /* we don't synchronize events for objects that are not in the cache */ obj = cache_find(STATE_SYNC(internal), ct, &id); if (obj == NULL) return 0; if (obj->status != C_OBJ_DEAD) { cache_object_set_status(obj, C_OBJ_DEAD); - sync_send(obj, NET_T_STATE_DEL); + if (origin == CTD_ORIGIN_NOT_ME) { + sync_send(obj, NET_T_STATE_DEL); + } cache_object_put(obj); } return 1; -- cgit v1.2.3 From 9406f29b89f6727c3db5485d109466701393b4d4 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 17 Jul 2009 13:33:36 +0200 Subject: local: add LOCAL_RET_* return values for UNIX sockets callbacks This patch adds the LOCAL_RET_* return values. The return value LOCAL_RET_STOLEN which allows to leave a client socket open while waiting for an operation to finish. Signed-off-by: Pablo Neira Ayuso --- include/conntrackd.h | 1 - include/local.h | 7 ++++++- src/local.c | 7 ++++--- src/run.c | 22 +++++++++++++--------- src/stats-mode.c | 2 +- src/sync-ftfw.c | 5 +---- src/sync-mode.c | 2 +- 7 files changed, 26 insertions(+), 20 deletions(-) (limited to 'src/stats-mode.c') diff --git a/include/conntrackd.h b/include/conntrackd.h index 040c252..417bac6 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -234,7 +234,6 @@ extern struct ct_mode stats_mode; /* These live in run.c */ void killer(int foo); -void local_handler(int fd, void *data); int init(void); void run(void); diff --git a/include/local.h b/include/local.h index 6940755..f9121b1 100644 --- a/include/local.h +++ b/include/local.h @@ -16,11 +16,16 @@ struct local_server { char path[UNIX_PATH_MAX]; }; +/* callback return values */ +#define LOCAL_RET_ERROR -1 +#define LOCAL_RET_OK 0 +#define LOCAL_RET_STOLEN 1 + /* local server */ int local_server_create(struct local_server *server, struct local_conf *conf); void local_server_destroy(struct local_server *server); int do_local_server_step(struct local_server *server, void *data, - void (*process)(int fd, void *data)); + int (*process)(int fd, void *data)); /* local client */ int local_client_create(struct local_conf *conf); diff --git a/src/local.c b/src/local.c index 4739e56..feff608 100644 --- a/src/local.c +++ b/src/local.c @@ -72,7 +72,7 @@ void local_server_destroy(struct local_server *server) } int do_local_server_step(struct local_server *server, void *data, - void (*process)(int fd, void *data)) + int (*process)(int fd, void *data)) { int rfd; struct sockaddr_un local; @@ -82,8 +82,9 @@ int do_local_server_step(struct local_server *server, void *data, if (rfd == -1) return -1; - process(rfd, data); - close(rfd); + /* This descriptor will be closed later, we ignore OK and errors */ + if (process(rfd, data) != LOCAL_RET_STOLEN) + close(rfd); return 0; } diff --git a/src/run.c b/src/run.c index 95d51a2..87b6fb2 100644 --- a/src/run.c +++ b/src/run.c @@ -182,18 +182,18 @@ static void dump_stats_runtime(int fd) send(fd, buf, size, 0); } -void local_handler(int fd, void *data) +static int local_handler(int fd, void *data) { - int ret; + int ret = LOCAL_RET_OK; int type; ret = read(fd, &type, sizeof(type)); if (ret == -1) { STATE(stats).local_read_failed++; - return; + return LOCAL_RET_OK; } if (ret == 0) - return; + return LOCAL_RET_OK; switch(type) { case FLUSH_MASTER: @@ -207,22 +207,26 @@ void local_handler(int fd, void *data) nl_flush_conntrack_table(STATE(flush)); exit(EXIT_SUCCESS); } - return; + break; case RESYNC_MASTER: STATE(stats).nl_kernel_table_resync++; dlog(LOG_NOTICE, "resync with master table"); nl_dump_conntrack_table(STATE(dump)); - return; + break; case STATS_RUNTIME: dump_stats_runtime(fd); - return; + break; case STATS_PROCESS: fork_process_dump(fd); - return; + break; } - if (!STATE(mode)->local(fd, type, data)) + ret = STATE(mode)->local(fd, type, data); + if (ret == LOCAL_RET_ERROR) { STATE(stats).local_unknown_request++; + return LOCAL_RET_ERROR; + } + return ret; } static void do_overrun_resync_alarm(struct alarm_block *a, void *data) diff --git a/src/stats-mode.c b/src/stats-mode.c index b84c7a1..5cfb638 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -55,7 +55,7 @@ static void kill_stats(void) /* handler for requests coming via UNIX socket */ static int local_handler_stats(int fd, int type, void *data) { - int ret = 1; + int ret = LOCAL_RET_OK; switch(type) { case DUMP_INTERNAL: diff --git a/src/sync-ftfw.c b/src/sync-ftfw.c index bf9f4f7..0d31e17 100644 --- a/src/sync-ftfw.c +++ b/src/sync-ftfw.c @@ -215,7 +215,7 @@ static void ftfw_local_queue(int fd) static int ftfw_local(int fd, int type, void *data) { - int ret = 1; + int ret = LOCAL_RET_OK; switch(type) { case REQUEST_DUMP: @@ -229,9 +229,6 @@ static int ftfw_local(int fd, int type, void *data) case STATS_RSQUEUE: ftfw_local_queue(fd); break; - default: - ret = 0; - break; } return ret; diff --git a/src/sync-mode.c b/src/sync-mode.c index 4d6956e..b0e2b02 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -403,7 +403,7 @@ static void dump_stats_sync_extended(int fd) /* handler for requests coming via UNIX socket */ static int local_handler_sync(int fd, int type, void *data) { - int ret = 1; + int ret = LOCAL_RET_OK; switch(type) { case DUMP_INTERNAL: -- cgit v1.2.3 From 8ad5df6121c46753a6d12fafa5ab9da309ddb721 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 21 Oct 2009 01:43:07 +0200 Subject: conntrackd: add `DisableInternalCache' clause This patch adds the clause `DisableInternalCache' that allows you to bypass the internal cache. This clause can only be used with the notrack synchronization mode. Signed-off-by: Pablo Neira Ayuso --- include/Makefile.am | 2 +- include/conntrackd.h | 12 +-- include/internal.h | 39 +++++++++ src/Makefile.am | 1 + src/internal_bypass.c | 165 +++++++++++++++++++++++++++++++++++++ src/internal_cache.c | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/read_config_lex.l | 1 + src/read_config_yy.y | 13 ++- src/run.c | 62 ++++++++------ src/stats-mode.c | 24 +++--- src/sync-alarm.c | 5 +- src/sync-ftfw.c | 19 +++-- src/sync-mode.c | 190 ++++--------------------------------------- src/sync-notrack.c | 53 ++++++++++-- 14 files changed, 572 insertions(+), 234 deletions(-) create mode 100644 include/internal.h create mode 100644 src/internal_bypass.c create mode 100644 src/internal_cache.c (limited to 'src/stats-mode.c') diff --git a/include/Makefile.am b/include/Makefile.am index a89490e..cbbca6b 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -4,5 +4,5 @@ noinst_HEADERS = alarm.h jhash.h cache.h linux_list.h linux_rbtree.h \ debug.h log.h hash.h mcast.h conntrack.h \ network.h filter.h queue.h vector.h cidr.h \ traffic_stats.h netlink.h fds.h event.h bitops.h channel.h \ - process.h origin.h external.h date.h + process.h origin.h internal.h external.h date.h diff --git a/include/conntrackd.h b/include/conntrackd.h index 7737532..c7f33f0 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -6,6 +6,7 @@ #include "alarm.h" #include "filter.h" #include "channel.h" +#include "internal.h" #include #include @@ -99,6 +100,7 @@ struct ct_conf { int error_queue_length; } channelc; struct { + int internal_cache_disable; int external_cache_disable; } sync; struct { @@ -177,7 +179,6 @@ struct ct_general_state { #define STATE_SYNC(x) state.sync->x struct ct_sync_state { - struct cache *internal; /* internal events cache (netlink) */ struct external_handler *external; struct multichannel *channel; @@ -239,18 +240,11 @@ extern union ct_state state; extern struct ct_general_state st; struct ct_mode { + struct internal_handler *internal; int (*init)(void); void (*run)(fd_set *readfds); int (*local)(int fd, int type, void *data); void (*kill)(void); - void (*dump)(struct nf_conntrack *ct); - int (*resync)(enum nf_conntrack_msg_type type, - struct nf_conntrack *ct, - void *data); - int (*purge)(void); - void (*event_new)(struct nf_conntrack *ct, int origin); - void (*event_upd)(struct nf_conntrack *ct, int origin); - int (*event_dst)(struct nf_conntrack *ct, int origin); }; /* conntrackd modes */ diff --git a/include/internal.h b/include/internal.h new file mode 100644 index 0000000..1f11340 --- /dev/null +++ b/include/internal.h @@ -0,0 +1,39 @@ +#ifndef _INTERNAL_H_ +#define _INTERNAL_H_ + +#include + +struct nf_conntrack; + +enum { + INTERNAL_F_POPULATE = (1 << 0), + INTERNAL_F_RESYNC = (1 << 1), + INTERNAL_F_MAX = (1 << 2) +}; + +struct internal_handler { + void *data; + unsigned int flags; + + int (*init)(void); + void (*close)(void); + + void (*new)(struct nf_conntrack *ct, int origin_type); + void (*update)(struct nf_conntrack *ct, int origin_type); + int (*destroy)(struct nf_conntrack *ct, int origin_type); + + void (*dump)(int fd, int type); + void (*populate)(struct nf_conntrack *ct); + void (*purge)(void); + int (*resync)(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, void *data); + void (*flush)(void); + + void (*stats)(int fd); + void (*stats_ext)(int fd); +}; + +extern struct internal_handler internal_cache; +extern struct internal_handler internal_bypass; + +#endif diff --git a/src/Makefile.am b/src/Makefile.am index 8b36642..76f0e73 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,6 +22,7 @@ conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c rbtree.c \ channel.c multichannel.c channel_mcast.c channel_udp.c \ tcp.c channel_tcp.c \ external_cache.c external_inject.c \ + internal_cache.c internal_bypass.c \ read_config_yy.y read_config_lex.l # yacc and lex generate dirty code diff --git a/src/internal_bypass.c b/src/internal_bypass.c new file mode 100644 index 0000000..4caaf4f --- /dev/null +++ b/src/internal_bypass.c @@ -0,0 +1,165 @@ +/* + * (C) 2009 by Pablo Neira Ayuso + * + * 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 feature has been sponsored by 6WIND . + */ +#include "conntrackd.h" +#include "sync.h" +#include "log.h" +#include "cache.h" +#include "netlink.h" +#include "network.h" +#include "origin.h" + +static int _init(void) +{ + return 0; +} + +static void _close(void) +{ +} + +static int dump_cb(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, void *data) +{ + char buf[1024]; + int size, *fd = data; + + size = nfct_snprintf(buf, 1024, ct, NFCT_T_UNKNOWN, NFCT_O_DEFAULT, 0); + if (size < 1024) { + buf[size] = '\n'; + size++; + } + send(*fd, buf, size, 0); + + return NFCT_CB_CONTINUE; +} + +static void dump(int fd, int type) +{ + struct nfct_handle *h; + u_int32_t family = AF_UNSPEC; + int ret; + + h = nfct_open(CONNTRACK, 0); + if (h == NULL) { + dlog(LOG_ERR, "can't allocate memory for the internal cache"); + return; + } + nfct_callback_register(h, NFCT_T_ALL, dump_cb, &fd); + ret = nfct_query(h, NFCT_Q_DUMP, &family); + if (ret == -1) { + dlog(LOG_ERR, "can't dump kernel table"); + } + nfct_close(h); +} + +static void flush(void) +{ + nl_flush_conntrack_table(STATE(flush)); +} + +struct { + uint32_t new; + uint32_t upd; + uint32_t del; +} internal_bypass_stats; + +static void stats(int fd) +{ + char buf[512]; + int size; + + size = sprintf(buf, "internal bypass:\n" + "connections new:\t\t%12u\n" + "connections updated:\t\t%12u\n" + "connections destroyed:\t\t%12u\n\n", + internal_bypass_stats.new, + internal_bypass_stats.upd, + internal_bypass_stats.del); + + send(fd, buf, size, 0); +} + +/* unused, INTERNAL_F_POPULATE is unset. No cache, nothing to populate. */ +static void populate(struct nf_conntrack *ct) +{ +} + +/* unused, INTERNAL_F_RESYNC is unset. */ +static void purge(void) +{ +} + +/* unused, INTERNAL_F_RESYNC is unset. Nothing to resync, we have no cache. */ +static int resync(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data) +{ + return NFCT_CB_CONTINUE; +} + +static void +event_new_sync(struct nf_conntrack *ct, int origin) +{ + struct nethdr *net; + + /* this event has been triggered by me, skip */ + if (origin != CTD_ORIGIN_NOT_ME) + return; + + net = BUILD_NETMSG(ct, NET_T_STATE_NEW); + multichannel_send(STATE_SYNC(channel), net); + internal_bypass_stats.new++; +} + +static void +event_update_sync(struct nf_conntrack *ct, int origin) +{ + struct nethdr *net; + + /* this event has been triggered by me, skip */ + if (origin != CTD_ORIGIN_NOT_ME) + return; + + net = BUILD_NETMSG(ct, NET_T_STATE_UPD); + multichannel_send(STATE_SYNC(channel), net); + internal_bypass_stats.upd++; +} + +static int +event_destroy_sync(struct nf_conntrack *ct, int origin) +{ + struct nethdr *net; + + /* this event has been triggered by me, skip */ + if (origin != CTD_ORIGIN_NOT_ME) + return 1; + + net = BUILD_NETMSG(ct, NET_T_STATE_DEL); + multichannel_send(STATE_SYNC(channel), net); + internal_bypass_stats.del++; + + return 1; +} + +struct internal_handler internal_bypass = { + .init = _init, + .close = _close, + .dump = dump, + .flush = flush, + .stats = stats, + .stats_ext = stats, + .populate = populate, + .purge = purge, + .resync = resync, + .new = event_new_sync, + .update = event_update_sync, + .destroy = event_destroy_sync, +}; diff --git a/src/internal_cache.c b/src/internal_cache.c new file mode 100644 index 0000000..daadfd6 --- /dev/null +++ b/src/internal_cache.c @@ -0,0 +1,220 @@ +/* + * (C) 2009 by Pablo Neira Ayuso + * + * 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. + */ +#include "conntrackd.h" +#include "sync.h" +#include "log.h" +#include "cache.h" +#include "netlink.h" +#include "network.h" +#include "origin.h" + +static inline void sync_send(struct cache_object *obj, int query) +{ + STATE_SYNC(sync)->enqueue(obj, query); +} + +static int _init(void) +{ + STATE(mode)->internal->data = + cache_create("internal", + STATE_SYNC(sync)->internal_cache_flags, + STATE_SYNC(sync)->internal_cache_extra); + + if (!STATE(mode)->internal->data) { + dlog(LOG_ERR, "can't allocate memory for the internal cache"); + return -1; + } + return 0; +} + +static void _close(void) +{ + cache_destroy(STATE(mode)->internal->data); +} + +static void dump(int fd, int type) +{ + cache_dump(STATE(mode)->internal->data, fd, NFCT_O_PLAIN); +} + +static void flush(void) +{ + cache_flush(STATE(mode)->internal->data); +} + +static void stats(int fd) +{ + cache_stats(STATE(mode)->internal->data, fd); +} + +static void stats_ext(int fd) +{ + cache_stats_extended(STATE(mode)->internal->data, fd); +} + +static void populate(struct nf_conntrack *ct) +{ + /* This is required by kernels < 2.6.20 */ + nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES); + nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS); + nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES); + nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); + nfct_attr_unset(ct, ATTR_USE); + + cache_update_force(STATE(mode)->internal->data, ct); +} + +static int purge_step(void *data1, void *data2) +{ + struct cache_object *obj = data2; + + STATE(get_retval) = 0; + nl_get_conntrack(STATE(get), obj->ct); /* modifies STATE(get_reval) */ + if (!STATE(get_retval)) { + if (obj->status != C_OBJ_DEAD) { + cache_object_set_status(obj, C_OBJ_DEAD); + sync_send(obj, NET_T_STATE_DEL); + cache_object_put(obj); + } + } + + return 0; +} + +static void purge(void) +{ + cache_iterate(STATE(mode)->internal->data, NULL, purge_step); +} + +static int resync(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data) +{ + struct cache_object *obj; + + if (ct_filter_conntrack(ct, 1)) + return NFCT_CB_CONTINUE; + + /* This is required by kernels < 2.6.20 */ + nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES); + nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS); + nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES); + nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); + nfct_attr_unset(ct, ATTR_USE); + + obj = cache_update_force(STATE(mode)->internal->data, ct); + if (obj == NULL) + return NFCT_CB_CONTINUE; + + switch (obj->status) { + case C_OBJ_NEW: + sync_send(obj, NET_T_STATE_NEW); + break; + case C_OBJ_ALIVE: + sync_send(obj, NET_T_STATE_UPD); + break; + } + return NFCT_CB_CONTINUE; +} + +static void +event_new_sync(struct nf_conntrack *ct, int origin) +{ + struct cache_object *obj; + int id; + + /* this event has been triggered by a direct inject, skip */ + if (origin == CTD_ORIGIN_INJECT) + return; + + /* required by linux kernel <= 2.6.20 */ + nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES); + nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS); + nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES); + nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); + + obj = cache_find(STATE(mode)->internal->data, ct, &id); + if (obj == NULL) { +retry: + obj = cache_object_new(STATE(mode)->internal->data, ct); + if (obj == NULL) + return; + if (cache_add(STATE(mode)->internal->data, obj, id) == -1) { + cache_object_free(obj); + return; + } + /* only synchronize events that have been triggered by other + * processes or the kernel, but don't propagate events that + * have been triggered by conntrackd itself, eg. commits. */ + if (origin == CTD_ORIGIN_NOT_ME) + sync_send(obj, NET_T_STATE_NEW); + } else { + cache_del(STATE(mode)->internal->data, obj); + cache_object_free(obj); + goto retry; + } +} + +static void +event_update_sync(struct nf_conntrack *ct, int origin) +{ + struct cache_object *obj; + + /* this event has been triggered by a direct inject, skip */ + if (origin == CTD_ORIGIN_INJECT) + return; + + obj = cache_update_force(STATE(mode)->internal->data, ct); + if (obj == NULL) + return; + + if (origin == CTD_ORIGIN_NOT_ME) + sync_send(obj, NET_T_STATE_UPD); +} + +static int +event_destroy_sync(struct nf_conntrack *ct, int origin) +{ + struct cache_object *obj; + int id; + + /* this event has been triggered by a direct inject, skip */ + if (origin == CTD_ORIGIN_INJECT) + return 0; + + /* we don't synchronize events for objects that are not in the cache */ + obj = cache_find(STATE(mode)->internal->data, ct, &id); + if (obj == NULL) + return 0; + + if (obj->status != C_OBJ_DEAD) { + cache_object_set_status(obj, C_OBJ_DEAD); + if (origin == CTD_ORIGIN_NOT_ME) { + sync_send(obj, NET_T_STATE_DEL); + } + cache_object_put(obj); + } + return 1; +} + +struct internal_handler internal_cache = { + .flags = INTERNAL_F_POPULATE | INTERNAL_F_RESYNC, + .init = _init, + .close = _close, + .dump = dump, + .flush = flush, + .stats = stats, + .stats_ext = stats_ext, + .populate = populate, + .purge = purge, + .resync = resync, + .new = event_new_sync, + .update = event_update_sync, + .destroy = event_destroy_sync, +}; diff --git a/src/read_config_lex.l b/src/read_config_lex.l index b4be6f0..b2d4bdb 100644 --- a/src/read_config_lex.l +++ b/src/read_config_lex.l @@ -136,6 +136,7 @@ notrack [N|n][O|o][T|t][R|r][A|a][C|c][K|k] "Type" { return T_TYPE; } "Priority" { return T_PRIO; } "NetlinkEventsReliable" { return T_NETLINK_EVENTS_RELIABLE; } +"DisableInternalCache" { return T_DISABLE_INTERNAL_CACHE; } "DisableExternalCache" { return T_DISABLE_EXTERNAL_CACHE; } "ErrorQueueLength" { return T_ERROR_QUEUE_LENGTH; } diff --git a/src/read_config_yy.y b/src/read_config_yy.y index 5075cf0..157e945 100644 --- a/src/read_config_yy.y +++ b/src/read_config_yy.y @@ -72,7 +72,7 @@ static void __max_dedicated_links_reached(void); %token T_FROM T_USERSPACE T_KERNELSPACE T_EVENT_ITER_LIMIT T_DEFAULT %token T_NETLINK_OVERRUN_RESYNC T_NICE T_IPV4_DEST_ADDR T_IPV6_DEST_ADDR %token T_SCHEDULER T_TYPE T_PRIO T_NETLINK_EVENTS_RELIABLE -%token T_DISABLE_EXTERNAL_CACHE T_ERROR_QUEUE_LENGTH +%token T_DISABLE_INTERNAL_CACHE T_DISABLE_EXTERNAL_CACHE T_ERROR_QUEUE_LENGTH %token T_IP T_PATH_VAL %token T_NUMBER @@ -852,9 +852,20 @@ sync_mode_notrack_list: sync_mode_notrack_line: timeout | purge + | disable_internal_cache | disable_external_cache ; +disable_internal_cache: T_DISABLE_INTERNAL_CACHE T_ON +{ + conf.sync.internal_cache_disable = 1; +}; + +disable_internal_cache: T_DISABLE_INTERNAL_CACHE T_OFF +{ + conf.sync.internal_cache_disable = 0; +}; + disable_external_cache: T_DISABLE_EXTERNAL_CACHE T_ON { conf.sync.external_cache_disable = 1; diff --git a/src/run.c b/src/run.c index 54ab1a5..803bbcc 100644 --- a/src/run.c +++ b/src/run.c @@ -28,6 +28,7 @@ #include "process.h" #include "origin.h" #include "date.h" +#include "internal.h" #include #include @@ -56,7 +57,9 @@ void killer(int foo) local_server_destroy(&STATE(local)); STATE(mode)->kill(); - nfct_close(STATE(dump)); /* cache_wt needs this here */ + if (STATE(mode)->internal->flags & INTERNAL_F_POPULATE) { + nfct_close(STATE(dump)); + } destroy_fds(STATE(fds)); unlink(CONFIG(lockfile)); @@ -210,9 +213,13 @@ static int local_handler(int fd, void *data) } break; case RESYNC_MASTER: - STATE(stats).nl_kernel_table_resync++; - dlog(LOG_NOTICE, "resync with master table"); - nl_dump_conntrack_table(STATE(dump)); + if (STATE(mode)->internal->flags & INTERNAL_F_POPULATE) { + STATE(stats).nl_kernel_table_resync++; + dlog(LOG_NOTICE, "resync with master table"); + nl_dump_conntrack_table(STATE(dump)); + } else { + dlog(LOG_NOTICE, "resync is unsupported in this mode"); + } break; case STATS_RUNTIME: dump_stats_runtime(fd); @@ -238,8 +245,8 @@ static void do_overrun_resync_alarm(struct alarm_block *a, void *data) static void do_polling_alarm(struct alarm_block *a, void *data) { - if (STATE(mode)->purge) - STATE(mode)->purge(); + if (STATE(mode)->internal->purge) + STATE(mode)->internal->purge(); nl_send_resync(STATE(resync)); add_alarm(&STATE(polling_alarm), CONFIG(poll_kernel_secs), 0); @@ -264,13 +271,13 @@ static int event_handler(const struct nlmsghdr *nlh, switch(type) { case NFCT_T_NEW: - STATE(mode)->event_new(ct, origin_type); + STATE(mode)->internal->new(ct, origin_type); break; case NFCT_T_UPDATE: - STATE(mode)->event_upd(ct, origin_type); + STATE(mode)->internal->update(ct, origin_type); break; case NFCT_T_DESTROY: - if (STATE(mode)->event_dst(ct, origin_type)) + if (STATE(mode)->internal->destroy(ct, origin_type)) update_traffic_stats(ct); break; default: @@ -295,7 +302,7 @@ static int dump_handler(enum nf_conntrack_msg_type type, switch(type) { case NFCT_T_UPDATE: - STATE(mode)->dump(ct); + STATE(mode)->internal->populate(ct); break; default: STATE(stats).nl_dump_unknown_type++; @@ -371,23 +378,26 @@ init(void) } nfct_callback_register(STATE(resync), NFCT_T_ALL, - STATE(mode)->resync, + STATE(mode)->internal->resync, NULL); register_fd(nfct_fd(STATE(resync)), STATE(fds)); fcntl(nfct_fd(STATE(resync)), F_SETFL, O_NONBLOCK); - STATE(dump) = nfct_open(CONNTRACK, 0); - if (STATE(dump) == NULL) { - dlog(LOG_ERR, "can't open netlink handler: %s", - strerror(errno)); - dlog(LOG_ERR, "no ctnetlink kernel support?"); - return -1; - } - nfct_callback_register(STATE(dump), NFCT_T_ALL, dump_handler, NULL); + if (STATE(mode)->internal->flags & INTERNAL_F_POPULATE) { + STATE(dump) = nfct_open(CONNTRACK, 0); + if (STATE(dump) == NULL) { + dlog(LOG_ERR, "can't open netlink handler: %s", + strerror(errno)); + dlog(LOG_ERR, "no ctnetlink kernel support?"); + return -1; + } + nfct_callback_register(STATE(dump), NFCT_T_ALL, + dump_handler, NULL); - if (nl_dump_conntrack_table(STATE(dump)) == -1) { - dlog(LOG_ERR, "can't get kernel conntrack table"); - return -1; + if (nl_dump_conntrack_table(STATE(dump)) == -1) { + dlog(LOG_ERR, "can't get kernel conntrack table"); + return -1; + } } STATE(get) = nfct_open(CONNTRACK, 0); @@ -499,7 +509,9 @@ static void __run(struct timeval *next_alarm) * we resync ourselves. */ nl_resize_socket_buffer(STATE(event)); - if (CONFIG(nl_overrun_resync) > 0) { + if (CONFIG(nl_overrun_resync) > 0 && + STATE(mode)->internal->flags & + INTERNAL_F_RESYNC) { add_alarm(&STATE(resync_alarm), CONFIG(nl_overrun_resync),0); } @@ -523,8 +535,8 @@ static void __run(struct timeval *next_alarm) } if (FD_ISSET(nfct_fd(STATE(resync)), &readfds)) { nfct_catch(STATE(resync)); - if (STATE(mode)->purge) - STATE(mode)->purge(); + if (STATE(mode)->internal->purge) + STATE(mode)->internal->purge(); } } else { /* using polling mode */ diff --git a/src/stats-mode.c b/src/stats-mode.c index 5cfb638..0403ce2 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -21,6 +21,7 @@ #include "cache.h" #include "log.h" #include "conntrackd.h" +#include "internal.h" #include #include @@ -87,7 +88,7 @@ static int local_handler_stats(int fd, int type, void *data) return ret; } -static void dump_stats(struct nf_conntrack *ct) +static void populate_stats(struct nf_conntrack *ct) { nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES); nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS); @@ -134,11 +135,9 @@ static int purge_step(void *data1, void *data2) return 0; } -static int purge_stats(void) +static void purge_stats(void) { cache_iterate(STATE_STATS(cache), NULL, purge_step); - - return 0; } static void @@ -188,15 +187,20 @@ event_destroy_stats(struct nf_conntrack *ct, int origin) return 0; } +static struct internal_handler internal_cache_stats = { + .flags = INTERNAL_F_POPULATE | INTERNAL_F_RESYNC, + .populate = populate_stats, + .resync = resync_stats, + .purge = purge_stats, + .new = event_new_stats, + .update = event_update_stats, + .destroy = event_destroy_stats +}; + struct ct_mode stats_mode = { .init = init_stats, .run = NULL, .local = local_handler_stats, .kill = kill_stats, - .dump = dump_stats, - .resync = resync_stats, - .purge = purge_stats, - .event_new = event_new_stats, - .event_upd = event_update_stats, - .event_dst = event_destroy_stats + .internal = &internal_cache_stats, }; diff --git a/src/sync-alarm.c b/src/sync-alarm.c index 4757026..0fc7943 100644 --- a/src/sync-alarm.c +++ b/src/sync-alarm.c @@ -109,7 +109,8 @@ static int alarm_recv(const struct nethdr *net) static void alarm_enqueue(struct cache_object *obj, int query) { - struct cache_alarm *ca = cache_get_extra(STATE_SYNC(internal), obj); + struct cache_alarm *ca = + cache_get_extra(STATE(mode)->internal->data, obj); if (queue_add(STATE_SYNC(tx_queue), &ca->qnode)) cache_object_get(obj); } @@ -134,7 +135,7 @@ static int tx_queue_xmit(struct queue_node *n, const void *data) int type; ca = (struct cache_alarm *)n; - obj = cache_data_get_object(STATE_SYNC(internal), ca); + obj = cache_data_get_object(STATE(mode)->internal->data, ca); type = object_status_to_network_type(obj->status); net = BUILD_NETMSG(obj->ct, type); multichannel_send(STATE_SYNC(channel), net); diff --git a/src/sync-ftfw.c b/src/sync-ftfw.c index 0d31e17..86edeab 100644 --- a/src/sync-ftfw.c +++ b/src/sync-ftfw.c @@ -166,7 +166,8 @@ static void ftfw_kill(void) static int do_cache_to_tx(void *data1, void *data2) { struct cache_object *obj = data2; - struct cache_ftfw *cn = cache_get_extra(STATE_SYNC(internal), obj); + struct cache_ftfw *cn = + cache_get_extra(STATE(mode)->internal->data, obj); if (queue_in(rs_queue, &cn->qnode)) { queue_del(&cn->qnode); @@ -224,7 +225,8 @@ static int ftfw_local(int fd, int type, void *data) break; case SEND_BULK: dlog(LOG_NOTICE, "sending bulk update"); - cache_iterate(STATE_SYNC(internal), NULL, do_cache_to_tx); + cache_iterate(STATE(mode)->internal->data, + NULL, do_cache_to_tx); break; case STATS_RSQUEUE: ftfw_local_queue(fd); @@ -303,7 +305,7 @@ static int rs_queue_empty(struct queue_node *n, const void *data) cn = (struct cache_ftfw *) n; if (h == NULL) { queue_del(n); - obj = cache_data_get_object(STATE_SYNC(internal), cn); + obj = cache_data_get_object(STATE(mode)->internal->data, cn); cache_object_put(obj); return 0; } @@ -314,7 +316,7 @@ static int rs_queue_empty(struct queue_node *n, const void *data) dp("queue: deleting from queue (seq=%u)\n", cn->seq); queue_del(n); - obj = cache_data_get_object(STATE_SYNC(internal), cn); + obj = cache_data_get_object(STATE(mode)->internal->data, cn); cache_object_put(obj); break; } @@ -347,7 +349,7 @@ static int digest_msg(const struct nethdr *net) } else if (IS_RESYNC(net)) { dp("RESYNC ALL\n"); - cache_iterate(STATE_SYNC(internal), NULL, do_cache_to_tx); + cache_iterate(STATE(mode)->internal->data, NULL, do_cache_to_tx); return MSG_CTL; } else if (IS_ALIVE(net)) @@ -464,7 +466,7 @@ static void rs_queue_purge_full(void) struct cache_object *obj; cn = (struct cache_ftfw *)n; - obj = cache_data_get_object(STATE_SYNC(internal), cn); + obj = cache_data_get_object(STATE(mode)->internal->data, cn); cache_object_put(obj); break; } @@ -512,7 +514,7 @@ static int tx_queue_xmit(struct queue_node *n, const void *data) struct nethdr *net; cn = (struct cache_ftfw *)n; - obj = cache_data_get_object(STATE_SYNC(internal), cn); + obj = cache_data_get_object(STATE(mode)->internal->data, cn); type = object_status_to_network_type(obj->status); net = BUILD_NETMSG(obj->ct, type); nethdr_set_hello(net); @@ -546,7 +548,8 @@ static void ftfw_xmit(void) static void ftfw_enqueue(struct cache_object *obj, int type) { - struct cache_ftfw *cn = cache_get_extra(STATE_SYNC(internal), obj); + struct cache_ftfw *cn = + cache_get_extra(STATE(mode)->internal->data, obj); if (queue_in(rs_queue, &cn->qnode)) { queue_del(&cn->qnode); queue_add(STATE_SYNC(tx_queue), &cn->qnode); diff --git a/src/sync-mode.c b/src/sync-mode.c index 63fae68..ecc2f0d 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -28,6 +28,7 @@ #include "queue.h" #include "process.h" #include "origin.h" +#include "internal.h" #include "external.h" #include @@ -246,7 +247,7 @@ static void do_reset_cache_alarm(struct alarm_block *a, void *data) exit(EXIT_SUCCESS); } /* this is not required if events don't get lost */ - cache_flush(STATE_SYNC(internal)); + STATE(mode)->internal->flush(); } static int init_sync(void) @@ -276,15 +277,15 @@ static int init_sync(void) if (STATE_SYNC(sync)->init) STATE_SYNC(sync)->init(); - STATE_SYNC(internal) = - cache_create("internal", - STATE_SYNC(sync)->internal_cache_flags, - STATE_SYNC(sync)->internal_cache_extra); + if (CONFIG(sync).internal_cache_disable == 0) { + STATE(mode)->internal = &internal_cache; + } else { + STATE(mode)->internal = &internal_bypass; + dlog(LOG_NOTICE, "disabling internal cache"); - if (!STATE_SYNC(internal)) { - dlog(LOG_ERR, "can't allocate memory for the internal cache"); - return -1; } + if (STATE(mode)->internal->init() == -1) + return -1; if (CONFIG(sync).external_cache_disable == 0) { STATE_SYNC(external) = &external_cache; @@ -389,7 +390,7 @@ static void run_sync(fd_set *readfds) static void kill_sync(void) { - cache_destroy(STATE_SYNC(internal)); + STATE(mode)->internal->close(); STATE_SYNC(external)->close(); multichannel_close(STATE_SYNC(channel)); @@ -466,7 +467,7 @@ static int local_handler_sync(int fd, int type, void *data) case DUMP_INTERNAL: ret = fork_process_new(CTD_PROC_ANY, 0, NULL, NULL); if (ret == 0) { - cache_dump(STATE_SYNC(internal), fd, NFCT_O_PLAIN); + STATE(mode)->internal->dump(fd, NFCT_O_PLAIN); exit(EXIT_SUCCESS); } break; @@ -480,7 +481,7 @@ static int local_handler_sync(int fd, int type, void *data) case DUMP_INT_XML: ret = fork_process_new(CTD_PROC_ANY, 0, NULL, NULL); if (ret == 0) { - cache_dump(STATE_SYNC(internal), fd, NFCT_O_XML); + STATE(mode)->internal->dump(fd, NFCT_O_XML); exit(EXIT_SUCCESS); } break; @@ -512,14 +513,14 @@ static int local_handler_sync(int fd, int type, void *data) /* inmediate flush, remove pending flush scheduled if any */ del_alarm(&STATE_SYNC(reset_cache_alarm)); dlog(LOG_NOTICE, "flushing caches"); - cache_flush(STATE_SYNC(internal)); + STATE(mode)->internal->flush(); STATE_SYNC(external)->flush(); break; case FLUSH_INT_CACHE: /* inmediate flush, remove pending flush scheduled if any */ del_alarm(&STATE_SYNC(reset_cache_alarm)); dlog(LOG_NOTICE, "flushing internal cache"); - cache_flush(STATE_SYNC(internal)); + STATE(mode)->internal->flush(); break; case FLUSH_EXT_CACHE: dlog(LOG_NOTICE, "flushing external cache"); @@ -529,7 +530,7 @@ static int local_handler_sync(int fd, int type, void *data) killer(0); break; case STATS: - cache_stats(STATE_SYNC(internal), fd); + STATE(mode)->internal->stats(fd); STATE_SYNC(external)->stats(fd); dump_traffic_stats(fd); multichannel_stats(STATE_SYNC(channel), fd); @@ -540,7 +541,7 @@ static int local_handler_sync(int fd, int type, void *data) multichannel_stats(STATE_SYNC(channel), fd); break; case STATS_CACHE: - cache_stats_extended(STATE_SYNC(internal), fd); + STATE(mode)->internal->stats_ext(fd); STATE_SYNC(external)->stats_ext(fd); break; case STATS_LINK: @@ -559,167 +560,10 @@ static int local_handler_sync(int fd, int type, void *data) return ret; } -static void sync_send(struct cache_object *obj, int query) -{ - STATE_SYNC(sync)->enqueue(obj, query); -} - -static void dump_sync(struct nf_conntrack *ct) -{ - /* This is required by kernels < 2.6.20 */ - nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES); - nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS); - nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES); - nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); - nfct_attr_unset(ct, ATTR_USE); - - cache_update_force(STATE_SYNC(internal), ct); -} - -static int purge_step(void *data1, void *data2) -{ - struct cache_object *obj = data2; - - STATE(get_retval) = 0; - nl_get_conntrack(STATE(get), obj->ct); /* modifies STATE(get_reval) */ - if (!STATE(get_retval)) { - if (obj->status != C_OBJ_DEAD) { - cache_object_set_status(obj, C_OBJ_DEAD); - sync_send(obj, NET_T_STATE_DEL); - cache_object_put(obj); - } - } - - return 0; -} - -static int purge_sync(void) -{ - cache_iterate(STATE_SYNC(internal), NULL, purge_step); - - return 0; -} - -static int resync_sync(enum nf_conntrack_msg_type type, - struct nf_conntrack *ct, - void *data) -{ - struct cache_object *obj; - - if (ct_filter_conntrack(ct, 1)) - return NFCT_CB_CONTINUE; - - /* This is required by kernels < 2.6.20 */ - nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES); - nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS); - nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES); - nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); - nfct_attr_unset(ct, ATTR_USE); - - obj = cache_update_force(STATE_SYNC(internal), ct); - if (obj == NULL) - return NFCT_CB_CONTINUE; - - switch (obj->status) { - case C_OBJ_NEW: - sync_send(obj, NET_T_STATE_NEW); - break; - case C_OBJ_ALIVE: - sync_send(obj, NET_T_STATE_UPD); - break; - } - return NFCT_CB_CONTINUE; -} - -static void -event_new_sync(struct nf_conntrack *ct, int origin) -{ - struct cache_object *obj; - int id; - - /* this event has been triggered by a direct inject, skip */ - if (origin == CTD_ORIGIN_INJECT) - return; - - /* required by linux kernel <= 2.6.20 */ - nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES); - nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS); - nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES); - nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); - - obj = cache_find(STATE_SYNC(internal), ct, &id); - if (obj == NULL) { -retry: - obj = cache_object_new(STATE_SYNC(internal), ct); - if (obj == NULL) - return; - if (cache_add(STATE_SYNC(internal), obj, id) == -1) { - cache_object_free(obj); - return; - } - /* only synchronize events that have been triggered by other - * processes or the kernel, but don't propagate events that - * have been triggered by conntrackd itself, eg. commits. */ - if (origin == CTD_ORIGIN_NOT_ME) - sync_send(obj, NET_T_STATE_NEW); - } else { - cache_del(STATE_SYNC(internal), obj); - cache_object_free(obj); - goto retry; - } -} - -static void -event_update_sync(struct nf_conntrack *ct, int origin) -{ - struct cache_object *obj; - - /* this event has been triggered by a direct inject, skip */ - if (origin == CTD_ORIGIN_INJECT) - return; - - obj = cache_update_force(STATE_SYNC(internal), ct); - if (obj == NULL) - return; - - if (origin == CTD_ORIGIN_NOT_ME) - sync_send(obj, NET_T_STATE_UPD); -} - -static int -event_destroy_sync(struct nf_conntrack *ct, int origin) -{ - struct cache_object *obj; - int id; - - /* this event has been triggered by a direct inject, skip */ - if (origin == CTD_ORIGIN_INJECT) - return 0; - - /* we don't synchronize events for objects that are not in the cache */ - obj = cache_find(STATE_SYNC(internal), ct, &id); - if (obj == NULL) - return 0; - - if (obj->status != C_OBJ_DEAD) { - cache_object_set_status(obj, C_OBJ_DEAD); - if (origin == CTD_ORIGIN_NOT_ME) { - sync_send(obj, NET_T_STATE_DEL); - } - cache_object_put(obj); - } - return 1; -} - struct ct_mode sync_mode = { .init = init_sync, .run = run_sync, .local = local_handler_sync, .kill = kill_sync, - .dump = dump_sync, - .resync = resync_sync, - .purge = purge_sync, - .event_new = event_new_sync, - .event_upd = event_update_sync, - .event_dst = event_destroy_sync + /* the internal handler is set in run-time. */ }; diff --git a/src/sync-notrack.c b/src/sync-notrack.c index d9f273e..c4ad941 100644 --- a/src/sync-notrack.c +++ b/src/sync-notrack.c @@ -74,12 +74,44 @@ static void tx_queue_add_ctlmsg(uint32_t flags, uint32_t from, uint32_t to) static int do_cache_to_tx(void *data1, void *data2) { struct cache_object *obj = data2; - struct cache_notrack *cn = cache_get_extra(STATE_SYNC(internal), obj); + struct cache_notrack *cn = + cache_get_extra(STATE(mode)->internal->data, obj); if (queue_add(STATE_SYNC(tx_queue), &cn->qnode)) cache_object_get(obj); return 0; } +static int kernel_resync_cb(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, void *data) +{ + struct nethdr *net; + + net = BUILD_NETMSG(ct, NET_T_STATE_NEW); + multichannel_send(STATE_SYNC(channel), net); + + return NFCT_CB_CONTINUE; +} + +/* Only used if the internal cache is disabled. */ +static void kernel_resync(void) +{ + struct nfct_handle *h; + u_int32_t family = AF_UNSPEC; + int ret; + + h = nfct_open(CONNTRACK, 0); + if (h == NULL) { + dlog(LOG_ERR, "can't allocate memory for the internal cache"); + return; + } + nfct_callback_register(h, NFCT_T_ALL, kernel_resync_cb, NULL); + ret = nfct_query(h, NFCT_Q_DUMP, &family); + if (ret == -1) { + dlog(LOG_ERR, "can't dump kernel table"); + } + nfct_close(h); +} + static int notrack_local(int fd, int type, void *data) { int ret = LOCAL_RET_OK; @@ -91,7 +123,12 @@ static int notrack_local(int fd, int type, void *data) break; case SEND_BULK: dlog(LOG_NOTICE, "sending bulk update"); - cache_iterate(STATE_SYNC(internal), NULL, do_cache_to_tx); + if (CONFIG(sync).internal_cache_disable) { + kernel_resync(); + } else { + cache_iterate(STATE(mode)->internal->data, + NULL, do_cache_to_tx); + } break; default: ret = 0; @@ -107,7 +144,12 @@ static int digest_msg(const struct nethdr *net) return MSG_DATA; if (IS_RESYNC(net)) { - cache_iterate(STATE_SYNC(internal), NULL, do_cache_to_tx); + if (CONFIG(sync).internal_cache_disable) { + kernel_resync(); + } else { + cache_iterate(STATE(mode)->internal->data, + NULL, do_cache_to_tx); + } return MSG_CTL; } @@ -154,7 +196,7 @@ static int tx_queue_xmit(struct queue_node *n, const void *data2) struct nethdr *net; cn = (struct cache_ftfw *)n; - obj = cache_data_get_object(STATE_SYNC(internal), cn); + obj = cache_data_get_object(STATE(mode)->internal->data, cn); type = object_status_to_network_type(obj->status);; net = BUILD_NETMSG(obj->ct, type); @@ -175,7 +217,8 @@ static void notrack_xmit(void) static void notrack_enqueue(struct cache_object *obj, int query) { - struct cache_notrack *cn = cache_get_extra(STATE_SYNC(internal), obj); + struct cache_notrack *cn = + cache_get_extra(STATE(mode)->internal->data, obj); if (queue_add(STATE_SYNC(tx_queue), &cn->qnode)) cache_object_get(obj); } -- cgit v1.2.3 From 65be3d49b0f4350a227dedd70ac17c7c9cf6274e Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 4 Jan 2012 14:28:50 +0100 Subject: conntrackd: generalize caching infrastructure This patch generalizes the caching infrastructure to store different object types. This patch is the first in the series to prepare support for the synchronization of expectations. Signed-off-by: Pablo Neira Ayuso --- include/cache.h | 57 +++++++- include/internal.h | 27 ++-- src/Makefile.am | 2 +- src/cache-ct.c | 358 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/cache.c | 154 +++++++++------------- src/cache_iterators.c | 268 ------------------------------------- src/external_cache.c | 4 +- src/internal_bypass.c | 67 +++++----- src/internal_cache.c | 104 ++++++++------- src/run.c | 23 ++-- src/stats-mode.c | 42 +++--- src/sync-alarm.c | 11 +- src/sync-ftfw.c | 23 ++-- src/sync-mode.c | 19 +-- src/sync-notrack.c | 12 +- 15 files changed, 647 insertions(+), 524 deletions(-) create mode 100644 src/cache-ct.c delete mode 100644 src/cache_iterators.c (limited to 'src/stats-mode.c') diff --git a/include/cache.h b/include/cache.h index ddf2049..a42e395 100644 --- a/include/cache.h +++ b/include/cache.h @@ -27,7 +27,7 @@ enum { struct cache; struct cache_object { struct hashtable_node hashnode; - struct nf_conntrack *ct; + void *ptr; struct cache *cache; int status; int refcnt; @@ -48,14 +48,22 @@ extern struct cache_feature timer_feature; #define CACHE_MAX_NAMELEN 32 +enum cache_type { + CACHE_T_NONE = 0, + CACHE_T_CT, + CACHE_T_MAX +}; + struct cache { char name[CACHE_MAX_NAMELEN]; + enum cache_type type; struct hashtable *h; unsigned int num_features; struct cache_feature **features; unsigned int feature_type[CACHE_MAX_FEATURE]; unsigned int *feature_offset; + struct cache_ops *ops; struct cache_extra *extra; unsigned int extra_offset; size_t object_size; @@ -94,22 +102,48 @@ struct cache_extra { void (*destroy)(struct cache_object *obj, void *data); }; +struct nfct_handle; + +/* cache options depends on the object type: conntrack or expectation. */ +struct cache_ops { + /* hashing and comparison of objects. */ + uint32_t (*hash)(const void *data, const struct hashtable *table); + int (*cmp)(const void *data1, const void *data2); + + /* object allocation, copy and release. */ + void *(*alloc)(void); + void (*copy)(void *dst, void *src, unsigned int flags); + void (*free)(void *ptr); + + /* dump and commit. */ + int (*dump_step)(void *data1, void *n); + int (*commit)(struct cache *c, struct nfct_handle *h, int clientfd); + + /* build network message from object. */ + struct nethdr *(*build_msg)(const struct cache_object *obj, int type); +}; + +/* templates to configure conntrack caching. */ +extern struct cache_ops cache_sync_internal_ct_ops; +extern struct cache_ops cache_sync_external_ct_ops; +extern struct cache_ops cache_stats_ct_ops; + struct nf_conntrack; -struct cache *cache_create(const char *name, unsigned int features, struct cache_extra *extra); +struct cache *cache_create(const char *name, enum cache_type type, unsigned int features, struct cache_extra *extra, struct cache_ops *ops); void cache_destroy(struct cache *e); -struct cache_object *cache_object_new(struct cache *c, struct nf_conntrack *ct); +struct cache_object *cache_object_new(struct cache *c, void *ptr); void cache_object_free(struct cache_object *obj); void cache_object_get(struct cache_object *obj); int cache_object_put(struct cache_object *obj); void cache_object_set_status(struct cache_object *obj, int status); int cache_add(struct cache *c, struct cache_object *obj, int id); -void cache_update(struct cache *c, struct cache_object *obj, int id, struct nf_conntrack *ct); -struct cache_object *cache_update_force(struct cache *c, struct nf_conntrack *ct); +void cache_update(struct cache *c, struct cache_object *obj, int id, void *ptr); +struct cache_object *cache_update_force(struct cache *c, void *ptr); void cache_del(struct cache *c, struct cache_object *obj); -struct cache_object *cache_find(struct cache *c, struct nf_conntrack *ct, int *pos); +struct cache_object *cache_find(struct cache *c, void *ptr, int *pos); void cache_stats(const struct cache *c, int fd); void cache_stats_extended(const struct cache *c, int fd); struct cache_object *cache_data_get_object(struct cache *c, void *data); @@ -120,7 +154,18 @@ void cache_iterate_limit(struct cache *c, void *data, uint32_t from, uint32_t st /* iterators */ struct nfct_handle; +struct __dump_container { + int fd; + int type; +}; + void cache_dump(struct cache *c, int fd, int type); + +struct __commit_container { + struct nfct_handle *h; + struct cache *c; +}; + int cache_commit(struct cache *c, struct nfct_handle *h, int clientfd); void cache_flush(struct cache *c); void cache_bulk(struct cache *c); diff --git a/include/internal.h b/include/internal.h index 1f11340..f50eb79 100644 --- a/include/internal.h +++ b/include/internal.h @@ -12,25 +12,28 @@ enum { }; struct internal_handler { - void *data; unsigned int flags; int (*init)(void); void (*close)(void); - void (*new)(struct nf_conntrack *ct, int origin_type); - void (*update)(struct nf_conntrack *ct, int origin_type); - int (*destroy)(struct nf_conntrack *ct, int origin_type); + struct { + void *data; - void (*dump)(int fd, int type); - void (*populate)(struct nf_conntrack *ct); - void (*purge)(void); - int (*resync)(enum nf_conntrack_msg_type type, - struct nf_conntrack *ct, void *data); - void (*flush)(void); + void (*new)(struct nf_conntrack *ct, int origin_type); + void (*upd)(struct nf_conntrack *ct, int origin_type); + int (*del)(struct nf_conntrack *ct, int origin_type); - void (*stats)(int fd); - void (*stats_ext)(int fd); + void (*dump)(int fd, int type); + void (*populate)(struct nf_conntrack *ct); + void (*purge)(void); + int (*resync)(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, void *data); + void (*flush)(void); + + void (*stats)(int fd); + void (*stats_ext)(int fd); + } ct; }; extern struct internal_handler internal_cache; diff --git a/src/Makefile.am b/src/Makefile.am index 70e496d..a0abeee 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,7 +12,7 @@ conntrack_LDADD = ../extensions/libct_proto_tcp.la ../extensions/libct_proto_udp conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c rbtree.c \ local.c log.c mcast.c udp.c netlink.c vector.c \ filter.c fds.c event.c process.c origin.c date.c \ - cache.c cache_iterators.c \ + cache.c cache-ct.c \ cache_timer.c \ sync-mode.c sync-alarm.c sync-ftfw.c sync-notrack.c \ traffic_stats.c stats-mode.c \ diff --git a/src/cache-ct.c b/src/cache-ct.c new file mode 100644 index 0000000..2c6fd4e --- /dev/null +++ b/src/cache-ct.c @@ -0,0 +1,358 @@ +/* + * (C) 2006-2011 by Pablo Neira Ayuso + * (C) 2011 by Vyatta Inc. + * + * 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 "cache.h" +#include "hash.h" +#include "log.h" +#include "conntrackd.h" +#include "netlink.h" +#include "event.h" +#include "jhash.h" +#include "network.h" + +#include +#include +#include +#include + +static uint32_t +cache_hash4_ct(const struct nf_conntrack *ct, const struct hashtable *table) +{ + uint32_t a[4] = { + [0] = nfct_get_attr_u32(ct, ATTR_IPV4_SRC), + [1] = nfct_get_attr_u32(ct, ATTR_IPV4_DST), + [2] = nfct_get_attr_u8(ct, ATTR_L3PROTO) << 16 | + nfct_get_attr_u8(ct, ATTR_L4PROTO), + [3] = nfct_get_attr_u16(ct, ATTR_PORT_SRC) << 16 | + nfct_get_attr_u16(ct, ATTR_PORT_DST), + }; + + /* + * Instead of returning hash % table->hashsize (implying a divide) + * we return the high 32 bits of the (hash * table->hashsize) that will + * give results between [0 and hashsize-1] and same hash distribution, + * but using a multiply, less expensive than a divide. See: + * http://www.mail-archive.com/netdev@vger.kernel.org/msg56623.html + */ + return ((uint64_t)jhash2(a, 4, 0) * table->hashsize) >> 32; +} + +static uint32_t +cache_hash6_ct(const struct nf_conntrack *ct, const struct hashtable *table) +{ + uint32_t a[10]; + + memcpy(&a[0], nfct_get_attr(ct, ATTR_IPV6_SRC), sizeof(uint32_t)*4); + memcpy(&a[4], nfct_get_attr(ct, ATTR_IPV6_SRC), sizeof(uint32_t)*4); + a[8] = nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16 | + nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO); + a[9] = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16 | + nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST); + + return ((uint64_t)jhash2(a, 10, 0) * table->hashsize) >> 32; +} + +static uint32_t +cache_ct_hash(const void *data, const struct hashtable *table) +{ + int ret = 0; + const struct nf_conntrack *ct = data; + + switch(nfct_get_attr_u8(ct, ATTR_L3PROTO)) { + case AF_INET: + ret = cache_hash4_ct(ct, table); + break; + case AF_INET6: + ret = cache_hash6_ct(ct, table); + break; + default: + dlog(LOG_ERR, "unknown layer 3 proto in hash"); + break; + } + return ret; +} + +static int cache_ct_cmp(const void *data1, const void *data2) +{ + const struct cache_object *obj = data1; + const struct nf_conntrack *ct = data2; + + return nfct_cmp(obj->ptr, ct, NFCT_CMP_ORIG) && + nfct_get_attr_u32(obj->ptr, ATTR_ID) == + nfct_get_attr_u32(ct, ATTR_ID); +} + +static void *cache_ct_alloc(void) +{ + return nfct_new(); +} + +static void cache_ct_free(void *ptr) +{ + nfct_destroy(ptr); +} + +static void cache_ct_copy(void *dst, void *src, unsigned int flags) +{ + nfct_copy(dst, src, flags); +} + +static int cache_ct_dump_step(void *data1, void *n) +{ + char buf[1024]; + int size; + struct __dump_container *container = data1; + struct cache_object *obj = n; + char *data = obj->data; + unsigned i; + + /* + * XXX: Do not dump the entries that are scheduled to expire. + * These entries talk about already destroyed connections + * that we keep for some time just in case that we have to + * resent some lost messages. We do not show them to the + * user as he may think that the firewall replicas are not + * in sync. The branch below is a hack as it is quite + * specific and it breaks conntrackd modularity. Probably + * there's a nicer way to do this but until I come up with it... + */ + if (CONFIG(flags) & CTD_SYNC_FTFW && obj->status == C_OBJ_DEAD) + return 0; + + /* do not show cached timeout, this may confuse users */ + if (nfct_attr_is_set(obj->ptr, ATTR_TIMEOUT)) + nfct_attr_unset(obj->ptr, ATTR_TIMEOUT); + + memset(buf, 0, sizeof(buf)); + size = nfct_snprintf(buf, + sizeof(buf), + obj->ptr, + NFCT_T_UNKNOWN, + container->type, + 0); + + for (i = 0; i < obj->cache->num_features; i++) { + if (obj->cache->features[i]->dump) { + size += obj->cache->features[i]->dump(obj, + data, + buf+size, + container->type); + data += obj->cache->features[i]->size; + } + } + if (container->type != NFCT_O_XML) { + long tm = time(NULL); + size += sprintf(buf+size, " [active since %lds]", + tm - obj->lifetime); + } + size += sprintf(buf+size, "\n"); + if (send(container->fd, buf, size, 0) == -1) { + if (errno != EPIPE) + return -1; + } + + return 0; +} + +static void +cache_ct_commit_step(struct __commit_container *tmp, struct cache_object *obj) +{ + int ret, retry = 1, timeout; + struct nf_conntrack *ct = obj->ptr; + + if (CONFIG(commit_timeout)) { + timeout = CONFIG(commit_timeout); + } else { + timeout = time(NULL) - obj->lastupdate; + if (timeout < 0) { + /* XXX: Arbitrarily set the timer to one minute, how + * can this happen? For example, an adjustment due to + * daylight-saving. Probably other situations can + * trigger this. */ + timeout = 60; + } + /* calculate an estimation of the current timeout */ + timeout = nfct_get_attr_u32(ct, ATTR_TIMEOUT) - timeout; + if (timeout < 0) { + timeout = 60; + } + } + +retry: + if (nl_create_conntrack(tmp->h, ct, timeout) == -1) { + if (errno == EEXIST && retry == 1) { + ret = nl_destroy_conntrack(tmp->h, ct); + if (ret == 0 || (ret == -1 && errno == ENOENT)) { + if (retry) { + retry = 0; + goto retry; + } + } + dlog(LOG_ERR, "commit-destroy: %s", strerror(errno)); + dlog_ct(STATE(log), ct, NFCT_O_PLAIN); + tmp->c->stats.commit_fail++; + } else { + dlog(LOG_ERR, "commit-create: %s", strerror(errno)); + dlog_ct(STATE(log), ct, NFCT_O_PLAIN); + tmp->c->stats.commit_fail++; + } + } else { + tmp->c->stats.commit_ok++; + } +} + +static int cache_ct_commit_related(void *data, void *n) +{ + struct cache_object *obj = n; + + if (ct_is_related(obj->ptr)) + cache_ct_commit_step(data, obj); + + /* keep iterating even if we have found errors */ + return 0; +} + +static int cache_ct_commit_master(void *data, void *n) +{ + struct cache_object *obj = n; + + if (ct_is_related(obj->ptr)) + return 0; + + cache_ct_commit_step(data, obj); + return 0; +} + +static int cache_ct_commit(struct cache *c, struct nfct_handle *h, int clientfd) +{ + unsigned int commit_ok, commit_fail; + struct __commit_container tmp = { + .h = h, + .c = c, + }; + struct timeval commit_stop, res; + + /* we already have one commit in progress, skip this. The clientfd + * descriptor has to be closed by the caller. */ + if (clientfd && STATE_SYNC(commit).clientfd != -1) + return 0; + + switch(STATE_SYNC(commit).state) { + case COMMIT_STATE_INACTIVE: + gettimeofday(&STATE_SYNC(commit).stats.start, NULL); + STATE_SYNC(commit).stats.ok = c->stats.commit_ok; + STATE_SYNC(commit).stats.fail = c->stats.commit_fail; + STATE_SYNC(commit).clientfd = clientfd; + case COMMIT_STATE_MASTER: + STATE_SYNC(commit).current = + hashtable_iterate_limit(c->h, &tmp, + STATE_SYNC(commit).current, + CONFIG(general).commit_steps, + cache_ct_commit_master); + if (STATE_SYNC(commit).current < CONFIG(hashsize)) { + STATE_SYNC(commit).state = COMMIT_STATE_MASTER; + /* give it another step as soon as possible */ + write_evfd(STATE_SYNC(commit).evfd); + return 1; + } + STATE_SYNC(commit).current = 0; + STATE_SYNC(commit).state = COMMIT_STATE_RELATED; + case COMMIT_STATE_RELATED: + STATE_SYNC(commit).current = + hashtable_iterate_limit(c->h, &tmp, + STATE_SYNC(commit).current, + CONFIG(general).commit_steps, + cache_ct_commit_related); + if (STATE_SYNC(commit).current < CONFIG(hashsize)) { + STATE_SYNC(commit).state = COMMIT_STATE_RELATED; + /* give it another step as soon as possible */ + write_evfd(STATE_SYNC(commit).evfd); + return 1; + } + /* calculate the time that commit has taken */ + gettimeofday(&commit_stop, NULL); + timersub(&commit_stop, &STATE_SYNC(commit).stats.start, &res); + + /* calculate new entries committed */ + commit_ok = c->stats.commit_ok - STATE_SYNC(commit).stats.ok; + commit_fail = + c->stats.commit_fail - STATE_SYNC(commit).stats.fail; + + /* log results */ + dlog(LOG_NOTICE, "Committed %u new entries", commit_ok); + + if (commit_fail) + dlog(LOG_NOTICE, "%u entries can't be " + "committed", commit_fail); + + dlog(LOG_NOTICE, "commit has taken %lu.%06lu seconds", + res.tv_sec, res.tv_usec); + + /* prepare the state machine for new commits */ + STATE_SYNC(commit).current = 0; + STATE_SYNC(commit).state = COMMIT_STATE_INACTIVE; + + /* Close the client socket now that we're done. */ + close(STATE_SYNC(commit).clientfd); + STATE_SYNC(commit).clientfd = -1; + } + return 1; +} + +static struct nethdr * +cache_ct_build_msg(const struct cache_object *obj, int type) +{ + return BUILD_NETMSG_FROM_CT(obj->ptr, type); +} + +/* template to cache conntracks coming from the kernel. */ +struct cache_ops cache_sync_internal_ct_ops = { + .hash = cache_ct_hash, + .cmp = cache_ct_cmp, + .alloc = cache_ct_alloc, + .free = cache_ct_free, + .copy = cache_ct_copy, + .dump_step = cache_ct_dump_step, + .commit = NULL, + .build_msg = cache_ct_build_msg, +}; + +/* template to cache conntracks coming from the network. */ +struct cache_ops cache_sync_external_ct_ops = { + .hash = cache_ct_hash, + .cmp = cache_ct_cmp, + .alloc = cache_ct_alloc, + .free = cache_ct_free, + .copy = cache_ct_copy, + .dump_step = cache_ct_dump_step, + .commit = cache_ct_commit, + .build_msg = NULL, +}; + +/* template to cache conntracks for the statistics mode. */ +struct cache_ops cache_stats_ct_ops = { + .hash = cache_ct_hash, + .cmp = cache_ct_cmp, + .alloc = cache_ct_alloc, + .free = cache_ct_free, + .copy = cache_ct_copy, + .dump_step = cache_ct_dump_step, + .commit = NULL, + .build_msg = NULL, +}; diff --git a/src/cache.c b/src/cache.c index f411121..efdab0e 100644 --- a/src/cache.c +++ b/src/cache.c @@ -1,5 +1,6 @@ /* - * (C) 2006-2009 by Pablo Neira Ayuso + * (C) 2006-2011 by Pablo Neira Ayuso + * (C) 2011 by Vyatta Inc. * * 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 @@ -28,80 +29,14 @@ #include #include -static uint32_t -__hash4(const struct nf_conntrack *ct, const struct hashtable *table) -{ - uint32_t a[4] = { - [0] = nfct_get_attr_u32(ct, ATTR_IPV4_SRC), - [1] = nfct_get_attr_u32(ct, ATTR_IPV4_DST), - [2] = nfct_get_attr_u8(ct, ATTR_L3PROTO) << 16 | - nfct_get_attr_u8(ct, ATTR_L4PROTO), - [3] = nfct_get_attr_u16(ct, ATTR_PORT_SRC) << 16 | - nfct_get_attr_u16(ct, ATTR_PORT_DST), - }; - - /* - * Instead of returning hash % table->hashsize (implying a divide) - * we return the high 32 bits of the (hash * table->hashsize) that will - * give results between [0 and hashsize-1] and same hash distribution, - * but using a multiply, less expensive than a divide. See: - * http://www.mail-archive.com/netdev@vger.kernel.org/msg56623.html - */ - return ((uint64_t)jhash2(a, 4, 0) * table->hashsize) >> 32; -} - -static uint32_t -__hash6(const struct nf_conntrack *ct, const struct hashtable *table) -{ - uint32_t a[10]; - - memcpy(&a[0], nfct_get_attr(ct, ATTR_IPV6_SRC), sizeof(uint32_t)*4); - memcpy(&a[4], nfct_get_attr(ct, ATTR_IPV6_SRC), sizeof(uint32_t)*4); - a[8] = nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16 | - nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO); - a[9] = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16 | - nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST); - - return ((uint64_t)jhash2(a, 10, 0) * table->hashsize) >> 32; -} - -static uint32_t hash(const void *data, const struct hashtable *table) -{ - int ret = 0; - const struct nf_conntrack *ct = data; - - switch(nfct_get_attr_u8(ct, ATTR_L3PROTO)) { - case AF_INET: - ret = __hash4(ct, table); - break; - case AF_INET6: - ret = __hash6(ct, table); - break; - default: - dlog(LOG_ERR, "unknown layer 3 proto in hash"); - break; - } - - return ret; -} - -static int compare(const void *data1, const void *data2) -{ - const struct cache_object *obj = data1; - const struct nf_conntrack *ct = data2; - - return nfct_cmp(obj->ct, ct, NFCT_CMP_ORIG) && - nfct_get_attr_u32(obj->ct, ATTR_ID) == - nfct_get_attr_u32(ct, ATTR_ID); -} - struct cache_feature *cache_feature[CACHE_MAX_FEATURE] = { [TIMER_FEATURE] = &timer_feature, }; -struct cache *cache_create(const char *name, +struct cache *cache_create(const char *name, enum cache_type type, unsigned int features, - struct cache_extra *extra) + struct cache_extra *extra, + struct cache_ops *ops) { size_t size = sizeof(struct cache_object); int i, j = 0; @@ -110,12 +45,16 @@ struct cache *cache_create(const char *name, unsigned int feature_offset[CACHE_MAX_FEATURE] = {}; unsigned int feature_type[CACHE_MAX_FEATURE] = {}; + if (type == CACHE_T_NONE || type >= CACHE_T_MAX) + return NULL; + c = malloc(sizeof(struct cache)); if (!c) return NULL; memset(c, 0, sizeof(struct cache)); strcpy(c->name, name); + c->type = type; for (i = 0; i < CACHE_MAX_FEATURE; i++) { if ((1 << i) & features) { @@ -150,11 +89,19 @@ struct cache *cache_create(const char *name, } memcpy(c->feature_offset, feature_offset, sizeof(unsigned int) * j); + if (!ops || !ops->hash || !ops->cmp || + !ops->alloc || !ops->copy || !ops->free) { + free(c->feature_offset); + free(c->features); + free(c); + return NULL; + } + c->ops = ops; + c->h = hashtable_create(CONFIG(hashsize), CONFIG(limit), - hash, - compare); - + c->ops->hash, + c->ops->cmp); if (!c->h) { free(c->features); free(c->feature_offset); @@ -175,7 +122,7 @@ void cache_destroy(struct cache *c) free(c); } -struct cache_object *cache_object_new(struct cache *c, struct nf_conntrack *ct) +struct cache_object *cache_object_new(struct cache *c, void *ptr) { struct cache_object *obj; @@ -187,13 +134,14 @@ struct cache_object *cache_object_new(struct cache *c, struct nf_conntrack *ct) } obj->cache = c; - if ((obj->ct = nfct_new()) == NULL) { + obj->ptr = c->ops->alloc(); + if (obj->ptr == NULL) { free(obj); errno = ENOMEM; c->stats.add_fail_enomem++; return NULL; } - nfct_copy(obj->ct, ct, NFCT_CP_OVERRIDE); + c->ops->copy(obj->ptr, ptr, NFCT_CP_OVERRIDE); obj->status = C_OBJ_NONE; c->stats.objects++; @@ -203,7 +151,8 @@ struct cache_object *cache_object_new(struct cache *c, struct nf_conntrack *ct) void cache_object_free(struct cache_object *obj) { obj->cache->stats.objects--; - nfct_destroy(obj->ct); + obj->cache->ops->free(obj->ptr); + free(obj); } @@ -271,13 +220,12 @@ int cache_add(struct cache *c, struct cache_object *obj, int id) return 0; } -void cache_update(struct cache *c, struct cache_object *obj, int id, - struct nf_conntrack *ct) +void cache_update(struct cache *c, struct cache_object *obj, int id, void *ptr) { char *data = obj->data; unsigned int i; - nfct_copy(obj->ct, ct, NFCT_CP_META); + c->ops->copy(obj->ptr, ptr, NFCT_CP_META); for (i = 0; i < c->num_features; i++) { c->features[i]->update(obj, data); @@ -322,23 +270,22 @@ void cache_del(struct cache *c, struct cache_object *obj) __del(c, obj); } -struct cache_object * -cache_update_force(struct cache *c, struct nf_conntrack *ct) +struct cache_object *cache_update_force(struct cache *c, void *ptr) { struct cache_object *obj; int id; - obj = cache_find(c, ct, &id); + obj = cache_find(c, ptr, &id); if (obj) { if (obj->status != C_OBJ_DEAD) { - cache_update(c, obj, id, ct); + cache_update(c, obj, id, ptr); return obj; } else { cache_del(c, obj); cache_object_free(obj); } } - obj = cache_object_new(c, ct); + obj = cache_object_new(c, ptr); if (obj == NULL) return NULL; @@ -350,11 +297,10 @@ cache_update_force(struct cache *c, struct nf_conntrack *ct) return obj; } -struct cache_object * -cache_find(struct cache *c, struct nf_conntrack *ct, int *id) +struct cache_object *cache_find(struct cache *c, void *ptr, int *id) { - *id = hashtable_hash(c->h, ct); - return ((struct cache_object *) hashtable_find(c->h, ct, *id)); + *id = hashtable_hash(c->h, ptr); + return ((struct cache_object *) hashtable_find(c->h, ptr, *id)); } struct cache_object *cache_data_get_object(struct cache *c, void *data) @@ -432,3 +378,33 @@ void cache_iterate_limit(struct cache *c, void *data, { hashtable_iterate_limit(c->h, data, from, steps, iterate); } + +void cache_dump(struct cache *c, int fd, int type) +{ + struct __dump_container tmp = { + .fd = fd, + .type = type + }; + hashtable_iterate(c->h, (void *) &tmp, c->ops->dump_step); +} + +int cache_commit(struct cache *c, struct nfct_handle *h, int clientfd) +{ + return c->ops->commit(c, h, clientfd); +} + +static int do_flush(void *data, void *n) +{ + struct cache *c = data; + struct cache_object *obj = n; + + cache_del(c, obj); + cache_object_free(obj); + return 0; +} + +void cache_flush(struct cache *c) +{ + hashtable_iterate(c->h, c, do_flush); + c->stats.flush++; +} diff --git a/src/cache_iterators.c b/src/cache_iterators.c deleted file mode 100644 index 3248c70..0000000 --- a/src/cache_iterators.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * (C) 2006-2007 by Pablo Neira Ayuso - * - * 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 "cache.h" -#include "hash.h" -#include "log.h" -#include "conntrackd.h" -#include "netlink.h" -#include "event.h" - -#include -#include -#include -#include -#include - -struct __dump_container { - int fd; - int type; -}; - -static int do_dump(void *data1, void *n) -{ - char buf[1024]; - int size; - struct __dump_container *container = data1; - struct cache_object *obj = n; - char *data = obj->data; - unsigned i; - - /* - * XXX: Do not dump the entries that are scheduled to expire. - * These entries talk about already destroyed connections - * that we keep for some time just in case that we have to - * resent some lost messages. We do not show them to the - * user as he may think that the firewall replicas are not - * in sync. The branch below is a hack as it is quite - * specific and it breaks conntrackd modularity. Probably - * there's a nicer way to do this but until I come up with it... - */ - if (CONFIG(flags) & CTD_SYNC_FTFW && obj->status == C_OBJ_DEAD) - return 0; - - /* do not show cached timeout, this may confuse users */ - if (nfct_attr_is_set(obj->ct, ATTR_TIMEOUT)) - nfct_attr_unset(obj->ct, ATTR_TIMEOUT); - - memset(buf, 0, sizeof(buf)); - size = nfct_snprintf(buf, - sizeof(buf), - obj->ct, - NFCT_T_UNKNOWN, - container->type, - 0); - - for (i = 0; i < obj->cache->num_features; i++) { - if (obj->cache->features[i]->dump) { - size += obj->cache->features[i]->dump(obj, - data, - buf+size, - container->type); - data += obj->cache->features[i]->size; - } - } - if (container->type != NFCT_O_XML) { - long tm = time(NULL); - size += sprintf(buf+size, " [active since %lds]", - tm - obj->lifetime); - } - size += sprintf(buf+size, "\n"); - if (send(container->fd, buf, size, 0) == -1) { - if (errno != EPIPE) - return -1; - } - - return 0; -} - -void cache_dump(struct cache *c, int fd, int type) -{ - struct __dump_container tmp = { - .fd = fd, - .type = type - }; - - hashtable_iterate(c->h, (void *) &tmp, do_dump); -} - -struct __commit_container { - struct nfct_handle *h; - struct cache *c; -}; - -static void -__do_commit_step(struct __commit_container *tmp, struct cache_object *obj) -{ - int ret, retry = 1, timeout; - struct nf_conntrack *ct = obj->ct; - - if (CONFIG(commit_timeout)) { - timeout = CONFIG(commit_timeout); - } else { - timeout = time(NULL) - obj->lastupdate; - if (timeout < 0) { - /* XXX: Arbitrarily set the timer to one minute, how - * can this happen? For example, an adjustment due to - * daylight-saving. Probably other situations can - * trigger this. */ - timeout = 60; - } - /* calculate an estimation of the current timeout */ - timeout = nfct_get_attr_u32(ct, ATTR_TIMEOUT) - timeout; - if (timeout < 0) { - timeout = 60; - } - } - -retry: - if (nl_create_conntrack(tmp->h, ct, timeout) == -1) { - if (errno == EEXIST && retry == 1) { - ret = nl_destroy_conntrack(tmp->h, ct); - if (ret == 0 || (ret == -1 && errno == ENOENT)) { - if (retry) { - retry = 0; - goto retry; - } - } - dlog(LOG_ERR, "commit-destroy: %s", strerror(errno)); - dlog_ct(STATE(log), ct, NFCT_O_PLAIN); - tmp->c->stats.commit_fail++; - } else { - dlog(LOG_ERR, "commit-create: %s", strerror(errno)); - dlog_ct(STATE(log), ct, NFCT_O_PLAIN); - tmp->c->stats.commit_fail++; - } - } else { - tmp->c->stats.commit_ok++; - } -} - -static int do_commit_related(void *data, void *n) -{ - struct cache_object *obj = n; - - if (ct_is_related(obj->ct)) - __do_commit_step(data, obj); - - /* keep iterating even if we have found errors */ - return 0; -} - -static int do_commit_master(void *data, void *n) -{ - struct cache_object *obj = n; - - if (ct_is_related(obj->ct)) - return 0; - - __do_commit_step(data, obj); - return 0; -} - -int cache_commit(struct cache *c, struct nfct_handle *h, int clientfd) -{ - unsigned int commit_ok, commit_fail; - struct __commit_container tmp = { - .h = h, - .c = c, - }; - struct timeval commit_stop, res; - - /* we already have one commit in progress, skip this. The clientfd - * descriptor has to be closed by the caller. */ - if (clientfd && STATE_SYNC(commit).clientfd != -1) - return 0; - - switch(STATE_SYNC(commit).state) { - case COMMIT_STATE_INACTIVE: - gettimeofday(&STATE_SYNC(commit).stats.start, NULL); - STATE_SYNC(commit).stats.ok = c->stats.commit_ok; - STATE_SYNC(commit).stats.fail = c->stats.commit_fail; - STATE_SYNC(commit).clientfd = clientfd; - case COMMIT_STATE_MASTER: - STATE_SYNC(commit).current = - hashtable_iterate_limit(c->h, &tmp, - STATE_SYNC(commit).current, - CONFIG(general).commit_steps, - do_commit_master); - if (STATE_SYNC(commit).current < CONFIG(hashsize)) { - STATE_SYNC(commit).state = COMMIT_STATE_MASTER; - /* give it another step as soon as possible */ - write_evfd(STATE_SYNC(commit).evfd); - return 1; - } - STATE_SYNC(commit).current = 0; - STATE_SYNC(commit).state = COMMIT_STATE_RELATED; - case COMMIT_STATE_RELATED: - STATE_SYNC(commit).current = - hashtable_iterate_limit(c->h, &tmp, - STATE_SYNC(commit).current, - CONFIG(general).commit_steps, - do_commit_related); - if (STATE_SYNC(commit).current < CONFIG(hashsize)) { - STATE_SYNC(commit).state = COMMIT_STATE_RELATED; - /* give it another step as soon as possible */ - write_evfd(STATE_SYNC(commit).evfd); - return 1; - } - /* calculate the time that commit has taken */ - gettimeofday(&commit_stop, NULL); - timersub(&commit_stop, &STATE_SYNC(commit).stats.start, &res); - - /* calculate new entries committed */ - commit_ok = c->stats.commit_ok - STATE_SYNC(commit).stats.ok; - commit_fail = - c->stats.commit_fail - STATE_SYNC(commit).stats.fail; - - /* log results */ - dlog(LOG_NOTICE, "Committed %u new entries", commit_ok); - - if (commit_fail) - dlog(LOG_NOTICE, "%u entries can't be " - "committed", commit_fail); - - dlog(LOG_NOTICE, "commit has taken %lu.%06lu seconds", - res.tv_sec, res.tv_usec); - - /* prepare the state machine for new commits */ - STATE_SYNC(commit).current = 0; - STATE_SYNC(commit).state = COMMIT_STATE_INACTIVE; - - /* Close the client socket now that we're done. */ - close(STATE_SYNC(commit).clientfd); - STATE_SYNC(commit).clientfd = -1; - } - return 1; -} - -static int do_flush(void *data, void *n) -{ - struct cache *c = data; - struct cache_object *obj = n; - - cache_del(c, obj); - cache_object_free(obj); - return 0; -} - -void cache_flush(struct cache *c) -{ - hashtable_iterate(c->h, c, do_flush); - c->stats.flush++; -} diff --git a/src/external_cache.c b/src/external_cache.c index 59c706a..073f309 100644 --- a/src/external_cache.c +++ b/src/external_cache.c @@ -28,9 +28,9 @@ static struct cache *external; static int external_cache_init(void) { - external = cache_create("external", + external = cache_create("external", CACHE_T_CT, STATE_SYNC(sync)->external_cache_flags, - NULL); + NULL, &cache_sync_external_ct_ops); if (external == NULL) { dlog(LOG_ERR, "can't allocate memory for the external cache"); return -1; diff --git a/src/internal_bypass.c b/src/internal_bypass.c index 1e1478f..8ecec34 100644 --- a/src/internal_bypass.c +++ b/src/internal_bypass.c @@ -1,6 +1,7 @@ /* - * (C) 2009 by Pablo Neira Ayuso - * + * (C) 2006-2011 by Pablo Neira Ayuso + * (C) 2011 by Vyatta Inc. + * * 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 @@ -16,17 +17,18 @@ #include "network.h" #include "origin.h" -static int _init(void) +static int internal_bypass_init(void) { return 0; } -static void _close(void) +static void internal_bypass_close(void) { } -static int dump_cb(enum nf_conntrack_msg_type type, - struct nf_conntrack *ct, void *data) +static int +internal_bypass_ct_dump_cb(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, void *data) { char buf[1024]; int size, *fd = data; @@ -44,7 +46,7 @@ static int dump_cb(enum nf_conntrack_msg_type type, return NFCT_CB_CONTINUE; } -static void dump(int fd, int type) +static void internal_bypass_ct_dump(int fd, int type) { struct nfct_handle *h; u_int32_t family = AF_UNSPEC; @@ -55,7 +57,7 @@ static void dump(int fd, int type) dlog(LOG_ERR, "can't allocate memory for the internal cache"); return; } - nfct_callback_register(h, NFCT_T_ALL, dump_cb, &fd); + nfct_callback_register(h, NFCT_T_ALL, internal_bypass_ct_dump_cb, &fd); ret = nfct_query(h, NFCT_Q_DUMP, &family); if (ret == -1) { dlog(LOG_ERR, "can't dump kernel table"); @@ -63,7 +65,7 @@ static void dump(int fd, int type) nfct_close(h); } -static void flush(void) +static void internal_bypass_ct_flush(void) { nl_flush_conntrack_table(STATE(flush)); } @@ -74,7 +76,7 @@ struct { uint32_t del; } internal_bypass_stats; -static void stats(int fd) +static void internal_bypass_ct_stats(int fd) { char buf[512]; int size; @@ -91,25 +93,24 @@ static void stats(int fd) } /* unused, INTERNAL_F_POPULATE is unset. No cache, nothing to populate. */ -static void populate(struct nf_conntrack *ct) +static void internal_bypass_ct_populate(struct nf_conntrack *ct) { } /* unused, INTERNAL_F_RESYNC is unset. */ -static void purge(void) +static void internal_bypass_ct_purge(void) { } /* unused, INTERNAL_F_RESYNC is unset. Nothing to resync, we have no cache. */ -static int resync(enum nf_conntrack_msg_type type, - struct nf_conntrack *ct, - void *data) +static int +internal_bypass_ct_resync(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, void *data) { return NFCT_CB_CONTINUE; } -static void -event_new_sync(struct nf_conntrack *ct, int origin) +static void internal_bypass_ct_event_new(struct nf_conntrack *ct, int origin) { struct nethdr *net; @@ -122,8 +123,7 @@ event_new_sync(struct nf_conntrack *ct, int origin) internal_bypass_stats.new++; } -static void -event_update_sync(struct nf_conntrack *ct, int origin) +static void internal_bypass_ct_event_upd(struct nf_conntrack *ct, int origin) { struct nethdr *net; @@ -136,8 +136,7 @@ event_update_sync(struct nf_conntrack *ct, int origin) internal_bypass_stats.upd++; } -static int -event_destroy_sync(struct nf_conntrack *ct, int origin) +static int internal_bypass_ct_event_del(struct nf_conntrack *ct, int origin) { struct nethdr *net; @@ -153,16 +152,18 @@ event_destroy_sync(struct nf_conntrack *ct, int origin) } struct internal_handler internal_bypass = { - .init = _init, - .close = _close, - .dump = dump, - .flush = flush, - .stats = stats, - .stats_ext = stats, - .populate = populate, - .purge = purge, - .resync = resync, - .new = event_new_sync, - .update = event_update_sync, - .destroy = event_destroy_sync, + .init = internal_bypass_init, + .close = internal_bypass_close, + .ct = { + .dump = internal_bypass_ct_dump, + .flush = internal_bypass_ct_flush, + .stats = internal_bypass_ct_stats, + .stats_ext = internal_bypass_ct_stats, + .populate = internal_bypass_ct_populate, + .purge = internal_bypass_ct_purge, + .resync = internal_bypass_ct_resync, + .new = internal_bypass_ct_event_new, + .upd = internal_bypass_ct_event_upd, + .del = internal_bypass_ct_event_del, + }, }; diff --git a/src/internal_cache.c b/src/internal_cache.c index e50e1db..7a698e6 100644 --- a/src/internal_cache.c +++ b/src/internal_cache.c @@ -1,6 +1,7 @@ /* - * (C) 2009 by Pablo Neira Ayuso - * + * (C) 2006-2011 by Pablo Neira Ayuso + * (C) 2011 by Vyatta Inc. + * * 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 @@ -19,46 +20,47 @@ static inline void sync_send(struct cache_object *obj, int query) STATE_SYNC(sync)->enqueue(obj, query); } -static int _init(void) +static int internal_cache_init(void) { - STATE(mode)->internal->data = - cache_create("internal", + STATE(mode)->internal->ct.data = + cache_create("internal", CACHE_T_CT, STATE_SYNC(sync)->internal_cache_flags, - STATE_SYNC(sync)->internal_cache_extra); + STATE_SYNC(sync)->internal_cache_extra, + &cache_sync_internal_ct_ops); - if (!STATE(mode)->internal->data) { + if (!STATE(mode)->internal->ct.data) { dlog(LOG_ERR, "can't allocate memory for the internal cache"); return -1; } return 0; } -static void _close(void) +static void internal_cache_close(void) { - cache_destroy(STATE(mode)->internal->data); + cache_destroy(STATE(mode)->internal->ct.data); } -static void dump(int fd, int type) +static void internal_cache_ct_dump(int fd, int type) { - cache_dump(STATE(mode)->internal->data, fd, type); + cache_dump(STATE(mode)->internal->ct.data, fd, type); } -static void flush(void) +static void internal_cache_ct_flush(void) { - cache_flush(STATE(mode)->internal->data); + cache_flush(STATE(mode)->internal->ct.data); } -static void stats(int fd) +static void internal_cache_ct_stats(int fd) { - cache_stats(STATE(mode)->internal->data, fd); + cache_stats(STATE(mode)->internal->ct.data, fd); } -static void stats_ext(int fd) +static void internal_cache_ct_stats_ext(int fd) { - cache_stats_extended(STATE(mode)->internal->data, fd); + cache_stats_extended(STATE(mode)->internal->ct.data, fd); } -static void populate(struct nf_conntrack *ct) +static void internal_cache_ct_populate(struct nf_conntrack *ct) { /* This is required by kernels < 2.6.20 */ nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES); @@ -67,15 +69,15 @@ static void populate(struct nf_conntrack *ct) nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); nfct_attr_unset(ct, ATTR_USE); - cache_update_force(STATE(mode)->internal->data, ct); + cache_update_force(STATE(mode)->internal->ct.data, ct); } -static int purge_step(void *data1, void *data2) +static int internal_cache_ct_purge_step(void *data1, void *data2) { struct cache_object *obj = data2; STATE(get_retval) = 0; - nl_get_conntrack(STATE(get), obj->ct); /* modifies STATE(get_reval) */ + nl_get_conntrack(STATE(get), obj->ptr); /* modifies STATE(get_reval) */ if (!STATE(get_retval)) { if (obj->status != C_OBJ_DEAD) { cache_object_set_status(obj, C_OBJ_DEAD); @@ -87,14 +89,15 @@ static int purge_step(void *data1, void *data2) return 0; } -static void purge(void) +static void internal_cache_ct_purge(void) { - cache_iterate(STATE(mode)->internal->data, NULL, purge_step); + cache_iterate(STATE(mode)->internal->ct.data, NULL, + internal_cache_ct_purge_step); } -static int resync(enum nf_conntrack_msg_type type, - struct nf_conntrack *ct, - void *data) +static int +internal_cache_ct_resync(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, void *data) { struct cache_object *obj; @@ -108,7 +111,7 @@ static int resync(enum nf_conntrack_msg_type type, nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); nfct_attr_unset(ct, ATTR_USE); - obj = cache_update_force(STATE(mode)->internal->data, ct); + obj = cache_update_force(STATE(mode)->internal->ct.data, ct); if (obj == NULL) return NFCT_CB_CONTINUE; @@ -123,8 +126,7 @@ static int resync(enum nf_conntrack_msg_type type, return NFCT_CB_CONTINUE; } -static void -event_new_sync(struct nf_conntrack *ct, int origin) +static void internal_cache_ct_event_new(struct nf_conntrack *ct, int origin) { struct cache_object *obj; int id; @@ -139,13 +141,13 @@ event_new_sync(struct nf_conntrack *ct, int origin) nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES); nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); - obj = cache_find(STATE(mode)->internal->data, ct, &id); + obj = cache_find(STATE(mode)->internal->ct.data, ct, &id); if (obj == NULL) { retry: - obj = cache_object_new(STATE(mode)->internal->data, ct); + obj = cache_object_new(STATE(mode)->internal->ct.data, ct); if (obj == NULL) return; - if (cache_add(STATE(mode)->internal->data, obj, id) == -1) { + if (cache_add(STATE(mode)->internal->ct.data, obj, id) == -1) { cache_object_free(obj); return; } @@ -155,14 +157,13 @@ retry: if (origin == CTD_ORIGIN_NOT_ME) sync_send(obj, NET_T_STATE_NEW); } else { - cache_del(STATE(mode)->internal->data, obj); + cache_del(STATE(mode)->internal->ct.data, obj); cache_object_free(obj); goto retry; } } -static void -event_update_sync(struct nf_conntrack *ct, int origin) +static void internal_cache_ct_event_upd(struct nf_conntrack *ct, int origin) { struct cache_object *obj; @@ -170,7 +171,7 @@ event_update_sync(struct nf_conntrack *ct, int origin) if (origin == CTD_ORIGIN_INJECT) return; - obj = cache_update_force(STATE(mode)->internal->data, ct); + obj = cache_update_force(STATE(mode)->internal->ct.data, ct); if (obj == NULL) return; @@ -178,8 +179,7 @@ event_update_sync(struct nf_conntrack *ct, int origin) sync_send(obj, NET_T_STATE_UPD); } -static int -event_destroy_sync(struct nf_conntrack *ct, int origin) +static int internal_cache_ct_event_del(struct nf_conntrack *ct, int origin) { struct cache_object *obj; int id; @@ -189,7 +189,7 @@ event_destroy_sync(struct nf_conntrack *ct, int origin) return 0; /* we don't synchronize events for objects that are not in the cache */ - obj = cache_find(STATE(mode)->internal->data, ct, &id); + obj = cache_find(STATE(mode)->internal->ct.data, ct, &id); if (obj == NULL) return 0; @@ -205,16 +205,18 @@ event_destroy_sync(struct nf_conntrack *ct, int origin) struct internal_handler internal_cache = { .flags = INTERNAL_F_POPULATE | INTERNAL_F_RESYNC, - .init = _init, - .close = _close, - .dump = dump, - .flush = flush, - .stats = stats, - .stats_ext = stats_ext, - .populate = populate, - .purge = purge, - .resync = resync, - .new = event_new_sync, - .update = event_update_sync, - .destroy = event_destroy_sync, + .init = internal_cache_init, + .close = internal_cache_close, + .ct = { + .dump = internal_cache_ct_dump, + .flush = internal_cache_ct_flush, + .stats = internal_cache_ct_stats, + .stats_ext = internal_cache_ct_stats_ext, + .populate = internal_cache_ct_populate, + .purge = internal_cache_ct_purge, + .resync = internal_cache_ct_resync, + .new = internal_cache_ct_event_new, + .upd = internal_cache_ct_event_upd, + .del = internal_cache_ct_event_del, + }, }; diff --git a/src/run.c b/src/run.c index 265a949..f8d3fad 100644 --- a/src/run.c +++ b/src/run.c @@ -1,6 +1,7 @@ /* - * (C) 2006-2009 by Pablo Neira Ayuso - * + * (C) 2006-2011 by Pablo Neira Ayuso + * (C) 2011 by Vyatta Inc. + * * 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 @@ -241,8 +242,8 @@ static void do_overrun_resync_alarm(struct alarm_block *a, void *data) static void do_polling_alarm(struct alarm_block *a, void *data) { - if (STATE(mode)->internal->purge) - STATE(mode)->internal->purge(); + if (STATE(mode)->internal->ct.purge) + STATE(mode)->internal->ct.purge(); nl_send_resync(STATE(resync)); add_alarm(&STATE(polling_alarm), CONFIG(poll_kernel_secs), 0); @@ -267,13 +268,13 @@ static int event_handler(const struct nlmsghdr *nlh, switch(type) { case NFCT_T_NEW: - STATE(mode)->internal->new(ct, origin_type); + STATE(mode)->internal->ct.new(ct, origin_type); break; case NFCT_T_UPDATE: - STATE(mode)->internal->update(ct, origin_type); + STATE(mode)->internal->ct.upd(ct, origin_type); break; case NFCT_T_DESTROY: - if (STATE(mode)->internal->destroy(ct, origin_type)) + if (STATE(mode)->internal->ct.del(ct, origin_type)) update_traffic_stats(ct); break; default: @@ -298,7 +299,7 @@ static int dump_handler(enum nf_conntrack_msg_type type, switch(type) { case NFCT_T_UPDATE: - STATE(mode)->internal->populate(ct); + STATE(mode)->internal->ct.populate(ct); break; default: STATE(stats).nl_dump_unknown_type++; @@ -363,7 +364,7 @@ init(void) } nfct_callback_register(STATE(resync), NFCT_T_ALL, - STATE(mode)->internal->resync, + STATE(mode)->internal->ct.resync, NULL); register_fd(nfct_fd(STATE(resync)), STATE(fds)); fcntl(nfct_fd(STATE(resync)), F_SETFL, O_NONBLOCK); @@ -537,8 +538,8 @@ static void run_events(struct timeval *next_alarm) /* we previously requested a resync due to buffer overrun. */ if (FD_ISSET(nfct_fd(STATE(resync)), &readfds)) { nfct_catch(STATE(resync)); - if (STATE(mode)->internal->purge) - STATE(mode)->internal->purge(); + if (STATE(mode)->internal->ct.purge) + STATE(mode)->internal->ct.purge(); } if (STATE(mode)->run) diff --git a/src/stats-mode.c b/src/stats-mode.c index 0403ce2..c7a81e3 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -1,6 +1,7 @@ /* - * (C) 2006-2007 by Pablo Neira Ayuso - * + * (C) 2006-2011 by Pablo Neira Ayuso + * (C) 2011 by Vyatta Inc. + * * 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 @@ -37,7 +38,9 @@ static int init_stats(void) } memset(state.stats, 0, sizeof(struct ct_stats_state)); - STATE_STATS(cache) = cache_create("stats", NO_FEATURES, NULL); + STATE_STATS(cache) = cache_create("stats", CACHE_T_CT, + NO_FEATURES, NULL, + &cache_stats_ct_ops); if (!STATE_STATS(cache)) { dlog(LOG_ERR, "can't allocate memory for the " "external cache"); @@ -88,7 +91,7 @@ static int local_handler_stats(int fd, int type, void *data) return ret; } -static void populate_stats(struct nf_conntrack *ct) +static void stats_populate(struct nf_conntrack *ct) { nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES); nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS); @@ -100,7 +103,7 @@ static void populate_stats(struct nf_conntrack *ct) cache_update_force(STATE_STATS(cache), ct); } -static int resync_stats(enum nf_conntrack_msg_type type, +static int stats_resync(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data) { @@ -125,23 +128,22 @@ static int purge_step(void *data1, void *data2) struct cache_object *obj = data2; STATE(get_retval) = 0; - nl_get_conntrack(STATE(get), obj->ct); /* modifies STATE(get_retval) */ + nl_get_conntrack(STATE(get), obj->ptr); /* modifies STATE(get_retval) */ if (!STATE(get_retval)) { cache_del(STATE_STATS(cache), obj); - dlog_ct(STATE(stats_log), obj->ct, NFCT_O_PLAIN); + dlog_ct(STATE(stats_log), obj->ptr, NFCT_O_PLAIN); cache_object_free(obj); } return 0; } -static void purge_stats(void) +static void stats_purge(void) { cache_iterate(STATE_STATS(cache), NULL, purge_step); } -static void -event_new_stats(struct nf_conntrack *ct, int origin) +static void stats_event_new(struct nf_conntrack *ct, int origin) { int id; struct cache_object *obj; @@ -162,15 +164,13 @@ event_new_stats(struct nf_conntrack *ct, int origin) return; } -static void -event_update_stats(struct nf_conntrack *ct, int origin) +static void stats_event_upd(struct nf_conntrack *ct, int origin) { nfct_attr_unset(ct, ATTR_TIMEOUT); cache_update_force(STATE_STATS(cache), ct); } -static int -event_destroy_stats(struct nf_conntrack *ct, int origin) +static int stats_event_del(struct nf_conntrack *ct, int origin) { int id; struct cache_object *obj; @@ -189,12 +189,14 @@ event_destroy_stats(struct nf_conntrack *ct, int origin) static struct internal_handler internal_cache_stats = { .flags = INTERNAL_F_POPULATE | INTERNAL_F_RESYNC, - .populate = populate_stats, - .resync = resync_stats, - .purge = purge_stats, - .new = event_new_stats, - .update = event_update_stats, - .destroy = event_destroy_stats + .ct = { + .populate = stats_populate, + .resync = stats_resync, + .purge = stats_purge, + .new = stats_event_new, + .upd = stats_event_upd, + .del = stats_event_del, + }, }; struct ct_mode stats_mode = { diff --git a/src/sync-alarm.c b/src/sync-alarm.c index b555dd5..8d6b34d 100644 --- a/src/sync-alarm.c +++ b/src/sync-alarm.c @@ -1,6 +1,7 @@ /* - * (C) 2006-2007 by Pablo Neira Ayuso - * + * (C) 2006-2011 by Pablo Neira Ayuso + * (C) 2011 by Vyatta Inc. + * * 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 @@ -110,7 +111,7 @@ static int alarm_recv(const struct nethdr *net) static void alarm_enqueue(struct cache_object *obj, int query) { struct cache_alarm *ca = - cache_get_extra(STATE(mode)->internal->data, obj); + cache_get_extra(STATE(mode)->internal->ct.data, obj); if (queue_add(STATE_SYNC(tx_queue), &ca->qnode) > 0) cache_object_get(obj); } @@ -135,9 +136,9 @@ static int tx_queue_xmit(struct queue_node *n, const void *data) int type; ca = (struct cache_alarm *)n; - obj = cache_data_get_object(STATE(mode)->internal->data, ca); + obj = cache_data_get_object(STATE(mode)->internal->ct.data, ca); type = object_status_to_network_type(obj->status); - net = BUILD_NETMSG(obj->ct, type); + net = obj->cache->ops->build_msg(obj, type); multichannel_send(STATE_SYNC(channel), net); cache_object_put(obj); break; diff --git a/src/sync-ftfw.c b/src/sync-ftfw.c index 581b5ca..55eda0b 100644 --- a/src/sync-ftfw.c +++ b/src/sync-ftfw.c @@ -1,6 +1,7 @@ /* - * (C) 2006-2008 by Pablo Neira Ayuso - * + * (C) 2006-2011 by Pablo Neira Ayuso + * (C) 2011 by Vyatta Inc. + * * 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 @@ -169,7 +170,7 @@ static int do_cache_to_tx(void *data1, void *data2) { struct cache_object *obj = data2; struct cache_ftfw *cn = - cache_get_extra(STATE(mode)->internal->data, obj); + cache_get_extra(STATE(mode)->internal->ct.data, obj); if (queue_in(rs_queue, &cn->qnode)) { queue_del(&cn->qnode); @@ -227,7 +228,7 @@ static int ftfw_local(int fd, int type, void *data) break; case SEND_BULK: dlog(LOG_NOTICE, "sending bulk update"); - cache_iterate(STATE(mode)->internal->data, + cache_iterate(STATE(mode)->internal->ct.data, NULL, do_cache_to_tx); break; case STATS_RSQUEUE: @@ -307,7 +308,7 @@ static int rs_queue_empty(struct queue_node *n, const void *data) cn = (struct cache_ftfw *) n; if (h == NULL) { queue_del(n); - obj = cache_data_get_object(STATE(mode)->internal->data, cn); + obj = cache_data_get_object(STATE(mode)->internal->ct.data, cn); cache_object_put(obj); return 0; } @@ -318,7 +319,7 @@ static int rs_queue_empty(struct queue_node *n, const void *data) dp("queue: deleting from queue (seq=%u)\n", cn->seq); queue_del(n); - obj = cache_data_get_object(STATE(mode)->internal->data, cn); + obj = cache_data_get_object(STATE(mode)->internal->ct.data, cn); cache_object_put(obj); break; } @@ -351,7 +352,7 @@ static int digest_msg(const struct nethdr *net) } else if (IS_RESYNC(net)) { dp("RESYNC ALL\n"); - cache_iterate(STATE(mode)->internal->data, NULL, do_cache_to_tx); + cache_iterate(STATE(mode)->internal->ct.data, NULL, do_cache_to_tx); return MSG_CTL; } else if (IS_ALIVE(net)) @@ -468,7 +469,7 @@ static void rs_queue_purge_full(void) struct cache_object *obj; cn = (struct cache_ftfw *)n; - obj = cache_data_get_object(STATE(mode)->internal->data, cn); + obj = cache_data_get_object(STATE(mode)->internal->ct.data, cn); cache_object_put(obj); break; } @@ -516,9 +517,9 @@ static int tx_queue_xmit(struct queue_node *n, const void *data) struct nethdr *net; cn = (struct cache_ftfw *)n; - obj = cache_data_get_object(STATE(mode)->internal->data, cn); + obj = cache_data_get_object(STATE(mode)->internal->ct.data, cn); type = object_status_to_network_type(obj->status); - net = BUILD_NETMSG(obj->ct, type); + net = obj->cache->ops->build_msg(obj, type); nethdr_set_hello(net); dp("tx_list sq: %u fl:%u len:%u\n", @@ -551,7 +552,7 @@ static void ftfw_xmit(void) static void ftfw_enqueue(struct cache_object *obj, int type) { struct cache_ftfw *cn = - cache_get_extra(STATE(mode)->internal->data, obj); + cache_get_extra(STATE(mode)->internal->ct.data, obj); if (queue_in(rs_queue, &cn->qnode)) { queue_del(&cn->qnode); queue_add(STATE_SYNC(tx_queue), &cn->qnode); diff --git a/src/sync-mode.c b/src/sync-mode.c index 5351110..34d9706 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -1,6 +1,7 @@ /* - * (C) 2006-2007 by Pablo Neira Ayuso - * + * (C) 2006-2011 by Pablo Neira Ayuso + * (C) 2011 by Vyatta Inc. + * * 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 @@ -251,7 +252,7 @@ static void do_reset_cache_alarm(struct alarm_block *a, void *data) exit(EXIT_SUCCESS); } /* this is not required if events don't get lost */ - STATE(mode)->internal->flush(); + STATE(mode)->internal->ct.flush(); } static int init_sync(void) @@ -471,7 +472,7 @@ static int local_handler_sync(int fd, int type, void *data) switch(type) { case DUMP_INTERNAL: if (fork_process_new(CTD_PROC_ANY, 0, NULL, NULL) == 0) { - STATE(mode)->internal->dump(fd, NFCT_O_PLAIN); + STATE(mode)->internal->ct.dump(fd, NFCT_O_PLAIN); exit(EXIT_SUCCESS); } break; @@ -483,7 +484,7 @@ static int local_handler_sync(int fd, int type, void *data) break; case DUMP_INT_XML: if (fork_process_new(CTD_PROC_ANY, 0, NULL, NULL) == 0) { - STATE(mode)->internal->dump(fd, NFCT_O_XML); + STATE(mode)->internal->ct.dump(fd, NFCT_O_XML); exit(EXIT_SUCCESS); } break; @@ -512,14 +513,14 @@ static int local_handler_sync(int fd, int type, void *data) /* inmediate flush, remove pending flush scheduled if any */ del_alarm(&STATE_SYNC(reset_cache_alarm)); dlog(LOG_NOTICE, "flushing caches"); - STATE(mode)->internal->flush(); + STATE(mode)->internal->ct.flush(); STATE_SYNC(external)->flush(); break; case FLUSH_INT_CACHE: /* inmediate flush, remove pending flush scheduled if any */ del_alarm(&STATE_SYNC(reset_cache_alarm)); dlog(LOG_NOTICE, "flushing internal cache"); - STATE(mode)->internal->flush(); + STATE(mode)->internal->ct.flush(); break; case FLUSH_EXT_CACHE: dlog(LOG_NOTICE, "flushing external cache"); @@ -529,7 +530,7 @@ static int local_handler_sync(int fd, int type, void *data) killer(0); break; case STATS: - STATE(mode)->internal->stats(fd); + STATE(mode)->internal->ct.stats(fd); STATE_SYNC(external)->stats(fd); dump_traffic_stats(fd); multichannel_stats(STATE_SYNC(channel), fd); @@ -540,7 +541,7 @@ static int local_handler_sync(int fd, int type, void *data) multichannel_stats(STATE_SYNC(channel), fd); break; case STATS_CACHE: - STATE(mode)->internal->stats_ext(fd); + STATE(mode)->internal->ct.stats_ext(fd); STATE_SYNC(external)->stats_ext(fd); break; case STATS_LINK: diff --git a/src/sync-notrack.c b/src/sync-notrack.c index 06af58b..e25cfd8 100644 --- a/src/sync-notrack.c +++ b/src/sync-notrack.c @@ -76,7 +76,7 @@ static int do_cache_to_tx(void *data1, void *data2) { struct cache_object *obj = data2; struct cache_notrack *cn = - cache_get_extra(STATE(mode)->internal->data, obj); + cache_get_extra(STATE(mode)->internal->ct.data, obj); if (queue_add(STATE_SYNC(tx_queue), &cn->qnode) > 0) cache_object_get(obj); return 0; @@ -127,7 +127,7 @@ static int notrack_local(int fd, int type, void *data) if (CONFIG(sync).internal_cache_disable) { kernel_resync(); } else { - cache_iterate(STATE(mode)->internal->data, + cache_iterate(STATE(mode)->internal->ct.data, NULL, do_cache_to_tx); } break; @@ -148,7 +148,7 @@ static int digest_msg(const struct nethdr *net) if (CONFIG(sync).internal_cache_disable) { kernel_resync(); } else { - cache_iterate(STATE(mode)->internal->data, + cache_iterate(STATE(mode)->internal->ct.data, NULL, do_cache_to_tx); } return MSG_CTL; @@ -197,9 +197,9 @@ static int tx_queue_xmit(struct queue_node *n, const void *data2) struct nethdr *net; cn = (struct cache_ftfw *)n; - obj = cache_data_get_object(STATE(mode)->internal->data, cn); + obj = cache_data_get_object(STATE(mode)->internal->ct.data, cn); type = object_status_to_network_type(obj->status);; - net = BUILD_NETMSG(obj->ct, type); + net = obj->cache->ops->build_msg(obj, type); multichannel_send(STATE_SYNC(channel), net); queue_del(n); @@ -219,7 +219,7 @@ static void notrack_xmit(void) static void notrack_enqueue(struct cache_object *obj, int query) { struct cache_notrack *cn = - cache_get_extra(STATE(mode)->internal->data, obj); + cache_get_extra(STATE(mode)->internal->ct.data, obj); if (queue_add(STATE_SYNC(tx_queue), &cn->qnode) > 0) cache_object_get(obj); } -- cgit v1.2.3 From 598e465087365db1fa36b67aa53d291e400ec5b1 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 27 Oct 2011 12:18:34 +0200 Subject: conntrackd: generalize local handler actions This patch prepares the introduction of actions with the expectation table. Mostly renamings. Signed-off-by: Pablo Neira Ayuso --- include/conntrackd.h | 46 +++++++++++++++++++++++----------------------- src/main.c | 24 ++++++++++++------------ src/run.c | 4 ++-- src/stats-mode.c | 8 ++++---- src/sync-mode.c | 16 ++++++++-------- 5 files changed, 49 insertions(+), 49 deletions(-) (limited to 'src/stats-mode.c') diff --git a/include/conntrackd.h b/include/conntrackd.h index b35c95d..697d3d7 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -14,29 +14,29 @@ #include /* UNIX facilities */ -#define FLUSH_MASTER 0 /* flush kernel conntrack table */ -#define RESYNC_MASTER 1 /* resync with kernel conntrack table */ -#define DUMP_INTERNAL 16 /* dump internal cache */ -#define DUMP_EXTERNAL 17 /* dump external cache */ -#define COMMIT 18 /* commit external cache */ -#define FLUSH_CACHE 19 /* flush cache */ -#define KILL 20 /* kill conntrackd */ -#define STATS 21 /* dump statistics */ -#define SEND_BULK 22 /* send a bulk */ -#define REQUEST_DUMP 23 /* request dump */ -#define DUMP_INT_XML 24 /* dump internal cache in XML */ -#define DUMP_EXT_XML 25 /* dump external cache in XML */ -#define RESET_TIMERS 26 /* reset kernel timers */ -#define DEBUG_INFO 27 /* unused */ -#define STATS_NETWORK 28 /* extended network stats */ -#define STATS_CACHE 29 /* extended cache stats */ -#define STATS_RUNTIME 30 /* extended runtime stats */ -#define STATS_LINK 31 /* dedicated link stats */ -#define STATS_RSQUEUE 32 /* resend queue stats */ -#define FLUSH_INT_CACHE 33 /* flush internal cache */ -#define FLUSH_EXT_CACHE 34 /* flush external cache */ -#define STATS_PROCESS 35 /* child process stats */ -#define STATS_QUEUE 36 /* queue stats */ +#define CT_FLUSH_MASTER 0 /* flush kernel conntrack table */ +#define CT_RESYNC_MASTER 1 /* resync with kernel ct table */ +#define CT_DUMP_INTERNAL 16 /* dump internal cache */ +#define CT_DUMP_EXTERNAL 17 /* dump external cache */ +#define CT_COMMIT 18 /* commit external cache */ +#define CT_FLUSH_CACHE 19 /* flush cache */ +#define KILL 20 /* kill conntrackd */ +#define STATS 21 /* dump statistics */ +#define SEND_BULK 22 /* send a bulk */ +#define REQUEST_DUMP 23 /* request dump */ +#define CT_DUMP_INT_XML 24 /* dump internal cache in XML */ +#define CT_DUMP_EXT_XML 25 /* dump external cache in XML */ +#define RESET_TIMERS 26 /* reset kernel timers */ +#define DEBUG_INFO 27 /* unused */ +#define STATS_NETWORK 28 /* extended network stats */ +#define STATS_CACHE 29 /* extended cache stats */ +#define STATS_RUNTIME 30 /* extended runtime stats */ +#define STATS_LINK 31 /* dedicated link stats */ +#define STATS_RSQUEUE 32 /* resend queue stats */ +#define CT_FLUSH_INT_CACHE 33 /* flush internal cache */ +#define CT_FLUSH_EXT_CACHE 34 /* flush external cache */ +#define STATS_PROCESS 35 /* child process stats */ +#define STATS_QUEUE 36 /* queue stats */ #define DEFAULT_CONFIGFILE "/etc/conntrackd/conntrackd.conf" #define DEFAULT_LOCKFILE "/var/lock/conntrackd.lock" diff --git a/src/main.c b/src/main.c index 4ead2ea..ebfc8b9 100644 --- a/src/main.c +++ b/src/main.c @@ -115,15 +115,15 @@ int main(int argc, char *argv[]) break; case 'c': set_operation_mode(&type, REQUEST, argv); - action = COMMIT; + action = CT_COMMIT; break; case 'i': set_operation_mode(&type, REQUEST, argv); - action = DUMP_INTERNAL; + action = CT_DUMP_INTERNAL; break; case 'e': set_operation_mode(&type, REQUEST, argv); - action = DUMP_EXTERNAL; + action = CT_DUMP_EXTERNAL; break; case 'C': if (++i < argc) { @@ -142,18 +142,18 @@ int main(int argc, char *argv[]) break; case 'F': set_operation_mode(&type, REQUEST, argv); - action = FLUSH_MASTER; + action = CT_FLUSH_MASTER; break; case 'f': set_operation_mode(&type, REQUEST, argv); if (i+1 < argc && argv[i+1][0] != '-') { if (strncmp(argv[i+1], "internal", strlen(argv[i+1])) == 0) { - action = FLUSH_INT_CACHE; + action = CT_FLUSH_INT_CACHE; i++; } else if (strncmp(argv[i+1], "external", strlen(argv[i+1])) == 0) { - action = FLUSH_EXT_CACHE; + action = CT_FLUSH_EXT_CACHE; i++; } else { fprintf(stderr, "ERROR: unknown " @@ -164,12 +164,12 @@ int main(int argc, char *argv[]) } } else { /* default to general flushing */ - action = FLUSH_CACHE; + action = CT_FLUSH_CACHE; } break; case 'R': set_operation_mode(&type, REQUEST, argv); - action = RESYNC_MASTER; + action = CT_RESYNC_MASTER; break; case 'B': set_operation_mode(&type, REQUEST, argv); @@ -243,10 +243,10 @@ int main(int argc, char *argv[]) action = REQUEST_DUMP; break; case 'x': - if (action == DUMP_INTERNAL) - action = DUMP_INT_XML; - else if (action == DUMP_EXTERNAL) - action = DUMP_EXT_XML; + if (action == CT_DUMP_INTERNAL) + action = CT_DUMP_INT_XML; + else if (action == CT_DUMP_EXTERNAL) + action = CT_DUMP_EXT_XML; else { show_usage(argv[0]); fprintf(stderr, "Error: Invalid parameters\n"); diff --git a/src/run.c b/src/run.c index f8d3fad..c21db2e 100644 --- a/src/run.c +++ b/src/run.c @@ -197,7 +197,7 @@ static int local_handler(int fd, void *data) return LOCAL_RET_OK; } switch(type) { - case FLUSH_MASTER: + case CT_FLUSH_MASTER: STATE(stats).nl_kernel_table_flush++; dlog(LOG_NOTICE, "flushing kernel conntrack table"); @@ -209,7 +209,7 @@ static int local_handler(int fd, void *data) exit(EXIT_SUCCESS); } break; - case RESYNC_MASTER: + case CT_RESYNC_MASTER: if (STATE(mode)->internal->flags & INTERNAL_F_POPULATE) { STATE(stats).nl_kernel_table_resync++; dlog(LOG_NOTICE, "resync with master table"); diff --git a/src/stats-mode.c b/src/stats-mode.c index c7a81e3..b768033 100644 --- a/src/stats-mode.c +++ b/src/stats-mode.c @@ -62,14 +62,14 @@ static int local_handler_stats(int fd, int type, void *data) int ret = LOCAL_RET_OK; switch(type) { - case DUMP_INTERNAL: + case CT_DUMP_INTERNAL: cache_dump(STATE_STATS(cache), fd, NFCT_O_PLAIN); break; - case DUMP_INT_XML: + case CT_DUMP_INT_XML: cache_dump(STATE_STATS(cache), fd, NFCT_O_XML); break; - case FLUSH_CACHE: - case FLUSH_INT_CACHE: + case CT_FLUSH_CACHE: + case CT_FLUSH_INT_CACHE: dlog(LOG_NOTICE, "flushing caches"); cache_flush(STATE_STATS(cache)); break; diff --git a/src/sync-mode.c b/src/sync-mode.c index 17533f8..7e6fa31 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -486,31 +486,31 @@ static int local_handler_sync(int fd, int type, void *data) int ret = LOCAL_RET_OK; switch(type) { - case DUMP_INTERNAL: + case CT_DUMP_INTERNAL: if (fork_process_new(CTD_PROC_ANY, 0, NULL, NULL) == 0) { STATE(mode)->internal->ct.dump(fd, NFCT_O_PLAIN); exit(EXIT_SUCCESS); } break; - case DUMP_EXTERNAL: + case CT_DUMP_EXTERNAL: if (fork_process_new(CTD_PROC_ANY, 0, NULL, NULL) == 0) { STATE_SYNC(external)->ct.dump(fd, NFCT_O_PLAIN); exit(EXIT_SUCCESS); } break; - case DUMP_INT_XML: + case CT_DUMP_INT_XML: if (fork_process_new(CTD_PROC_ANY, 0, NULL, NULL) == 0) { STATE(mode)->internal->ct.dump(fd, NFCT_O_XML); exit(EXIT_SUCCESS); } break; - case DUMP_EXT_XML: + case CT_DUMP_EXT_XML: if (fork_process_new(CTD_PROC_ANY, 0, NULL, NULL) == 0) { STATE_SYNC(external)->ct.dump(fd, NFCT_O_XML); exit(EXIT_SUCCESS); } break; - case COMMIT: + case CT_COMMIT: /* delete the reset alarm if any before committing */ del_alarm(&STATE_SYNC(reset_cache_alarm)); @@ -525,20 +525,20 @@ static int local_handler_sync(int fd, int type, void *data) CONFIG(purge_timeout), 0); } break; - case FLUSH_CACHE: + case CT_FLUSH_CACHE: /* inmediate flush, remove pending flush scheduled if any */ del_alarm(&STATE_SYNC(reset_cache_alarm)); dlog(LOG_NOTICE, "flushing caches"); STATE(mode)->internal->ct.flush(); STATE_SYNC(external)->ct.flush(); break; - case FLUSH_INT_CACHE: + case CT_FLUSH_INT_CACHE: /* inmediate flush, remove pending flush scheduled if any */ del_alarm(&STATE_SYNC(reset_cache_alarm)); dlog(LOG_NOTICE, "flushing internal cache"); STATE(mode)->internal->ct.flush(); break; - case FLUSH_EXT_CACHE: + case CT_FLUSH_EXT_CACHE: dlog(LOG_NOTICE, "flushing external cache"); STATE_SYNC(external)->ct.flush(); break; -- cgit v1.2.3