From d894e26211f38db37015850afab6b7331edeecdb Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=pablo/emailAddress=pablo@netfilter.org" Date: Sun, 1 May 2005 23:19:42 +0000 Subject: o Created changelog file o Deleted libctnetlink.h and libnfnetlink.h from the include/ dir. o Added support for version (-V) and help (-h) o Added event mask based support o Added GPLv2 headers o Use fprintf instead of printf o Defined print_tuple and print_proto output interfaces o ctnl_[get|del]_conntrack handles return value from kernel via msgerr o Added support for conntrack table flushing o Added test case file (test.sh) o Improve dump output o Autoconf stuff for conntrack + some pablo's modifications. o Fixed packet counters formatting (use %llu instead of %lu) --- Makefile.am | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 Makefile.am (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..888d53e --- /dev/null +++ b/Makefile.am @@ -0,0 +1,13 @@ +# not a GNU package. You can remove this line, if +# have all needed files, that a GNU package needs +AUTOMAKE_OPTIONS = foreign 1.4 + +INCLUDES = $(all_includes) -I$(top_srcdir)/include -I${KERNELDIR} +SUBDIRS = src extensions +DIST_SUBDIRS = include src extensions +LINKOPTS = -ldl -lnfnetlink -lctnetlink +AM_CFLAGS = -g + +$(OBJECTS): libtool +libtool: $(LIBTOOL_DEPS) + $(SHELL) ./config.status --recheck -- cgit v1.2.3 From 7a60a4748220105e592c583ef0860d51e540a2c6 Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=pablo/emailAddress=pablo@netfilter.org" Date: Mon, 8 Aug 2005 11:38:55 +0000 Subject: Resync to current libnfnetlink_conntrack and 2.6.14 tree --- Makefile.am | 2 +- config.h.in | 7 ++-- configure.in | 2 +- extensions/libct_proto_sctp.c | 2 +- extensions/libct_proto_tcp.c | 2 +- extensions/libct_proto_udp.c | 2 +- src/conntrack.c | 10 +++--- src/libct.c | 79 +++++++++++++++++++------------------------ 8 files changed, 47 insertions(+), 59 deletions(-) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 888d53e..b114b00 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,7 +5,7 @@ AUTOMAKE_OPTIONS = foreign 1.4 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I${KERNELDIR} SUBDIRS = src extensions DIST_SUBDIRS = include src extensions -LINKOPTS = -ldl -lnfnetlink -lctnetlink +LINKOPTS = -ldl -lnfnetlink -lnfnetlink_conntrack AM_CFLAGS = -g $(OBJECTS): libtool diff --git a/config.h.in b/config.h.in index 3921abd..9045dbb 100644 --- a/config.h.in +++ b/config.h.in @@ -6,15 +6,16 @@ /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H -/* Define to 1 if you have the `ctnetlink' library (-lctnetlink). */ -#undef HAVE_LIBCTNETLINK - /* Define to 1 if you have the `dl' library (-ldl). */ #undef HAVE_LIBDL /* Define to 1 if you have the `nfnetlink' library (-lnfnetlink). */ #undef HAVE_LIBNFNETLINK +/* Define to 1 if you have the `nfnetlink_conntrack' library + (-lnfnetlink_conntrack). */ +#undef HAVE_LIBNFNETLINK_CONNTRACK + /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H diff --git a/configure.in b/configure.in index efdacf1..8956e34 100644 --- a/configure.in +++ b/configure.in @@ -22,7 +22,7 @@ dnl AC_CHECK_LIB([c], [main]) AC_CHECK_LIB([dl], [dlopen]) AC_CHECK_LIB([nfnetlink], [nfnl_listen]) -AC_CHECK_LIB([ctnetlink], [ctnl_register_handler] ,,,[-lnfnetlink]) +AC_CHECK_LIB([nfnetlink_conntrack], [ctnl_register_handler] ,,,[-lnfnetlink]) # Checks for header files. dnl AC_HEADER_STDC diff --git a/extensions/libct_proto_sctp.c b/extensions/libct_proto_sctp.c index b519ff1..4dbdf27 100644 --- a/extensions/libct_proto_sctp.c +++ b/extensions/libct_proto_sctp.c @@ -14,7 +14,7 @@ #include /* For htons */ #include #include "libct_proto.h" -#include "libctnetlink.h" +#include static struct option opts[] = { {"orig-port-src", 1, 0, '1'}, diff --git a/extensions/libct_proto_tcp.c b/extensions/libct_proto_tcp.c index 65f0fb6..323e4ec 100644 --- a/extensions/libct_proto_tcp.c +++ b/extensions/libct_proto_tcp.c @@ -14,7 +14,7 @@ #include /* For htons */ #include #include "libct_proto.h" -#include "libctnetlink.h" +#include static struct option opts[] = { {"orig-port-src", 1, 0, '1'}, diff --git a/extensions/libct_proto_udp.c b/extensions/libct_proto_udp.c index 706f113..8a9f0cf 100644 --- a/extensions/libct_proto_udp.c +++ b/extensions/libct_proto_udp.c @@ -13,7 +13,7 @@ #include /* For htons */ #include #include "libct_proto.h" -#include "libctnetlink.h" +#include static struct option opts[] = { {"orig-port-src", 1, 0, '1'}, diff --git a/src/conntrack.c b/src/conntrack.c index ccfb71a..22c6115 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -880,13 +880,11 @@ int main(int argc, char *argv[]) case EXP_CREATE: if (options & CT_OPT_ORIG) res = create_expectation(&orig, - CTA_TUPLE_ORIG, &exptuple, &mask, timeout); else if (options & CT_OPT_REPL) res = create_expectation(&reply, - CTA_TUPLE_REPLY, &exptuple, &mask, timeout); @@ -917,16 +915,16 @@ int main(int argc, char *argv[]) case EXP_DELETE: if (options & CT_OPT_ORIG) - res = delete_expectation(&orig, CTA_TUPLE_ORIG); + res = delete_expectation(&orig); else if (options & CT_OPT_REPL) - res = delete_expectation(&reply, CTA_TUPLE_REPLY); + res = delete_expectation(&reply); break; case CT_GET: if (options & CT_OPT_ORIG) - res = get_conntrack(&orig, CTA_TUPLE_ORIG, id); + res = get_conntrack(&orig, id); else if (options & CT_OPT_REPL) - res = get_conntrack(&reply, CTA_TUPLE_REPLY, id); + res = get_conntrack(&reply, id); break; case EXP_GET: diff --git a/src/libct.c b/src/libct.c index cf46b99..e03c02a 100644 --- a/src/libct.c +++ b/src/libct.c @@ -162,7 +162,7 @@ static int handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void *arg) parse_tuple(attr, &ct.tuple[CTNL_DIR_REPLY]); break; case CTA_STATUS: - ct.status = ntohl(*(unsigned int *)NFA_DATA(attr)); + ct.status = *(unsigned int *)NFA_DATA(attr); flags |= STATUS; break; case CTA_PROTOINFO: @@ -268,25 +268,6 @@ static int event_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, return handler(sock, nlh, arg); } -void parse_expect(struct nfattr *attr, struct ctnl_tuple *tuple, - struct ctnl_tuple *mask, unsigned long *timeout, - u_int32_t *id) -{ - struct nfattr *tb[CTA_EXPECT_MAX]; - - memset(tb, 0, CTA_EXPECT_MAX*sizeof(struct nfattr *)); - - nfnl_parse_nested(tb, CTA_EXPECT_MAX, attr); - if (tb[CTA_EXPECT_TUPLE-1]) - parse_tuple(tb[CTA_EXPECT_TUPLE-1], tuple); - if (tb[CTA_EXPECT_MASK-1]) - parse_tuple(tb[CTA_EXPECT_MASK-1], mask); - if (tb[CTA_EXPECT_TIMEOUT-1]) - *timeout = htonl(*(unsigned long *)NFA_DATA(tb[CTA_EXPECT_TIMEOUT-1])); - if (tb[CTA_EXPECT_ID-1]) - *id = htonl(*(u_int32_t *)NFA_DATA(tb[CTA_EXPECT_ID-1])); -} - static int expect_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void *arg) { struct nfgenmsg *nfmsg; @@ -310,9 +291,19 @@ static int expect_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void * while (NFA_OK(attr, attrlen)) { switch(attr->nfa_type) { - case CTA_EXPECT: - parse_expect(attr, &tuple, &mask, &timeout, - &id); + + case CTA_EXPECT_TUPLE: + parse_tuple(attr, &tuple); + break; + case CTA_EXPECT_MASK: + parse_tuple(attr, &mask); + break; + case CTA_EXPECT_TIMEOUT: + timeout = htonl(*(unsigned long *) + NFA_DATA(attr)); + break; + case CTA_EXPECT_ID: + id = htonl(*(u_int32_t *)NFA_DATA(attr)); break; } attr = NFA_NEXT(attr, attrlen); @@ -348,12 +339,12 @@ int create_conntrack(struct ctnl_tuple *orig, ct.tuple[CTNL_DIR_ORIGINAL] = *orig; ct.tuple[CTNL_DIR_REPLY] = *reply; ct.timeout = htonl(timeout); - ct.status = htonl(status); + ct.status = status; ct.protoinfo = *proto; if (range) ct.nat = *range; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) return ret; ret = ctnl_new_conntrack(&cth, &ct); @@ -376,10 +367,10 @@ int update_conntrack(struct ctnl_tuple *orig, ct.tuple[CTNL_DIR_ORIGINAL] = *orig; ct.tuple[CTNL_DIR_REPLY] = *reply; ct.timeout = htonl(timeout); - ct.status = htonl(status); + ct.status = status; ct.protoinfo = *proto; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) return ret; ret = ctnl_upd_conntrack(&cth, &ct); @@ -393,7 +384,7 @@ int delete_conntrack(struct ctnl_tuple *tuple, int dir) { int ret; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) return ret; ret = ctnl_del_conntrack(&cth, tuple, dir); @@ -411,7 +402,7 @@ int get_conntrack(struct ctnl_tuple *tuple, int dir) }; int ret; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) return ret; ctnl_register_handler(&cth, &h); @@ -430,7 +421,7 @@ int dump_conntrack_table(int zero) .handler = handler }; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) return ret; ctnl_register_handler(&cth, &h); @@ -463,7 +454,7 @@ int event_conntrack(unsigned int event_mask) }; int ret; - if ((ret = ctnl_open(&cth, event_mask)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, event_mask)) < 0) return ret; signal(SIGINT, event_sighandler); @@ -527,7 +518,7 @@ int dump_expect_list() }; int ret; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) return ret; ctnl_register_handler(&cth, &h); @@ -542,7 +533,7 @@ int flush_conntrack() { int ret; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) return ret; ret = ctnl_flush_conntrack(&cth); @@ -551,8 +542,7 @@ int flush_conntrack() return ret; } -int get_expect(struct ctnl_tuple *tuple, - enum ctattr_type t) +int get_expect(struct ctnl_tuple *tuple) { struct ctnl_msg_handler h = { .type = IPCTNL_MSG_EXP_NEW, @@ -560,43 +550,42 @@ int get_expect(struct ctnl_tuple *tuple, }; int ret; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) return 0; ctnl_register_handler(&cth, &h); - ret = ctnl_get_expect(&cth, tuple, t); + ret = ctnl_get_expect(&cth, tuple); ctnl_close(&cth); return ret; } int create_expectation(struct ctnl_tuple *tuple, - enum ctattr_type t, struct ctnl_tuple *exptuple, struct ctnl_tuple *mask, unsigned long timeout) { int ret; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) return ret; - ret = ctnl_new_expect(&cth, tuple, t, exptuple, mask, timeout); + ret = ctnl_new_expect(&cth, tuple, exptuple, mask, timeout); ctnl_close(&cth); return ret; } -int delete_expectation(struct ctnl_tuple *tuple, enum ctattr_type t) +int delete_expectation(struct ctnl_tuple *tuple) { int ret; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) return ret; - ret = ctnl_del_expect(&cth, tuple, t); + ret = ctnl_del_expect(&cth, tuple); ctnl_close(&cth); return ret; @@ -614,7 +603,7 @@ int event_expectation(unsigned int event_mask) }; int ret; - if ((ret = ctnl_open(&cth, event_mask)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, event_mask)) < 0) return ret; ctnl_register_handler(&cth, &hnew); @@ -629,7 +618,7 @@ int flush_expectation() { int ret; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) return ret; ret = ctnl_flush_expect(&cth); -- cgit v1.2.3 From 8354fefa19bdaadb19a8fd0a818a7097e24bceaf Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=pablo/emailAddress=pablo@netfilter.org" Date: Mon, 8 Aug 2005 11:40:51 +0000 Subject: Resync to 2.6.14 and libnfnetlink_conntrack --- Makefile.am | 2 +- config.h.in | 7 ++-- configure.in | 2 +- extensions/libct_proto_sctp.c | 2 +- extensions/libct_proto_tcp.c | 2 +- extensions/libct_proto_udp.c | 2 +- src/conntrack.c | 10 +++--- src/libct.c | 79 ++++++++++++++++++++++++------------------- 8 files changed, 59 insertions(+), 47 deletions(-) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index b114b00..888d53e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,7 +5,7 @@ AUTOMAKE_OPTIONS = foreign 1.4 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I${KERNELDIR} SUBDIRS = src extensions DIST_SUBDIRS = include src extensions -LINKOPTS = -ldl -lnfnetlink -lnfnetlink_conntrack +LINKOPTS = -ldl -lnfnetlink -lctnetlink AM_CFLAGS = -g $(OBJECTS): libtool diff --git a/config.h.in b/config.h.in index 9045dbb..3921abd 100644 --- a/config.h.in +++ b/config.h.in @@ -6,16 +6,15 @@ /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H +/* Define to 1 if you have the `ctnetlink' library (-lctnetlink). */ +#undef HAVE_LIBCTNETLINK + /* Define to 1 if you have the `dl' library (-ldl). */ #undef HAVE_LIBDL /* Define to 1 if you have the `nfnetlink' library (-lnfnetlink). */ #undef HAVE_LIBNFNETLINK -/* Define to 1 if you have the `nfnetlink_conntrack' library - (-lnfnetlink_conntrack). */ -#undef HAVE_LIBNFNETLINK_CONNTRACK - /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H diff --git a/configure.in b/configure.in index 8956e34..efdacf1 100644 --- a/configure.in +++ b/configure.in @@ -22,7 +22,7 @@ dnl AC_CHECK_LIB([c], [main]) AC_CHECK_LIB([dl], [dlopen]) AC_CHECK_LIB([nfnetlink], [nfnl_listen]) -AC_CHECK_LIB([nfnetlink_conntrack], [ctnl_register_handler] ,,,[-lnfnetlink]) +AC_CHECK_LIB([ctnetlink], [ctnl_register_handler] ,,,[-lnfnetlink]) # Checks for header files. dnl AC_HEADER_STDC diff --git a/extensions/libct_proto_sctp.c b/extensions/libct_proto_sctp.c index 4dbdf27..b519ff1 100644 --- a/extensions/libct_proto_sctp.c +++ b/extensions/libct_proto_sctp.c @@ -14,7 +14,7 @@ #include /* For htons */ #include #include "libct_proto.h" -#include +#include "libctnetlink.h" static struct option opts[] = { {"orig-port-src", 1, 0, '1'}, diff --git a/extensions/libct_proto_tcp.c b/extensions/libct_proto_tcp.c index 323e4ec..65f0fb6 100644 --- a/extensions/libct_proto_tcp.c +++ b/extensions/libct_proto_tcp.c @@ -14,7 +14,7 @@ #include /* For htons */ #include #include "libct_proto.h" -#include +#include "libctnetlink.h" static struct option opts[] = { {"orig-port-src", 1, 0, '1'}, diff --git a/extensions/libct_proto_udp.c b/extensions/libct_proto_udp.c index 8a9f0cf..706f113 100644 --- a/extensions/libct_proto_udp.c +++ b/extensions/libct_proto_udp.c @@ -13,7 +13,7 @@ #include /* For htons */ #include #include "libct_proto.h" -#include +#include "libctnetlink.h" static struct option opts[] = { {"orig-port-src", 1, 0, '1'}, diff --git a/src/conntrack.c b/src/conntrack.c index 22c6115..ccfb71a 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -880,11 +880,13 @@ int main(int argc, char *argv[]) case EXP_CREATE: if (options & CT_OPT_ORIG) res = create_expectation(&orig, + CTA_TUPLE_ORIG, &exptuple, &mask, timeout); else if (options & CT_OPT_REPL) res = create_expectation(&reply, + CTA_TUPLE_REPLY, &exptuple, &mask, timeout); @@ -915,16 +917,16 @@ int main(int argc, char *argv[]) case EXP_DELETE: if (options & CT_OPT_ORIG) - res = delete_expectation(&orig); + res = delete_expectation(&orig, CTA_TUPLE_ORIG); else if (options & CT_OPT_REPL) - res = delete_expectation(&reply); + res = delete_expectation(&reply, CTA_TUPLE_REPLY); break; case CT_GET: if (options & CT_OPT_ORIG) - res = get_conntrack(&orig, id); + res = get_conntrack(&orig, CTA_TUPLE_ORIG, id); else if (options & CT_OPT_REPL) - res = get_conntrack(&reply, id); + res = get_conntrack(&reply, CTA_TUPLE_REPLY, id); break; case EXP_GET: diff --git a/src/libct.c b/src/libct.c index e03c02a..cf46b99 100644 --- a/src/libct.c +++ b/src/libct.c @@ -162,7 +162,7 @@ static int handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void *arg) parse_tuple(attr, &ct.tuple[CTNL_DIR_REPLY]); break; case CTA_STATUS: - ct.status = *(unsigned int *)NFA_DATA(attr); + ct.status = ntohl(*(unsigned int *)NFA_DATA(attr)); flags |= STATUS; break; case CTA_PROTOINFO: @@ -268,6 +268,25 @@ static int event_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, return handler(sock, nlh, arg); } +void parse_expect(struct nfattr *attr, struct ctnl_tuple *tuple, + struct ctnl_tuple *mask, unsigned long *timeout, + u_int32_t *id) +{ + struct nfattr *tb[CTA_EXPECT_MAX]; + + memset(tb, 0, CTA_EXPECT_MAX*sizeof(struct nfattr *)); + + nfnl_parse_nested(tb, CTA_EXPECT_MAX, attr); + if (tb[CTA_EXPECT_TUPLE-1]) + parse_tuple(tb[CTA_EXPECT_TUPLE-1], tuple); + if (tb[CTA_EXPECT_MASK-1]) + parse_tuple(tb[CTA_EXPECT_MASK-1], mask); + if (tb[CTA_EXPECT_TIMEOUT-1]) + *timeout = htonl(*(unsigned long *)NFA_DATA(tb[CTA_EXPECT_TIMEOUT-1])); + if (tb[CTA_EXPECT_ID-1]) + *id = htonl(*(u_int32_t *)NFA_DATA(tb[CTA_EXPECT_ID-1])); +} + static int expect_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void *arg) { struct nfgenmsg *nfmsg; @@ -291,19 +310,9 @@ static int expect_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void * while (NFA_OK(attr, attrlen)) { switch(attr->nfa_type) { - - case CTA_EXPECT_TUPLE: - parse_tuple(attr, &tuple); - break; - case CTA_EXPECT_MASK: - parse_tuple(attr, &mask); - break; - case CTA_EXPECT_TIMEOUT: - timeout = htonl(*(unsigned long *) - NFA_DATA(attr)); - break; - case CTA_EXPECT_ID: - id = htonl(*(u_int32_t *)NFA_DATA(attr)); + case CTA_EXPECT: + parse_expect(attr, &tuple, &mask, &timeout, + &id); break; } attr = NFA_NEXT(attr, attrlen); @@ -339,12 +348,12 @@ int create_conntrack(struct ctnl_tuple *orig, ct.tuple[CTNL_DIR_ORIGINAL] = *orig; ct.tuple[CTNL_DIR_REPLY] = *reply; ct.timeout = htonl(timeout); - ct.status = status; + ct.status = htonl(status); ct.protoinfo = *proto; if (range) ct.nat = *range; - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) + if ((ret = ctnl_open(&cth, 0)) < 0) return ret; ret = ctnl_new_conntrack(&cth, &ct); @@ -367,10 +376,10 @@ int update_conntrack(struct ctnl_tuple *orig, ct.tuple[CTNL_DIR_ORIGINAL] = *orig; ct.tuple[CTNL_DIR_REPLY] = *reply; ct.timeout = htonl(timeout); - ct.status = status; + ct.status = htonl(status); ct.protoinfo = *proto; - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) + if ((ret = ctnl_open(&cth, 0)) < 0) return ret; ret = ctnl_upd_conntrack(&cth, &ct); @@ -384,7 +393,7 @@ int delete_conntrack(struct ctnl_tuple *tuple, int dir) { int ret; - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) + if ((ret = ctnl_open(&cth, 0)) < 0) return ret; ret = ctnl_del_conntrack(&cth, tuple, dir); @@ -402,7 +411,7 @@ int get_conntrack(struct ctnl_tuple *tuple, int dir) }; int ret; - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) + if ((ret = ctnl_open(&cth, 0)) < 0) return ret; ctnl_register_handler(&cth, &h); @@ -421,7 +430,7 @@ int dump_conntrack_table(int zero) .handler = handler }; - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) + if ((ret = ctnl_open(&cth, 0)) < 0) return ret; ctnl_register_handler(&cth, &h); @@ -454,7 +463,7 @@ int event_conntrack(unsigned int event_mask) }; int ret; - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, event_mask)) < 0) + if ((ret = ctnl_open(&cth, event_mask)) < 0) return ret; signal(SIGINT, event_sighandler); @@ -518,7 +527,7 @@ int dump_expect_list() }; int ret; - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) + if ((ret = ctnl_open(&cth, 0)) < 0) return ret; ctnl_register_handler(&cth, &h); @@ -533,7 +542,7 @@ int flush_conntrack() { int ret; - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) + if ((ret = ctnl_open(&cth, 0)) < 0) return ret; ret = ctnl_flush_conntrack(&cth); @@ -542,7 +551,8 @@ int flush_conntrack() return ret; } -int get_expect(struct ctnl_tuple *tuple) +int get_expect(struct ctnl_tuple *tuple, + enum ctattr_type t) { struct ctnl_msg_handler h = { .type = IPCTNL_MSG_EXP_NEW, @@ -550,42 +560,43 @@ int get_expect(struct ctnl_tuple *tuple) }; int ret; - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) + if ((ret = ctnl_open(&cth, 0)) < 0) return 0; ctnl_register_handler(&cth, &h); - ret = ctnl_get_expect(&cth, tuple); + ret = ctnl_get_expect(&cth, tuple, t); ctnl_close(&cth); return ret; } int create_expectation(struct ctnl_tuple *tuple, + enum ctattr_type t, struct ctnl_tuple *exptuple, struct ctnl_tuple *mask, unsigned long timeout) { int ret; - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) + if ((ret = ctnl_open(&cth, 0)) < 0) return ret; - ret = ctnl_new_expect(&cth, tuple, exptuple, mask, timeout); + ret = ctnl_new_expect(&cth, tuple, t, exptuple, mask, timeout); ctnl_close(&cth); return ret; } -int delete_expectation(struct ctnl_tuple *tuple) +int delete_expectation(struct ctnl_tuple *tuple, enum ctattr_type t) { int ret; - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) + if ((ret = ctnl_open(&cth, 0)) < 0) return ret; - ret = ctnl_del_expect(&cth, tuple); + ret = ctnl_del_expect(&cth, tuple, t); ctnl_close(&cth); return ret; @@ -603,7 +614,7 @@ int event_expectation(unsigned int event_mask) }; int ret; - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, event_mask)) < 0) + if ((ret = ctnl_open(&cth, event_mask)) < 0) return ret; ctnl_register_handler(&cth, &hnew); @@ -618,7 +629,7 @@ int flush_expectation() { int ret; - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) + if ((ret = ctnl_open(&cth, 0)) < 0) return ret; ret = ctnl_flush_expect(&cth); -- cgit v1.2.3 From 496dbfa8a0d9ae7bc432873dfb2ef3b41087acd5 Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=pablo/emailAddress=pablo@netfilter.org" Date: Mon, 8 Aug 2005 11:43:51 +0000 Subject: Bumped version to 0.80 --- Makefile.am | 2 +- config.h.in | 7 ++-- configure.in | 2 +- extensions/libct_proto_sctp.c | 2 +- extensions/libct_proto_tcp.c | 2 +- extensions/libct_proto_udp.c | 2 +- src/conntrack.c | 12 +++---- src/libct.c | 79 +++++++++++++++++++------------------------ 8 files changed, 48 insertions(+), 60 deletions(-) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 888d53e..b114b00 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,7 +5,7 @@ AUTOMAKE_OPTIONS = foreign 1.4 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I${KERNELDIR} SUBDIRS = src extensions DIST_SUBDIRS = include src extensions -LINKOPTS = -ldl -lnfnetlink -lctnetlink +LINKOPTS = -ldl -lnfnetlink -lnfnetlink_conntrack AM_CFLAGS = -g $(OBJECTS): libtool diff --git a/config.h.in b/config.h.in index 3921abd..9045dbb 100644 --- a/config.h.in +++ b/config.h.in @@ -6,15 +6,16 @@ /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H -/* Define to 1 if you have the `ctnetlink' library (-lctnetlink). */ -#undef HAVE_LIBCTNETLINK - /* Define to 1 if you have the `dl' library (-ldl). */ #undef HAVE_LIBDL /* Define to 1 if you have the `nfnetlink' library (-lnfnetlink). */ #undef HAVE_LIBNFNETLINK +/* Define to 1 if you have the `nfnetlink_conntrack' library + (-lnfnetlink_conntrack). */ +#undef HAVE_LIBNFNETLINK_CONNTRACK + /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H diff --git a/configure.in b/configure.in index efdacf1..8956e34 100644 --- a/configure.in +++ b/configure.in @@ -22,7 +22,7 @@ dnl AC_CHECK_LIB([c], [main]) AC_CHECK_LIB([dl], [dlopen]) AC_CHECK_LIB([nfnetlink], [nfnl_listen]) -AC_CHECK_LIB([ctnetlink], [ctnl_register_handler] ,,,[-lnfnetlink]) +AC_CHECK_LIB([nfnetlink_conntrack], [ctnl_register_handler] ,,,[-lnfnetlink]) # Checks for header files. dnl AC_HEADER_STDC diff --git a/extensions/libct_proto_sctp.c b/extensions/libct_proto_sctp.c index b519ff1..4dbdf27 100644 --- a/extensions/libct_proto_sctp.c +++ b/extensions/libct_proto_sctp.c @@ -14,7 +14,7 @@ #include /* For htons */ #include #include "libct_proto.h" -#include "libctnetlink.h" +#include static struct option opts[] = { {"orig-port-src", 1, 0, '1'}, diff --git a/extensions/libct_proto_tcp.c b/extensions/libct_proto_tcp.c index 65f0fb6..323e4ec 100644 --- a/extensions/libct_proto_tcp.c +++ b/extensions/libct_proto_tcp.c @@ -14,7 +14,7 @@ #include /* For htons */ #include #include "libct_proto.h" -#include "libctnetlink.h" +#include static struct option opts[] = { {"orig-port-src", 1, 0, '1'}, diff --git a/extensions/libct_proto_udp.c b/extensions/libct_proto_udp.c index 706f113..8a9f0cf 100644 --- a/extensions/libct_proto_udp.c +++ b/extensions/libct_proto_udp.c @@ -13,7 +13,7 @@ #include /* For htons */ #include #include "libct_proto.h" -#include "libctnetlink.h" +#include static struct option opts[] = { {"orig-port-src", 1, 0, '1'}, diff --git a/src/conntrack.c b/src/conntrack.c index ccfb71a..12825b4 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -47,7 +47,7 @@ #include "libct_proto.h" #define PROGNAME "conntrack" -#define VERSION "0.63" +#define VERSION "0.80" #if 0 #define DEBUGP printf @@ -880,13 +880,11 @@ int main(int argc, char *argv[]) case EXP_CREATE: if (options & CT_OPT_ORIG) res = create_expectation(&orig, - CTA_TUPLE_ORIG, &exptuple, &mask, timeout); else if (options & CT_OPT_REPL) res = create_expectation(&reply, - CTA_TUPLE_REPLY, &exptuple, &mask, timeout); @@ -917,16 +915,16 @@ int main(int argc, char *argv[]) case EXP_DELETE: if (options & CT_OPT_ORIG) - res = delete_expectation(&orig, CTA_TUPLE_ORIG); + res = delete_expectation(&orig); else if (options & CT_OPT_REPL) - res = delete_expectation(&reply, CTA_TUPLE_REPLY); + res = delete_expectation(&reply); break; case CT_GET: if (options & CT_OPT_ORIG) - res = get_conntrack(&orig, CTA_TUPLE_ORIG, id); + res = get_conntrack(&orig, id); else if (options & CT_OPT_REPL) - res = get_conntrack(&reply, CTA_TUPLE_REPLY, id); + res = get_conntrack(&reply, id); break; case EXP_GET: diff --git a/src/libct.c b/src/libct.c index cf46b99..e03c02a 100644 --- a/src/libct.c +++ b/src/libct.c @@ -162,7 +162,7 @@ static int handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void *arg) parse_tuple(attr, &ct.tuple[CTNL_DIR_REPLY]); break; case CTA_STATUS: - ct.status = ntohl(*(unsigned int *)NFA_DATA(attr)); + ct.status = *(unsigned int *)NFA_DATA(attr); flags |= STATUS; break; case CTA_PROTOINFO: @@ -268,25 +268,6 @@ static int event_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, return handler(sock, nlh, arg); } -void parse_expect(struct nfattr *attr, struct ctnl_tuple *tuple, - struct ctnl_tuple *mask, unsigned long *timeout, - u_int32_t *id) -{ - struct nfattr *tb[CTA_EXPECT_MAX]; - - memset(tb, 0, CTA_EXPECT_MAX*sizeof(struct nfattr *)); - - nfnl_parse_nested(tb, CTA_EXPECT_MAX, attr); - if (tb[CTA_EXPECT_TUPLE-1]) - parse_tuple(tb[CTA_EXPECT_TUPLE-1], tuple); - if (tb[CTA_EXPECT_MASK-1]) - parse_tuple(tb[CTA_EXPECT_MASK-1], mask); - if (tb[CTA_EXPECT_TIMEOUT-1]) - *timeout = htonl(*(unsigned long *)NFA_DATA(tb[CTA_EXPECT_TIMEOUT-1])); - if (tb[CTA_EXPECT_ID-1]) - *id = htonl(*(u_int32_t *)NFA_DATA(tb[CTA_EXPECT_ID-1])); -} - static int expect_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void *arg) { struct nfgenmsg *nfmsg; @@ -310,9 +291,19 @@ static int expect_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void * while (NFA_OK(attr, attrlen)) { switch(attr->nfa_type) { - case CTA_EXPECT: - parse_expect(attr, &tuple, &mask, &timeout, - &id); + + case CTA_EXPECT_TUPLE: + parse_tuple(attr, &tuple); + break; + case CTA_EXPECT_MASK: + parse_tuple(attr, &mask); + break; + case CTA_EXPECT_TIMEOUT: + timeout = htonl(*(unsigned long *) + NFA_DATA(attr)); + break; + case CTA_EXPECT_ID: + id = htonl(*(u_int32_t *)NFA_DATA(attr)); break; } attr = NFA_NEXT(attr, attrlen); @@ -348,12 +339,12 @@ int create_conntrack(struct ctnl_tuple *orig, ct.tuple[CTNL_DIR_ORIGINAL] = *orig; ct.tuple[CTNL_DIR_REPLY] = *reply; ct.timeout = htonl(timeout); - ct.status = htonl(status); + ct.status = status; ct.protoinfo = *proto; if (range) ct.nat = *range; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) return ret; ret = ctnl_new_conntrack(&cth, &ct); @@ -376,10 +367,10 @@ int update_conntrack(struct ctnl_tuple *orig, ct.tuple[CTNL_DIR_ORIGINAL] = *orig; ct.tuple[CTNL_DIR_REPLY] = *reply; ct.timeout = htonl(timeout); - ct.status = htonl(status); + ct.status = status; ct.protoinfo = *proto; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) return ret; ret = ctnl_upd_conntrack(&cth, &ct); @@ -393,7 +384,7 @@ int delete_conntrack(struct ctnl_tuple *tuple, int dir) { int ret; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) return ret; ret = ctnl_del_conntrack(&cth, tuple, dir); @@ -411,7 +402,7 @@ int get_conntrack(struct ctnl_tuple *tuple, int dir) }; int ret; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) return ret; ctnl_register_handler(&cth, &h); @@ -430,7 +421,7 @@ int dump_conntrack_table(int zero) .handler = handler }; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) return ret; ctnl_register_handler(&cth, &h); @@ -463,7 +454,7 @@ int event_conntrack(unsigned int event_mask) }; int ret; - if ((ret = ctnl_open(&cth, event_mask)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, event_mask)) < 0) return ret; signal(SIGINT, event_sighandler); @@ -527,7 +518,7 @@ int dump_expect_list() }; int ret; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) return ret; ctnl_register_handler(&cth, &h); @@ -542,7 +533,7 @@ int flush_conntrack() { int ret; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) return ret; ret = ctnl_flush_conntrack(&cth); @@ -551,8 +542,7 @@ int flush_conntrack() return ret; } -int get_expect(struct ctnl_tuple *tuple, - enum ctattr_type t) +int get_expect(struct ctnl_tuple *tuple) { struct ctnl_msg_handler h = { .type = IPCTNL_MSG_EXP_NEW, @@ -560,43 +550,42 @@ int get_expect(struct ctnl_tuple *tuple, }; int ret; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) return 0; ctnl_register_handler(&cth, &h); - ret = ctnl_get_expect(&cth, tuple, t); + ret = ctnl_get_expect(&cth, tuple); ctnl_close(&cth); return ret; } int create_expectation(struct ctnl_tuple *tuple, - enum ctattr_type t, struct ctnl_tuple *exptuple, struct ctnl_tuple *mask, unsigned long timeout) { int ret; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) return ret; - ret = ctnl_new_expect(&cth, tuple, t, exptuple, mask, timeout); + ret = ctnl_new_expect(&cth, tuple, exptuple, mask, timeout); ctnl_close(&cth); return ret; } -int delete_expectation(struct ctnl_tuple *tuple, enum ctattr_type t) +int delete_expectation(struct ctnl_tuple *tuple) { int ret; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) return ret; - ret = ctnl_del_expect(&cth, tuple, t); + ret = ctnl_del_expect(&cth, tuple); ctnl_close(&cth); return ret; @@ -614,7 +603,7 @@ int event_expectation(unsigned int event_mask) }; int ret; - if ((ret = ctnl_open(&cth, event_mask)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, event_mask)) < 0) return ret; ctnl_register_handler(&cth, &hnew); @@ -629,7 +618,7 @@ int flush_expectation() { int ret; - if ((ret = ctnl_open(&cth, 0)) < 0) + if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) return ret; ret = ctnl_flush_expect(&cth); -- cgit v1.2.3 From f1295c5587345751c79b0247f68655c826ae052f Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org" Date: Fri, 23 Sep 2005 20:16:33 +0000 Subject: make sure we build against KERELDIR! --- Makefile.am | 2 +- configure.in | 8 ++++---- extensions/Makefile.am | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index b114b00..1cec4aa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ # not a GNU package. You can remove this line, if # have all needed files, that a GNU package needs -AUTOMAKE_OPTIONS = foreign 1.4 +AUTOMAKE_OPTIONS = foreign 1.8 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I${KERNELDIR} SUBDIRS = src extensions diff --git a/configure.in b/configure.in index 8956e34..cd8f37f 100644 --- a/configure.in +++ b/configure.in @@ -74,10 +74,10 @@ AC_ARG_WITH(kernel, [ Show location of kernel source. Default is to use uname -r and look in /lib/modules/KERNEL/build/include. ]), NF_KERNEL_SOURCE($with_kernel),NF_KERNEL_SOURCE()) -if test ! -z "$libdir"; then - MODULE_DIR="\\\"$libdir/\\\"" - CFLAGS="$CFLAGS -DCONNTRACK_LIB_DIR=$MODULE_DIR" -fi +#if test ! -z "$libdir"; then +# MODULE_DIR="\\\"$libdir/\\\"" +# CFLAGS="$CFLAGS -DCONNTRACK_LIB_DIR=$MODULE_DIR" +#fi dnl-------------------------------- diff --git a/extensions/Makefile.am b/extensions/Makefile.am index ecd3a91..ad48e09 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -4,7 +4,7 @@ EXTRA_DIST = $(man_MANS) acinclude.m4 man_MANS = -INCLUDES=-I../include -I/lib/modules/$(shell (uname -r))/build/include +INCLUDES=-I../include -I${KERNELDIR} CFLAGS=-fPIC -Wall LIBS= -- cgit v1.2.3 From 7c468c11793ddc54cc5a09756f711deb3511e788 Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org" Date: Sat, 24 Sep 2005 21:26:05 +0000 Subject: fix "dist-bzip2" for firt reelase --- Makefile.am | 2 +- configure.in | 2 +- extensions/Makefile.am | 6 +- missing | 336 ------------------------------------------------- 4 files changed, 3 insertions(+), 343 deletions(-) delete mode 100644 missing (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 1cec4aa..111505a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ # not a GNU package. You can remove this line, if # have all needed files, that a GNU package needs -AUTOMAKE_OPTIONS = foreign 1.8 +AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I${KERNELDIR} SUBDIRS = src extensions diff --git a/configure.in b/configure.in index 8956e34..cd6d7b5 100644 --- a/configure.in +++ b/configure.in @@ -2,7 +2,7 @@ AC_INIT AC_CANONICAL_SYSTEM -AM_INIT_AUTOMAKE(conntrack, 0.63) +AM_INIT_AUTOMAKE(conntrack, 0.81) AM_CONFIG_HEADER(config.h) AC_PROG_CC diff --git a/extensions/Makefile.am b/extensions/Makefile.am index ad48e09..1cae1df 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -1,8 +1,4 @@ -AUTOMAKE_OPTIONS = no-dependencies foreign - -EXTRA_DIST = $(man_MANS) acinclude.m4 - -man_MANS = +# AUTOMAKE_OPTIONS = no-dependencies foreign INCLUDES=-I../include -I${KERNELDIR} CFLAGS=-fPIC -Wall diff --git a/missing b/missing deleted file mode 100644 index 6a37006..0000000 --- a/missing +++ /dev/null @@ -1,336 +0,0 @@ -#! /bin/sh -# Common stub for a few missing GNU programs while installing. -# Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc. -# Originally by Fran,cois Pinard , 1996. - -# 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, 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., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -if test $# -eq 0; then - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 -fi - -run=: - -# In the cases where this matters, `missing' is being run in the -# srcdir already. -if test -f configure.ac; then - configure_ac=configure.ac -else - configure_ac=configure.in -fi - -case "$1" in ---run) - # Try to run requested program, and just exit if it succeeds. - run= - shift - "$@" && exit 0 - ;; -esac - -# If it does not exist, or fails to run (possibly an outdated version), -# try to emulate it. -case "$1" in - - -h|--h|--he|--hel|--help) - echo "\ -$0 [OPTION]... PROGRAM [ARGUMENT]... - -Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an -error status if there is no known handling for PROGRAM. - -Options: - -h, --help display this help and exit - -v, --version output version information and exit - --run try to run the given command, and emulate it if it fails - -Supported PROGRAM values: - aclocal touch file \`aclocal.m4' - autoconf touch file \`configure' - autoheader touch file \`config.h.in' - automake touch all \`Makefile.in' files - bison create \`y.tab.[ch]', if possible, from existing .[ch] - flex create \`lex.yy.c', if possible, from existing .c - help2man touch the output file - lex create \`lex.yy.c', if possible, from existing .c - makeinfo touch the output file - tar try tar, gnutar, gtar, then tar without non-portable flags - yacc create \`y.tab.[ch]', if possible, from existing .[ch]" - ;; - - -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing 0.4 - GNU automake" - ;; - - -*) - echo 1>&2 "$0: Unknown \`$1' option" - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 - ;; - - aclocal*) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`acinclude.m4' or \`${configure_ac}'. You might want - to install the \`Automake' and \`Perl' packages. Grab them from - any GNU archive site." - touch aclocal.m4 - ;; - - autoconf) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`${configure_ac}'. You might want to install the - \`Autoconf' and \`GNU m4' packages. Grab them from any GNU - archive site." - touch configure - ;; - - autoheader) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`acconfig.h' or \`${configure_ac}'. You might want - to install the \`Autoconf' and \`GNU m4' packages. Grab them - from any GNU archive site." - files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` - test -z "$files" && files="config.h" - touch_files= - for f in $files; do - case "$f" in - *:*) touch_files="$touch_files "`echo "$f" | - sed -e 's/^[^:]*://' -e 's/:.*//'`;; - *) touch_files="$touch_files $f.in";; - esac - done - touch $touch_files - ;; - - automake*) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. - You might want to install the \`Automake' and \`Perl' packages. - Grab them from any GNU archive site." - find . -type f -name Makefile.am -print | - sed 's/\.am$/.in/' | - while read f; do touch "$f"; done - ;; - - autom4te) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is needed, and you do not seem to have it handy on your - system. You might have modified some files without having the - proper tools for further handling them. - You can get \`$1Help2man' as part of \`Autoconf' from any GNU - archive site." - - file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` - test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo "#! /bin/sh" - echo "# Created by GNU Automake missing as a replacement of" - echo "# $ $@" - echo "exit 0" - chmod +x $file - exit 1 - fi - ;; - - bison|yacc) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a \`.y' file. You may need the \`Bison' package - in order for those modifications to take effect. You can get - \`Bison' from any GNU archive site." - rm -f y.tab.c y.tab.h - if [ $# -ne 1 ]; then - eval LASTARG="\${$#}" - case "$LASTARG" in - *.y) - SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" y.tab.c - fi - SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" y.tab.h - fi - ;; - esac - fi - if [ ! -f y.tab.h ]; then - echo >y.tab.h - fi - if [ ! -f y.tab.c ]; then - echo 'main() { return 0; }' >y.tab.c - fi - ;; - - lex|flex) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a \`.l' file. You may need the \`Flex' package - in order for those modifications to take effect. You can get - \`Flex' from any GNU archive site." - rm -f lex.yy.c - if [ $# -ne 1 ]; then - eval LASTARG="\${$#}" - case "$LASTARG" in - *.l) - SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" lex.yy.c - fi - ;; - esac - fi - if [ ! -f lex.yy.c ]; then - echo 'main() { return 0; }' >lex.yy.c - fi - ;; - - help2man) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a dependency of a manual page. You may need the - \`Help2man' package in order for those modifications to take - effect. You can get \`Help2man' from any GNU archive site." - - file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` - if test -z "$file"; then - file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` - fi - if [ -f "$file" ]; then - touch $file - else - test -z "$file" || exec >$file - echo ".ab help2man is required to generate this page" - exit 1 - fi - ;; - - makeinfo) - if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then - # We have makeinfo, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a \`.texi' or \`.texinfo' file, or any other file - indirectly affecting the aspect of the manual. The spurious - call might also be the consequence of using a buggy \`make' (AIX, - DU, IRIX). You might want to install the \`Texinfo' package or - the \`GNU make' package. Grab either from any GNU archive site." - file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` - if test -z "$file"; then - file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` - file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` - fi - touch $file - ;; - - tar) - shift - if test -n "$run"; then - echo 1>&2 "ERROR: \`tar' requires --run" - exit 1 - fi - - # We have already tried tar in the generic part. - # Look for gnutar/gtar before invocation to avoid ugly error - # messages. - if (gnutar --version > /dev/null 2>&1); then - gnutar "$@" && exit 0 - fi - if (gtar --version > /dev/null 2>&1); then - gtar "$@" && exit 0 - fi - firstarg="$1" - if shift; then - case "$firstarg" in - *o*) - firstarg=`echo "$firstarg" | sed s/o//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - case "$firstarg" in - *h*) - firstarg=`echo "$firstarg" | sed s/h//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - fi - - echo 1>&2 "\ -WARNING: I can't seem to be able to run \`tar' with the given arguments. - You may want to install GNU tar or Free paxutils, or check the - command line arguments." - exit 1 - ;; - - *) - echo 1>&2 "\ -WARNING: \`$1' is needed, and you do not seem to have it handy on your - system. You might have modified some files without having the - proper tools for further handling them. Check the \`README' file, - it often tells you about the needed prerequirements for installing - this package. You may also peek at any GNU archive site, in case - some other package would contain this missing \`$1' program." - exit 1 - ;; -esac - -exit 0 -- cgit v1.2.3 From 2b90455785ce4d4b304407994e379068df80aefd Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org" Date: Sat, 24 Sep 2005 21:31:50 +0000 Subject: make sure manpage is included in dist --- Makefile.am | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 111505a..18a67c6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,6 +2,10 @@ # have all needed files, that a GNU package needs AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 +man_MANS = conntrack.8 + +EXTRA_DIST = $(man_MANS) + INCLUDES = $(all_includes) -I$(top_srcdir)/include -I${KERNELDIR} SUBDIRS = src extensions DIST_SUBDIRS = include src extensions -- cgit v1.2.3 From da9b980f8d34c436b31d5a0a09b4ea27849c9c82 Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=pablo/emailAddress=pablo@netfilter.org" Date: Sun, 16 Oct 2005 21:13:29 +0000 Subject: See ChangeLog --- ChangeLog | 8 + Makefile.am | 2 +- configure.in | 4 +- extensions/libct_proto_icmp.c | 41 +-- extensions/libct_proto_sctp.c | 31 +- extensions/libct_proto_tcp.c | 49 +--- extensions/libct_proto_udp.c | 35 +-- include/libct_proto.h | 25 +- src/Makefile.am | 2 +- src/conntrack.c | 263 ++++++++++++----- src/libct.c | 660 ------------------------------------------ 11 files changed, 253 insertions(+), 867 deletions(-) delete mode 100644 src/libct.c (limited to 'Makefile.am') diff --git a/ChangeLog b/ChangeLog index 1a44a43..2942f78 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2005-10-14 + + o Kill config.h.in, it's generated by the autocrap + o The conntrack tool now uses libnetfilter_conntrack :) + o libct.c has been killed, now it's in libnetfilter_conntrack + o Check if you're root or CAP_NET_ADMIN + o Bumped version number to 0.86 + 2005-10-07 o Fixed ICMP options diff --git a/Makefile.am b/Makefile.am index 18a67c6..8d9faf6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,7 +9,7 @@ EXTRA_DIST = $(man_MANS) INCLUDES = $(all_includes) -I$(top_srcdir)/include -I${KERNELDIR} SUBDIRS = src extensions DIST_SUBDIRS = include src extensions -LINKOPTS = -ldl -lnfnetlink -lnfnetlink_conntrack +LINKOPTS = -ldl -lnfnetlink -lnetfilter_conntrack AM_CFLAGS = -g $(OBJECTS): libtool diff --git a/configure.in b/configure.in index cd6d7b5..0f0fc5f 100644 --- a/configure.in +++ b/configure.in @@ -2,7 +2,7 @@ AC_INIT AC_CANONICAL_SYSTEM -AM_INIT_AUTOMAKE(conntrack, 0.81) +AM_INIT_AUTOMAKE(conntrack, 0.63) AM_CONFIG_HEADER(config.h) AC_PROG_CC @@ -22,7 +22,7 @@ dnl AC_CHECK_LIB([c], [main]) AC_CHECK_LIB([dl], [dlopen]) AC_CHECK_LIB([nfnetlink], [nfnl_listen]) -AC_CHECK_LIB([nfnetlink_conntrack], [ctnl_register_handler] ,,,[-lnfnetlink]) +AC_CHECK_LIB([netfilter_conntrack], [nfct_dump_conntrack_table] ,,,[-lnetfilter_conntrack]) # Checks for header files. dnl AC_HEADER_STDC diff --git a/extensions/libct_proto_icmp.c b/extensions/libct_proto_icmp.c index be81507..7142fa7 100644 --- a/extensions/libct_proto_icmp.c +++ b/extensions/libct_proto_icmp.c @@ -13,6 +13,7 @@ #include #include /* For htons */ #include +#include #include "libct_proto.h" static struct option opts[] = { @@ -52,10 +53,10 @@ static u_int8_t invmap[] [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1}; int parse(char c, char *argv[], - struct ctnl_tuple *orig, - struct ctnl_tuple *reply, - struct ctnl_tuple *mask, - union ctnl_protoinfo *proto, + struct nfct_tuple *orig, + struct nfct_tuple *reply, + struct nfct_tuple *mask, + union nfct_protoinfo *proto, unsigned int *flags) { switch(c) { @@ -85,24 +86,9 @@ int parse(char c, char *argv[], return 1; } -void parse_proto(struct nfattr *cda[], struct ctnl_tuple *tuple) -{ - if (cda[CTA_PROTO_ICMP_TYPE-1]) - tuple->l4dst.icmp.type = - *(u_int8_t *)NFA_DATA(cda[CTA_PROTO_ICMP_TYPE-1]); - - if (cda[CTA_PROTO_ICMP_CODE-1]) - tuple->l4dst.icmp.code = - *(u_int8_t *)NFA_DATA(cda[CTA_PROTO_ICMP_CODE-1]); - - if (cda[CTA_PROTO_ICMP_ID-1]) - tuple->l4src.icmp.id = - *(u_int16_t *)NFA_DATA(cda[CTA_PROTO_ICMP_ID-1]); -} - int final_check(unsigned int flags, - struct ctnl_tuple *orig, - struct ctnl_tuple *reply) + struct nfct_tuple *orig, + struct nfct_tuple *reply) { if (!(flags & ICMP_TYPE)) return 0; @@ -112,21 +98,10 @@ int final_check(unsigned int flags, return 1; } -void print_proto(struct ctnl_tuple *t) -{ - fprintf(stdout, "type=%d code=%d ", t->l4dst.icmp.type, - t->l4dst.icmp.code); - /* ID only makes sense with ECHO */ - if (t->l4dst.icmp.type == 8) - fprintf(stdout, "id=%d ", t->l4src.icmp.id); -} - static struct ctproto_handler icmp = { .name = "icmp", - .protonum = 1, + .protonum = IPPROTO_ICMP, .parse_opts = parse, - .parse_proto = parse_proto, - .print_proto = print_proto, .final_check = final_check, .help = help, .opts = opts, diff --git a/extensions/libct_proto_sctp.c b/extensions/libct_proto_sctp.c index 9afb661..bc91966 100644 --- a/extensions/libct_proto_sctp.c +++ b/extensions/libct_proto_sctp.c @@ -12,9 +12,8 @@ #include #include #include /* For htons */ -#include #include "libct_proto.h" -#include +#include static struct option opts[] = { {"orig-port-src", 1, 0, '1'}, @@ -63,10 +62,10 @@ void help() } int parse_options(char c, char *argv[], - struct ctnl_tuple *orig, - struct ctnl_tuple *reply, - struct ctnl_tuple *mask, - union ctnl_protoinfo *proto, + struct nfct_tuple *orig, + struct nfct_tuple *reply, + struct nfct_tuple *mask, + union nfct_protoinfo *proto, unsigned int *flags) { switch(c) { @@ -100,7 +99,7 @@ int parse_options(char c, char *argv[], for (i=0; i<10; i++) { if (strcmp(optarg, states[i]) == 0) { /* FIXME: Add state to - * ctnl_protoinfo + * nfct_protoinfo proto->sctp.state = i; */ break; } @@ -116,8 +115,8 @@ int parse_options(char c, char *argv[], } int final_check(unsigned int flags, - struct ctnl_tuple *orig, - struct ctnl_tuple *reply) + struct nfct_tuple *orig, + struct nfct_tuple *reply) { if ((flags & (ORIG_SPORT|ORIG_DPORT)) && !(flags & (REPL_SPORT|REPL_DPORT))) { @@ -137,7 +136,7 @@ int final_check(unsigned int flags, return 0; } -void parse_proto(struct nfattr *cda[], struct ctnl_tuple *tuple) +void parse_proto(struct nfattr *cda[], struct nfct_tuple *tuple) { if (cda[CTA_PROTO_SRC_PORT-1]) tuple->l4src.sctp.port = @@ -147,7 +146,7 @@ void parse_proto(struct nfattr *cda[], struct ctnl_tuple *tuple) *(u_int16_t *)NFA_DATA(cda[CTA_PROTO_DST_PORT-1]); } -void parse_protoinfo(struct nfattr *cda[], struct ctnl_conntrack *ct) +void parse_protoinfo(struct nfattr *cda[], struct nfct_conntrack *ct) { /* if (cda[CTA_PROTOINFO_SCTP_STATE-1]) ct->protoinfo.sctp.state = @@ -155,12 +154,12 @@ void parse_protoinfo(struct nfattr *cda[], struct ctnl_conntrack *ct) */ } -void print_protoinfo(union ctnl_protoinfo *protoinfo) +void print_protoinfo(union nfct_protoinfo *protoinfo) { /* fprintf(stdout, "%s ", states[protoinfo->sctp.state]); */ } -void print_proto(struct ctnl_tuple *tuple) +void print_proto(struct nfct_tuple *tuple) { fprintf(stdout, "sport=%u dport=%u ", htons(tuple->l4src.sctp.port), htons(tuple->l4dst.sctp.port)); @@ -168,12 +167,8 @@ void print_proto(struct ctnl_tuple *tuple) static struct ctproto_handler sctp = { .name = "sctp", - .protonum = 132, + .protonum = IPPROTO_SCTP, .parse_opts = parse_options, - .parse_protoinfo = parse_protoinfo, - .parse_proto = parse_proto, - .print_proto = print_proto, - .print_protoinfo = print_protoinfo, .final_check = final_check, .help = help, .opts = opts, diff --git a/extensions/libct_proto_tcp.c b/extensions/libct_proto_tcp.c index 4f3094f..3b06aa2 100644 --- a/extensions/libct_proto_tcp.c +++ b/extensions/libct_proto_tcp.c @@ -12,8 +12,7 @@ #include #include #include /* For htons */ -#include -#include +#include #include "libct_proto.h" @@ -76,10 +75,10 @@ void help() } int parse_options(char c, char *argv[], - struct ctnl_tuple *orig, - struct ctnl_tuple *reply, - struct ctnl_tuple *mask, - union ctnl_protoinfo *proto, + struct nfct_tuple *orig, + struct nfct_tuple *reply, + struct nfct_tuple *mask, + union nfct_protoinfo *proto, unsigned int *flags) { switch(c) { @@ -139,8 +138,8 @@ int parse_options(char c, char *argv[], } int final_check(unsigned int flags, - struct ctnl_tuple *orig, - struct ctnl_tuple *reply) + struct nfct_tuple *orig, + struct nfct_tuple *reply) { if ((flags & (ORIG_SPORT|ORIG_DPORT)) && !(flags & (REPL_SPORT|REPL_DPORT))) { @@ -160,42 +159,10 @@ int final_check(unsigned int flags, return 0; } -void parse_proto(struct nfattr *cda[], struct ctnl_tuple *tuple) -{ - if (cda[CTA_PROTO_SRC_PORT-1]) - tuple->l4src.tcp.port = - *(u_int16_t *)NFA_DATA(cda[CTA_PROTO_SRC_PORT-1]); - if (cda[CTA_PROTO_DST_PORT-1]) - tuple->l4dst.tcp.port = - *(u_int16_t *)NFA_DATA(cda[CTA_PROTO_DST_PORT-1]); -} - -void parse_protoinfo(struct nfattr *cda[], struct ctnl_conntrack *ct) -{ - if (cda[CTA_PROTOINFO_TCP_STATE-1]) - ct->protoinfo.tcp.state = - *(u_int8_t *)NFA_DATA(cda[CTA_PROTOINFO_TCP_STATE-1]); -} - -void print_protoinfo(union ctnl_protoinfo *protoinfo) -{ - fprintf(stdout, "%s ", states[protoinfo->tcp.state]); -} - -void print_proto(struct ctnl_tuple *tuple) -{ - fprintf(stdout, "sport=%u dport=%u ", htons(tuple->l4src.tcp.port), - htons(tuple->l4dst.tcp.port)); -} - static struct ctproto_handler tcp = { .name = "tcp", - .protonum = 6, + .protonum = IPPROTO_TCP, .parse_opts = parse_options, - .parse_protoinfo = parse_protoinfo, - .parse_proto = parse_proto, - .print_proto = print_proto, - .print_protoinfo = print_protoinfo, .final_check = final_check, .help = help, .opts = opts, diff --git a/extensions/libct_proto_udp.c b/extensions/libct_proto_udp.c index ecde5f2..8e77f0c 100644 --- a/extensions/libct_proto_udp.c +++ b/extensions/libct_proto_udp.c @@ -11,9 +11,8 @@ #include #include #include /* For htons */ -#include #include "libct_proto.h" -#include +#include static struct option opts[] = { {"orig-port-src", 1, 0, '1'}, @@ -56,10 +55,10 @@ void help() } int parse_options(char c, char *argv[], - struct ctnl_tuple *orig, - struct ctnl_tuple *reply, - struct ctnl_tuple *mask, - union ctnl_protoinfo *proto, + struct nfct_tuple *orig, + struct nfct_tuple *reply, + struct nfct_tuple *mask, + union nfct_protoinfo *proto, unsigned int *flags) { switch(c) { @@ -104,8 +103,8 @@ int parse_options(char c, char *argv[], } int final_check(unsigned int flags, - struct ctnl_tuple *orig, - struct ctnl_tuple *reply) + struct nfct_tuple *orig, + struct nfct_tuple *reply) { if ((flags & (ORIG_SPORT|ORIG_DPORT)) && !(flags & (REPL_SPORT|REPL_DPORT))) { @@ -125,28 +124,10 @@ int final_check(unsigned int flags, return 0; } -void parse_proto(struct nfattr *cda[], struct ctnl_tuple *tuple) -{ - if (cda[CTA_PROTO_SRC_PORT-1]) - tuple->l4src.udp.port = - *(u_int16_t *)NFA_DATA(cda[CTA_PROTO_SRC_PORT-1]); - if (cda[CTA_PROTO_DST_PORT-1]) - tuple->l4dst.udp.port = - *(u_int16_t *)NFA_DATA(cda[CTA_PROTO_DST_PORT-1]); -} - -void print_proto(struct ctnl_tuple *tuple) -{ - fprintf(stdout, "sport=%u dport=%u ", htons(tuple->l4src.udp.port), - htons(tuple->l4dst.udp.port)); -} - static struct ctproto_handler udp = { .name = "udp", - .protonum = 17, + .protonum = IPPROTO_UDP, .parse_opts = parse_options, - .parse_proto = parse_proto, - .print_proto = print_proto, .final_check = final_check, .help = help, .opts = opts, diff --git a/include/libct_proto.h b/include/libct_proto.h index b358e1a..db434d6 100644 --- a/include/libct_proto.h +++ b/include/libct_proto.h @@ -1,11 +1,9 @@ #ifndef _LIBCT_PROTO_H #define _LIBCT_PROTO_H -/* FIXME: Rename this file pablo... */ - #include "linux_list.h" #include -#include +#include #define LIBCT_VERSION "0.1.0" @@ -16,8 +14,6 @@ #define IPS_DST_NAT_DONE (1 << 8) #define IPS_CONFIRMED (1 << 3) -struct cta_proto; - struct ctproto_handler { struct list_head head; @@ -28,20 +24,15 @@ struct ctproto_handler { enum ctattr_protoinfo protoinfo_attr; int (*parse_opts)(char c, char *argv[], - struct ctnl_tuple *orig, - struct ctnl_tuple *reply, - struct ctnl_tuple *mask, - union ctnl_protoinfo *proto, + struct nfct_tuple *orig, + struct nfct_tuple *reply, + struct nfct_tuple *mask, + union nfct_protoinfo *proto, unsigned int *flags); - void (*parse_proto)(struct nfattr *cda[], struct ctnl_tuple *tuple); - void (*parse_protoinfo)(struct nfattr *cda[], - struct ctnl_conntrack *ct); - void (*print_proto)(struct ctnl_tuple *t); - void (*print_protoinfo)(union ctnl_protoinfo *protoinfo); int (*final_check)(unsigned int flags, - struct ctnl_tuple *orig, - struct ctnl_tuple *reply); + struct nfct_tuple *orig, + struct nfct_tuple *reply); void (*help)(); @@ -53,8 +44,6 @@ struct ctproto_handler { extern void register_proto(struct ctproto_handler *h); extern void unregister_proto(struct ctproto_handler *h); -extern struct ctproto_handler *findproto(char *name); - #define NIPQUAD(addr) \ ((unsigned char *)&addr)[0], \ ((unsigned char *)&addr)[1], \ diff --git a/src/Makefile.am b/src/Makefile.am index ae3f429..71ad3d5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ bin_PROGRAMS = conntrack -conntrack_SOURCES = conntrack.c libct.c +conntrack_SOURCES = conntrack.c INCLUDES= $(all_includes) -I$(top_srcdir)/include -I${KERNELDIR} conntrack_LDFLAGS = $(all_libraries) -rdynamic diff --git a/src/conntrack.c b/src/conntrack.c index 1d5227e..8132dcb 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -1,5 +1,5 @@ /* - * (C) 2005 by Pablo Neira Ayuso + * (C) 2005 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 @@ -42,19 +42,14 @@ #include #include #include +#include #include -#include #include "linux_list.h" #include "libct_proto.h" +#include #define PROGNAME "conntrack" -#define VERSION "0.82" - -#if 0 -#define DEBUGP printf -#else -#define DEBUGP -#endif +#define VERSION "0.86" #ifndef PROC_SYS_MODPROBE #define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe" @@ -197,6 +192,7 @@ static struct option original_opts[] = { #define OPTION_OFFSET 256 +struct nfct_handle *cth; static struct option *opts = original_opts; static unsigned int global_option_offset = 0; @@ -236,12 +232,53 @@ char *lib_dir = CONNTRACK_LIB_DIR; LIST_HEAD(proto_list); -char *proto2str[IPPROTO_MAX] = { - [IPPROTO_TCP] = "tcp", - [IPPROTO_UDP] = "udp", - [IPPROTO_ICMP] = "icmp", - [IPPROTO_SCTP] = "sctp" -}; +void register_proto(struct ctproto_handler *h) +{ + if (strcmp(h->version, LIBCT_VERSION) != 0) { + fprintf(stderr, "plugin `%s': version %s (I'm %s)\n", + h->name, h->version, LIBCT_VERSION); + exit(1); + } + list_add(&h->head, &proto_list); +} + +void unregister_proto(struct ctproto_handler *h) +{ + list_del(&h->head); +} + +static struct nfct_proto *findproto(char *name) +{ + struct list_head *i; + struct nfct_proto *cur = NULL, *handler = NULL; + + if (!name) + return handler; + + lib_dir = getenv("CONNTRACK_LIB_DIR"); + if (!lib_dir) + lib_dir = CONNTRACK_LIB_DIR; + + list_for_each(i, &proto_list) { + cur = (struct nfct_proto *) i; + if (strcmp(cur->name, name) == 0) { + handler = cur; + break; + } + } + + if (!handler) { + char path[sizeof("libct_proto_.so") + + strlen(name) + strlen(lib_dir)]; + sprintf(path, "%s/libct_proto_%s.so", lib_dir, name); + if (dlopen(path, RTLD_NOW)) + handler = findproto(name); + else + fprintf(stderr, "%s\n", dlerror()); + } + + return handler; +} enum exittype { OTHER_PROBLEM = 1, @@ -383,7 +420,9 @@ err2str(int err, enum action command) { CT_GET, -EAFNOSUPPORT, "protocol not supported" }, { CT_CREATE, -ETIME, "conntrack has expired" }, { EXP_CREATE, -ENOENT, "master conntrack not found" }, - { EXP_CREATE, -EINVAL, "invalid parameters" } + { EXP_CREATE, -EINVAL, "invalid parameters" }, + { ~0UL, -EPERM, "sorry, you must be root or get " + "CAP_NET_ADMIN capability to do this"} }; for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) { @@ -394,7 +433,7 @@ err2str(int err, enum action command) return strerror(err); } -static void dump_tuple(struct ctnl_tuple *tp) +static void dump_tuple(struct nfct_tuple *tp) { fprintf(stdout, "tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n", tp, tp->protonum, @@ -553,7 +592,7 @@ int iptables_insmod(const char *modname, const char *modprobe) /* Shamelessly stolen from libipt_DNAT ;). Ranges expected in network order. */ static void -nat_parse(char *arg, int portok, struct ctnl_nat *range) +nat_parse(char *arg, int portok, struct nfct_nat *range) { char *colon, *dash, *error; unsigned long ip; @@ -625,6 +664,13 @@ nat_parse(char *arg, int portok, struct ctnl_nat *range) range->max_ip = range->min_ip; } +static void event_sighandler(int s) +{ + fprintf(stdout, "Now closing conntrack event dumping...\n"); + nfct_close(cth); + exit(0); +} + void usage(char *prog) { fprintf(stdout, "Tool to manipulate conntrack and expectations. Version %s\n", VERSION); fprintf(stdout, "Usage: %s [commands] [options]\n", prog); @@ -659,11 +705,11 @@ int main(int argc, char *argv[]) { char c; unsigned int command = 0, options = 0; - struct ctnl_tuple orig, reply, mask, *o = NULL, *r = NULL; - struct ctnl_tuple exptuple; + struct nfct_tuple orig, reply, mask, *o = NULL, *r = NULL; + struct nfct_tuple exptuple; struct ctproto_handler *h = NULL; - union ctnl_protoinfo proto; - struct ctnl_nat range; + union nfct_protoinfo proto; + struct nfct_nat range; unsigned long timeout = 0; unsigned int status = IPS_CONFIRMED; unsigned long id = 0; @@ -671,13 +717,13 @@ int main(int argc, char *argv[]) int manip = -1; int res = 0, retry = 2; - memset(&proto, 0, sizeof(union ctnl_protoinfo)); - memset(&orig, 0, sizeof(struct ctnl_tuple)); - memset(&reply, 0, sizeof(struct ctnl_tuple)); - memset(&mask, 0, sizeof(struct ctnl_tuple)); - memset(&exptuple, 0, sizeof(struct ctnl_tuple)); - memset(&range, 0, sizeof(struct ctnl_nat)); - + memset(&proto, 0, sizeof(union nfct_protoinfo)); + memset(&orig, 0, sizeof(struct nfct_tuple)); + memset(&reply, 0, sizeof(struct nfct_tuple)); + memset(&mask, 0, sizeof(struct nfct_tuple)); + memset(&exptuple, 0, sizeof(struct nfct_tuple)); + memset(&range, 0, sizeof(struct nfct_nat)); + while ((c = getopt_long(argc, argv, "L::I::U::D::G::E::F::hVs:d:r:q:p:t:u:e:a:z[:]:{:}:", opts, NULL)) != -1) { @@ -846,14 +892,24 @@ int main(int argc, char *argv[]) retry--; switch(command) { case CT_LIST: + cth = nfct_open(CONNTRACK, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Not enough memory"); + nfct_set_callback(cth, nfct_default_conntrack_display); if (options & CT_OPT_ZERO) - res = dump_conntrack_table(1); + res = nfct_dump_conntrack_table_zero(cth); else - res = dump_conntrack_table(0); + res = nfct_dump_conntrack_table(cth); break; + nfct_close(cth); case EXP_LIST: - res = dump_expect_list(); + cth = nfct_open(EXPECT, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Not enough memory"); + nfct_set_callback(cth, nfct_default_expect_display); + res = nfct_dump_expect_list(cth); + nfct_close(cth); break; case CT_CREATE: @@ -866,25 +922,43 @@ int main(int argc, char *argv[]) orig.src.v4 = reply.dst.v4; orig.dst.v4 = reply.src.v4; } + cth = nfct_open(CONNTRACK, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Not enough memory"); if (options & CT_OPT_NATRANGE) - res = create_conntrack(&orig, &reply, timeout, - &proto, status, &range); + res = nfct_create_conntrack_nat(cth, + &orig, + &reply, + timeout, + &proto, + status, + &range); else - res = create_conntrack(&orig, &reply, timeout, - &proto, status, NULL); + res = nfct_create_conntrack(cth, &orig, + &reply, + timeout, + &proto, + status); + nfct_close(cth); break; case EXP_CREATE: + cth = nfct_open(EXPECT, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Not enough memory"); if (options & CT_OPT_ORIG) - res = create_expectation(&orig, - &exptuple, - &mask, - timeout); + res = nfct_create_expectation(cth, + &orig, + &exptuple, + &mask, + timeout); else if (options & CT_OPT_REPL) - res = create_expectation(&reply, - &exptuple, - &mask, - timeout); + res = nfct_create_expectation(cth, + &reply, + &exptuple, + &mask, + timeout); + nfct_close(cth); break; case CT_UPDATE: @@ -897,60 +971,117 @@ int main(int argc, char *argv[]) orig.src.v4 = reply.dst.v4; orig.dst.v4 = reply.src.v4; } - res = update_conntrack(&orig, &reply, timeout, - &proto, status); + cth = nfct_open(CONNTRACK, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Not enough memory"); + res = nfct_update_conntrack(cth, &orig, &reply, + timeout, &proto, + status); + nfct_close(cth); break; case CT_DELETE: + cth = nfct_open(CONNTRACK, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Not enough memory"); if (options & CT_OPT_ORIG) - res = delete_conntrack(&orig, CTA_TUPLE_ORIG, - CTNL_DIR_ORIGINAL); + res = nfct_delete_conntrack(cth,&orig, + NFCT_DIR_ORIGINAL); else if (options & CT_OPT_REPL) - res = delete_conntrack(&reply, CTA_TUPLE_REPLY, - CTNL_DIR_REPLY); + res = nfct_delete_conntrack(cth,&reply, + NFCT_DIR_REPLY); + nfct_close(cth); break; case EXP_DELETE: + cth = nfct_open(EXPECT, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Not enough memory"); if (options & CT_OPT_ORIG) - res = delete_expectation(&orig); + res = nfct_delete_expectation(cth,&orig); else if (options & CT_OPT_REPL) - res = delete_expectation(&reply); + res = nfct_delete_expectation(cth,&reply); + nfct_close(cth); break; case CT_GET: + cth = nfct_open(CONNTRACK, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Not enough memory"); if (options & CT_OPT_ORIG) - res = get_conntrack(&orig, id); + res = nfct_get_conntrack(cth,&orig, id); else if (options & CT_OPT_REPL) - res = get_conntrack(&reply, id); + res = nfct_get_conntrack(cth,&reply, id); + nfct_close(cth); break; case EXP_GET: + cth = nfct_open(EXPECT, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Not enough memory"); if (options & CT_OPT_ORIG) - res = get_expect(&orig, CTA_TUPLE_ORIG); + res = nfct_get_expectation(cth,&orig); else if (options & CT_OPT_REPL) - res = get_expect(&reply, CTA_TUPLE_REPLY); + res = nfct_get_expectation(cth,&reply); + nfct_close(cth); break; case CT_FLUSH: - res = flush_conntrack(); + cth = nfct_open(CONNTRACK, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Not enough memory"); + res = nfct_flush_conntrack_table(cth); + nfct_close(cth); break; case EXP_FLUSH: - res = flush_expectation(); + cth = nfct_open(EXPECT, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Not enough memory"); + res = nfct_flush_expectation_table(cth); + nfct_close(cth); break; case CT_EVENT: - if (options & CT_OPT_EVENT_MASK) - res = event_conntrack(event_mask); - else - res = event_conntrack(~0U); + if (options & CT_OPT_EVENT_MASK) { + cth = nfct_open(CONNTRACK, event_mask); + if (!cth) + exit_error(OTHER_PROBLEM, + "Not enough memory"); + signal(SIGINT, event_sighandler); + nfct_set_callback(cth, nfct_default_conntrack_display); + res = nfct_event_conntrack(cth); + } else { + cth = nfct_open(CONNTRACK, ~0U); + if (!cth) + exit_error(OTHER_PROBLEM, + "Not enough memory"); + signal(SIGINT, event_sighandler); + nfct_set_callback(cth, nfct_default_conntrack_display); + res = nfct_event_conntrack(cth); + } + nfct_close(cth); break; case EXP_EVENT: - if (options & CT_OPT_EVENT_MASK) - res = event_expectation(event_mask); - else - res = event_expectation(~0U); + if (options & CT_OPT_EVENT_MASK) { + cth = nfct_open(EXPECT, event_mask); + if (!cth) + exit_error(OTHER_PROBLEM, + "Not enough memory"); + signal(SIGINT, event_sighandler); + nfct_set_callback(cth, nfct_default_expect_display); + res = nfct_event_expectation(cth); + } else { + cth = nfct_open(EXPECT, ~0U); + if (!cth) + exit_error(OTHER_PROBLEM, + "Not enough memory"); + signal(SIGINT, event_sighandler); + nfct_set_callback(cth, nfct_default_expect_display); + res = nfct_event_expectation(cth); + } + nfct_close(cth); break; case CT_VERSION: diff --git a/src/libct.c b/src/libct.c deleted file mode 100644 index 36aacbd..0000000 --- a/src/libct.c +++ /dev/null @@ -1,660 +0,0 @@ -/* - * (C) 2005 by Pablo Neira Ayuso - * Harald Welte - * - * 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 -#include -#include -#include -#include -#include -#include -/* From kernel.h */ -#define INT_MAX ((int)(~0U>>1)) -#define INT_MIN (-INT_MAX - 1) -#include -#include "linux_list.h" -#include "libct_proto.h" - -#if 0 -#define DEBUGP printf -#else -#define DEBUGP -#endif - -static struct ctnl_handle cth; -extern char *lib_dir; -extern struct list_head proto_list; -extern char *proto2str[]; - -static void dump_tuple(struct ctnl_tuple *tp) -{ - fprintf(stdout, "tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n", - tp, tp->protonum, - NIPQUAD(tp->src.v4), ntohs(tp->l4src.all), - NIPQUAD(tp->dst.v4), ntohs(tp->l4dst.all)); -} - -static void print_status(unsigned int status) -{ - if (status & IPS_ASSURED) - fprintf(stdout, "[ASSURED] "); - if (!(status & IPS_SEEN_REPLY)) - fprintf(stdout, "[UNREPLIED] "); -} - -static void parse_ip(struct nfattr *attr, struct ctnl_tuple *tuple) -{ - struct nfattr *tb[CTA_IP_MAX]; - - memset(tb, 0, CTA_IP_MAX * sizeof(struct nfattr *)); - - nfnl_parse_nested(tb, CTA_IP_MAX, attr); - if (tb[CTA_IP_V4_SRC-1]) - tuple->src.v4 = *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_SRC-1]); - - if (tb[CTA_IP_V4_DST-1]) - tuple->dst.v4 = *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_DST-1]); -} - -static void parse_proto(struct nfattr *attr, struct ctnl_tuple *tuple) -{ - struct nfattr *tb[CTA_PROTO_MAX]; - struct ctproto_handler *h; - int dir = CTNL_DIR_REPLY; - - memset(tb, 0, CTA_PROTO_MAX * sizeof(struct nfattr *)); - - nfnl_parse_nested(tb, CTA_PROTO_MAX, attr); - if (tb[CTA_PROTO_NUM-1]) - tuple->protonum = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_NUM-1]); - - h = findproto(proto2str[tuple->protonum]); - if (h && h->parse_proto) - h->parse_proto(tb, tuple); -} - -static void parse_tuple(struct nfattr *attr, struct ctnl_tuple *tuple) -{ - struct nfattr *tb[CTA_TUPLE_MAX]; - - memset(tb, 0, CTA_TUPLE_MAX*sizeof(struct nfattr *)); - - nfnl_parse_nested(tb, CTA_TUPLE_MAX, attr); - if (tb[CTA_TUPLE_IP-1]) - parse_ip(tb[CTA_TUPLE_IP-1], tuple); - if (tb[CTA_TUPLE_PROTO-1]) - parse_proto(tb[CTA_TUPLE_PROTO-1], tuple); -} - -static void parse_protoinfo(struct nfattr *attr, struct ctnl_conntrack *ct) -{ - struct nfattr *tb[CTA_PROTOINFO_MAX]; - struct ctproto_handler *h; - - memset(tb, 0, CTA_PROTOINFO_MAX*sizeof(struct nfattr *)); - - nfnl_parse_nested(tb,CTA_PROTOINFO_MAX, attr); - - h = findproto(proto2str[ct->tuple[CTNL_DIR_ORIGINAL].protonum]); - if (h && h->parse_protoinfo) - h->parse_protoinfo(tb, ct); -} - -/* Pablo: What is the equivalence of be64_to_cpu in userspace? - * - * Harald: Good question. I don't think there's a standard way [yet?], - * so I'd suggest manually implementing it by "#if little endian" bitshift - * operations in C (at least for now). - * - * All the payload of any nfattr will always be in network byte order. - * This would allow easy transport over a real network in the future - * (e.g. jamal's netlink2). - * - * Pablo: I've called it __be64_to_cpu instead of be64_to_cpu, since maybe - * there will one in the userspace headers someday. We don't want to - * pollute POSIX space naming, - */ - -#include -#if __BYTE_ORDER == __BIG_ENDIAN -# define __be64_to_cpu(x) (x) -# else -# if __BYTE_ORDER == __LITTLE_ENDIAN -# define __be64_to_cpu(x) __bswap_64(x) -# endif -#endif - -static void parse_counters(struct nfattr *attr, struct ctnl_conntrack *ct, - enum ctattr_type parent) -{ - struct nfattr *tb[CTA_COUNTERS_MAX]; - int dir = (parent == CTA_COUNTERS_ORIG ? CTNL_DIR_REPLY - : CTNL_DIR_ORIGINAL); - - memset(tb, 0, CTA_COUNTERS_MAX*sizeof(struct nfattr *)); - - nfnl_parse_nested(tb, CTA_COUNTERS_MAX, attr); - if (tb[CTA_COUNTERS_PACKETS-1]) - ct->counters[dir].packets - = __be64_to_cpu(*(u_int64_t *) - NFA_DATA(tb[CTA_COUNTERS_PACKETS-1])); - if (tb[CTA_COUNTERS_BYTES-1]) - ct->counters[dir].bytes - = __be64_to_cpu(*(u_int64_t *) - NFA_DATA(tb[CTA_COUNTERS_BYTES-1])); -} - -/* Some people seem to like counting in decimal... */ -#define STATUS 1 -#define PROTOINFO 2 -#define TIMEOUT 4 -#define MARK 8 -#define COUNTERS 16 -#define USE 32 -#define ID 64 - -static int handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void *arg) -{ - struct nfgenmsg *nfmsg; - struct nfattr *nfa; - int min_len = sizeof(struct nfgenmsg);; - struct ctproto_handler *h = NULL; - struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh)); - int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); - struct ctnl_conntrack ct; - unsigned int flags = 0; - - memset(&ct, 0, sizeof(struct ctnl_conntrack)); - - nfmsg = NLMSG_DATA(nlh); - - if (nlh->nlmsg_len < min_len) - return -EINVAL; - - while (NFA_OK(attr, attrlen)) { - switch(attr->nfa_type) { - case CTA_TUPLE_ORIG: - parse_tuple(attr, &ct.tuple[CTNL_DIR_ORIGINAL]); - break; - case CTA_TUPLE_REPLY: - parse_tuple(attr, &ct.tuple[CTNL_DIR_REPLY]); - break; - case CTA_STATUS: - ct.status = ntohl(*(u_int32_t *)NFA_DATA(attr)); - flags |= STATUS; - break; - case CTA_PROTOINFO: - parse_protoinfo(attr, &ct); - flags |= PROTOINFO; - break; - case CTA_TIMEOUT: - ct.timeout = ntohl(*(u_int32_t *)NFA_DATA(attr)); - flags |= TIMEOUT; - break; - case CTA_MARK: - ct.mark = ntohl(*(u_int32_t *)NFA_DATA(attr)); - flags |= MARK; - break; - case CTA_COUNTERS_ORIG: - case CTA_COUNTERS_REPLY: - parse_counters(attr, &ct, attr->nfa_type-1); - flags |= COUNTERS; - break; - case CTA_USE: - ct.use = ntohl(*(u_int32_t *)NFA_DATA(attr)); - flags |= USE; - break; - case CTA_ID: - ct.id = ntohl(*(u_int32_t *)NFA_DATA(attr)); - flags |= ID; - break; - } - attr = NFA_NEXT(attr, attrlen); - } - - fprintf(stdout, "%-8s %u ", - proto2str[ct.tuple[CTNL_DIR_ORIGINAL].protonum] == NULL ? - "unknown" : proto2str[ct.tuple[CTNL_DIR_ORIGINAL].protonum], - ct.tuple[CTNL_DIR_ORIGINAL].protonum); - - if (flags & TIMEOUT) - fprintf(stdout, "%lu ", ct.timeout); - - h = findproto(proto2str[ct.tuple[CTNL_DIR_ORIGINAL].protonum]); - if ((flags & PROTOINFO) && h && h->print_protoinfo) - h->print_protoinfo(&ct.protoinfo); - - fprintf(stdout, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ", - NIPQUAD(ct.tuple[CTNL_DIR_ORIGINAL].src.v4), - NIPQUAD(ct.tuple[CTNL_DIR_ORIGINAL].dst.v4)); - - if (h && h->print_proto) - h->print_proto(&ct.tuple[CTNL_DIR_ORIGINAL]); - - if (flags & COUNTERS) - fprintf(stdout, "packets=%llu bytes=%llu ", - ct.counters[CTNL_DIR_ORIGINAL].packets, - ct.counters[CTNL_DIR_ORIGINAL].bytes); - - fprintf(stdout, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ", - NIPQUAD(ct.tuple[CTNL_DIR_REPLY].src.v4), - NIPQUAD(ct.tuple[CTNL_DIR_REPLY].dst.v4)); - - h = findproto(proto2str[ct.tuple[CTNL_DIR_ORIGINAL].protonum]); - if (h && h->print_proto) - h->print_proto(&ct.tuple[CTNL_DIR_REPLY]); - - if (flags & COUNTERS) - fprintf(stdout, "packets=%llu bytes=%llu ", - ct.counters[CTNL_DIR_REPLY].packets, - ct.counters[CTNL_DIR_REPLY].bytes); - - if (flags & STATUS) - print_status(ct.status); - - if (flags & MARK) - fprintf(stdout, "mark=%lu ", ct.mark); - if (flags & USE) - fprintf(stdout, "use=%u ", ct.use); - if (flags & ID) - fprintf(stdout, "id=%u ", ct.id); - - fprintf(stdout, "\n"); - - return 0; -} - -static char *typemsg2str(type, flags) -{ - char *ret = "[UNKNOWN]"; - - if (type == IPCTNL_MSG_CT_NEW) { - if (flags & NLM_F_CREATE) - ret = "[NEW]"; - else - ret = "[UPDATE]"; - } else if (type == IPCTNL_MSG_CT_DELETE) - ret = "[DESTROY]"; - - return ret; -} - -static int event_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, - void *arg) -{ - int type = NFNL_MSG_TYPE(nlh->nlmsg_type); - fprintf(stdout, "%9s ", typemsg2str(type, nlh->nlmsg_flags)); - return handler(sock, nlh, arg); -} - -static int expect_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void *arg) -{ - struct nfgenmsg *nfmsg; - struct nfattr *nfa; - int min_len = sizeof(struct nfgenmsg);; - struct ctproto_handler *h = NULL; - struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh)); - int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); - struct ctnl_tuple tuple, mask; - unsigned long timeout = 0; - u_int32_t id = 0; - unsigned int flags; - - memset(&tuple, 0, sizeof(struct ctnl_tuple)); - memset(&mask, 0, sizeof(struct ctnl_tuple)); - - nfmsg = NLMSG_DATA(nlh); - - if (nlh->nlmsg_len < min_len) - return -EINVAL; - - while (NFA_OK(attr, attrlen)) { - switch(attr->nfa_type) { - - case CTA_EXPECT_TUPLE: - parse_tuple(attr, &tuple); - break; - case CTA_EXPECT_MASK: - parse_tuple(attr, &mask); - break; - case CTA_EXPECT_TIMEOUT: - timeout = htonl(*(unsigned long *) - NFA_DATA(attr)); - break; - case CTA_EXPECT_ID: - id = htonl(*(u_int32_t *)NFA_DATA(attr)); - break; - } - attr = NFA_NEXT(attr, attrlen); - } - fprintf(stdout, "%ld proto=%d ", timeout, tuple.protonum); - - fprintf(stdout, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ", - NIPQUAD(tuple.src.v4), - NIPQUAD(tuple.dst.v4)); - - fprintf(stdout, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ", - NIPQUAD(mask.src.v4), - NIPQUAD(mask.dst.v4)); - - fprintf(stdout, "id=%u ", id); - - fputc('\n', stdout); - - return 0; -} - -int create_conntrack(struct ctnl_tuple *orig, - struct ctnl_tuple *reply, - unsigned long timeout, - union ctnl_protoinfo *proto, - unsigned int status, - struct ctnl_nat *range) -{ - struct ctnl_conntrack ct; - int ret; - - memset(&ct, 0, sizeof(struct ctnl_conntrack)); - ct.tuple[CTNL_DIR_ORIGINAL] = *orig; - ct.tuple[CTNL_DIR_REPLY] = *reply; - ct.timeout = htonl(timeout); - ct.status = status; - ct.protoinfo = *proto; - if (range) - ct.nat = *range; - - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) - return ret; - - ret = ctnl_new_conntrack(&cth, &ct); - - ctnl_close(&cth); - - return ret; -} - -int update_conntrack(struct ctnl_tuple *orig, - struct ctnl_tuple *reply, - unsigned long timeout, - union ctnl_protoinfo *proto, - unsigned int status) -{ - struct ctnl_conntrack ct; - int ret; - - memset(&ct, 0, sizeof(struct ctnl_conntrack)); - ct.tuple[CTNL_DIR_ORIGINAL] = *orig; - ct.tuple[CTNL_DIR_REPLY] = *reply; - ct.timeout = htonl(timeout); - ct.status = status; - ct.protoinfo = *proto; - - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) - return ret; - - ret = ctnl_upd_conntrack(&cth, &ct); - - ctnl_close(&cth); - - return ret; -} - -int delete_conntrack(struct ctnl_tuple *tuple, int dir) -{ - int ret; - - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) - return ret; - - ret = ctnl_del_conntrack(&cth, tuple, dir); - ctnl_close(&cth); - - return ret; -} - -/* get_conntrack_handler */ -int get_conntrack(struct ctnl_tuple *tuple, int dir) -{ - struct ctnl_msg_handler h = { - .type = 0, - .handler = handler - }; - int ret; - - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) - return ret; - - ctnl_register_handler(&cth, &h); - - ret = ctnl_get_conntrack(&cth, tuple, dir); - ctnl_close(&cth); - - return ret; -} - -int dump_conntrack_table(int zero) -{ - int ret; - struct ctnl_msg_handler h = { - .type = IPCTNL_MSG_CT_NEW, /* Hm... really? */ - .handler = handler - }; - - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) - return ret; - - ctnl_register_handler(&cth, &h); - - if (zero) { - ret = ctnl_list_conntrack_zero_counters(&cth, AF_INET); - } else - ret = ctnl_list_conntrack(&cth, AF_INET); - - ctnl_close(&cth); - - return ret; -} - -static void event_sighandler(int s) -{ - fprintf(stdout, "Now closing conntrack event dumping...\n"); - ctnl_close(&cth); - exit(0); -} - -int event_conntrack(unsigned int event_mask) -{ - struct ctnl_msg_handler hnew = { - .type = IPCTNL_MSG_CT_NEW, - .handler = event_handler - }; - struct ctnl_msg_handler hdestroy = { - .type = IPCTNL_MSG_CT_DELETE, - .handler = event_handler - }; - int ret; - - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, event_mask)) < 0) - return ret; - - signal(SIGINT, event_sighandler); - ctnl_register_handler(&cth, &hnew); - ctnl_register_handler(&cth, &hdestroy); - ret = ctnl_event_conntrack(&cth, AF_INET); - ctnl_close(&cth); - - return 0; -} - -struct ctproto_handler *findproto(char *name) -{ - void *h = NULL; - struct list_head *i; - struct ctproto_handler *cur = NULL, *handler = NULL; - - if (!name) - return handler; - - lib_dir = getenv("CONNTRACK_LIB_DIR"); - if (!lib_dir) - lib_dir = CONNTRACK_LIB_DIR; - - list_for_each(i, &proto_list) { - cur = (struct ctproto_handler *) i; - if (strcmp(cur->name, name) == 0) { - handler = cur; - break; - } - } - - if (!handler) { - char path[sizeof("libct_proto_.so") - + strlen(name) + strlen(lib_dir)]; - sprintf(path, "%s/libct_proto_%s.so", lib_dir, name); - if (dlopen(path, RTLD_NOW)) - handler = findproto(name); - else - DEBUGP(stderr, "%s\n", dlerror()); - } - - return handler; -} - -void register_proto(struct ctproto_handler *h) -{ - if (strcmp(h->version, LIBCT_VERSION) != 0) { - fprintf(stderr, "plugin `%s': version %s (I'm %s)\n", - h->name, h->version, LIBCT_VERSION); - exit(1); - } - list_add(&h->head, &proto_list); -} - -void unregister_proto(struct ctproto_handler *h) -{ - list_del(&h->head); -} - -int dump_expect_list() -{ - struct ctnl_msg_handler h = { - .type = IPCTNL_MSG_EXP_NEW, - .handler = expect_handler - }; - int ret; - - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) - return ret; - - ctnl_register_handler(&cth, &h); - - ret = ctnl_list_expect(&cth, AF_INET); - ctnl_close(&cth); - - return ret; -} - -int flush_conntrack() -{ - int ret; - - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0) - return ret; - - ret = ctnl_flush_conntrack(&cth); - ctnl_close(&cth); - - return ret; -} - -int get_expect(struct ctnl_tuple *tuple) -{ - struct ctnl_msg_handler h = { - .type = IPCTNL_MSG_EXP_NEW, - .handler = expect_handler - }; - int ret; - - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) - return 0; - - ctnl_register_handler(&cth, &h); - - ret = ctnl_get_expect(&cth, tuple); - ctnl_close(&cth); - - return ret; -} - -int create_expectation(struct ctnl_tuple *tuple, - struct ctnl_tuple *exptuple, - struct ctnl_tuple *mask, - unsigned long timeout) -{ - int ret; - - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) - return ret; - - - ret = ctnl_new_expect(&cth, tuple, exptuple, mask, timeout); - ctnl_close(&cth); - - return ret; -} - -int delete_expectation(struct ctnl_tuple *tuple) -{ - int ret; - - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) - return ret; - - ret = ctnl_del_expect(&cth, tuple); - ctnl_close(&cth); - - return ret; -} - -int event_expectation(unsigned int event_mask) -{ - struct ctnl_msg_handler hnew = { - .type = IPCTNL_MSG_EXP_NEW, - .handler = expect_handler - }; - struct ctnl_msg_handler hdestroy = { - .type = IPCTNL_MSG_EXP_DELETE, - .handler = expect_handler - }; - int ret; - - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, event_mask)) < 0) - return ret; - - ctnl_register_handler(&cth, &hnew); - ctnl_register_handler(&cth, &hdestroy); - ret = ctnl_event_expect(&cth, AF_INET); - ctnl_close(&cth); - - return ret; -} - -int flush_expectation() -{ - int ret; - - if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0) - return ret; - - ret = ctnl_flush_expect(&cth); - ctnl_close(&cth); - - return ret; -} - -- cgit v1.2.3 From 26caf6b0d84c0709dedb9b05ca4ab91fa3677bb0 Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org" Date: Sat, 5 Nov 2005 13:59:33 +0000 Subject: we don't use libnfnetlink directly, so we don't link it explicitly --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 8d9faf6..46a9220 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,7 +9,7 @@ EXTRA_DIST = $(man_MANS) INCLUDES = $(all_includes) -I$(top_srcdir)/include -I${KERNELDIR} SUBDIRS = src extensions DIST_SUBDIRS = include src extensions -LINKOPTS = -ldl -lnfnetlink -lnetfilter_conntrack +LINKOPTS = -ldl -lnetfilter_conntrack AM_CFLAGS = -g $(OBJECTS): libtool -- cgit v1.2.3 From 9ed5ff2dace70b5235682d336a90faaf28377e6e Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org" Date: Mon, 14 Nov 2005 16:37:04 +0000 Subject: - get rid of KERNELDIR - use Make_global.am --- Make_global.am | 1 + Makefile.am | 5 +++-- extensions/Makefile.am | 3 +-- src/Makefile.am | 5 ++--- 4 files changed, 7 insertions(+), 7 deletions(-) create mode 100644 Make_global.am (limited to 'Makefile.am') diff --git a/Make_global.am b/Make_global.am new file mode 100644 index 0000000..685add7 --- /dev/null +++ b/Make_global.am @@ -0,0 +1 @@ +INCLUDES=$(all_includes) -I$(top_srcdir)/include diff --git a/Makefile.am b/Makefile.am index 46a9220..4962fb4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,12 +1,13 @@ +include Make_global.am + # not a GNU package. You can remove this line, if # have all needed files, that a GNU package needs AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 man_MANS = conntrack.8 -EXTRA_DIST = $(man_MANS) +EXTRA_DIST = $(man_MANS) Make_global.am -INCLUDES = $(all_includes) -I$(top_srcdir)/include -I${KERNELDIR} SUBDIRS = src extensions DIST_SUBDIRS = include src extensions LINKOPTS = -ldl -lnetfilter_conntrack diff --git a/extensions/Makefile.am b/extensions/Makefile.am index c1f9cb6..1eaf230 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -1,6 +1,5 @@ -# AUTOMAKE_OPTIONS = no-dependencies foreign +include $(top_srcdir)/Make_global.am -INCLUDES=-I../include -I${KERNELDIR} CFLAGS=-fPIC -Wall LIBS= diff --git a/src/Makefile.am b/src/Makefile.am index 0116de2..fb1410a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,8 +1,7 @@ +include $(top_srcdir)/Make_global.am + sbin_PROGRAMS = conntrack conntrack_SOURCES = conntrack.c -INCLUDES= $(all_includes) -I$(top_srcdir)/include -I${KERNELDIR} conntrack_LDFLAGS = $(all_libraries) -rdynamic -#AM_CFLAGS = -g -#LINKOPTS=-ldl -lnfnetlink -lctnetlink -rdynamic -- cgit v1.2.3 From 08951de68efebc3104bd8f591c8076b0be5013ae Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org" Date: Sat, 7 Jan 2006 15:35:53 +0000 Subject: add 'debian' to EXTRA_DIST --- Makefile.am | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 4962fb4..d3b4ceb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,7 +6,7 @@ AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 man_MANS = conntrack.8 -EXTRA_DIST = $(man_MANS) Make_global.am +EXTRA_DIST = $(man_MANS) Make_global.am debian SUBDIRS = src extensions DIST_SUBDIRS = include src extensions @@ -16,3 +16,6 @@ AM_CFLAGS = -g $(OBJECTS): libtool libtool: $(LIBTOOL_DEPS) $(SHELL) ./config.status --recheck + +dist-hook: + rm -rf `find $(distdir)/debian -name .svn` -- cgit v1.2.3 From ad31f852c3454136bdbfeb7f222cb9c175f13c1c 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 17:55:00 +0000 Subject: initial import of the conntrack daemon to Netfilter SVN --- AUTHORS | 2 - ChangeLog | 243 ----- INSTALL | 229 ---- Make_global.am | 1 - Makefile.am | 21 - README | 17 + autogen.sh | 18 - cli/AUTHORS | 2 + cli/ChangeLog | 243 +++++ cli/INSTALL | 229 ++++ cli/Make_global.am | 1 + cli/Makefile.am | 21 + cli/autogen.sh | 18 + cli/configure.in | 72 ++ cli/conntrack.8 | 142 +++ cli/extensions/Makefile.am | 16 + cli/extensions/libct_proto_icmp.c | 108 ++ cli/extensions/libct_proto_icmp.man | 10 + cli/extensions/libct_proto_sctp.c | 164 +++ cli/extensions/libct_proto_tcp.c | 180 ++++ cli/extensions/libct_proto_tcp.man | 16 + cli/extensions/libct_proto_udp.c | 141 +++ cli/extensions/libct_proto_udp.man | 13 + cli/include/Makefile.am | 2 + cli/include/conntrack.h | 160 +++ cli/include/linux_list.h | 725 +++++++++++++ cli/src/Makefile.am | 7 + cli/src/conntrack.c | 1131 ++++++++++++++++++++ cli/test.sh | 110 ++ configure.in | 72 -- conntrack.8 | 142 --- daemon/AUTHORS | 1 + daemon/CHANGELOG | 184 ++++ daemon/CONTRIBUTORS | 3 + daemon/INSTALL | 199 ++++ daemon/Make_global.am | 1 + daemon/Makefile.am | 21 + daemon/TODO | 18 + daemon/autogen.sh | 18 + daemon/configure.in | 106 ++ daemon/examples/Makefile.am | 1 + daemon/examples/debian.conntrackd.init.d | 48 + daemon/examples/stats/Makefile.am | 1 + daemon/examples/stats/conntrackd.conf | 69 ++ daemon/examples/sync/Makefile.am | 1 + daemon/examples/sync/nack/Makefile.am | 2 + daemon/examples/sync/nack/README | 1 + daemon/examples/sync/nack/node1/Makefile.am | 1 + daemon/examples/sync/nack/node1/conntrackd.conf | 125 +++ daemon/examples/sync/nack/node1/keepalived.conf | 38 + daemon/examples/sync/nack/node2/Makefile.am | 1 + daemon/examples/sync/nack/node2/conntrackd.conf | 124 +++ daemon/examples/sync/nack/node2/keepalived.conf | 38 + daemon/examples/sync/nack/script_backup.sh | 3 + daemon/examples/sync/nack/script_master.sh | 5 + daemon/examples/sync/persistent/Makefile.am | 2 + daemon/examples/sync/persistent/README | 1 + daemon/examples/sync/persistent/node1/Makefile.am | 1 + .../examples/sync/persistent/node1/conntrackd.conf | 130 +++ .../examples/sync/persistent/node1/keepalived.conf | 38 + daemon/examples/sync/persistent/node2/Makefile.am | 1 + .../examples/sync/persistent/node2/conntrackd.conf | 130 +++ .../examples/sync/persistent/node2/keepalived.conf | 38 + daemon/examples/sync/persistent/script_backup.sh | 3 + daemon/examples/sync/persistent/script_master.sh | 4 + daemon/include/Makefile.am | 5 + daemon/include/alarm.h | 13 + daemon/include/buffer.h | 32 + daemon/include/cache.h | 92 ++ daemon/include/conntrackd.h | 174 +++ daemon/include/debug.h | 53 + daemon/include/hash.h | 47 + daemon/include/ignore.h | 12 + daemon/include/jhash.h | 146 +++ daemon/include/linux_list.h | 725 +++++++++++++ daemon/include/local.h | 29 + daemon/include/log.h | 10 + daemon/include/mcast.h | 48 + daemon/include/network.h | 34 + daemon/include/slist.h | 41 + daemon/include/state_helper.h | 20 + daemon/include/sync.h | 23 + daemon/include/us-conntrack.h | 13 + daemon/src/Makefile.am | 22 + daemon/src/alarm.c | 141 +++ daemon/src/buffer.c | 136 +++ daemon/src/cache.c | 446 ++++++++ daemon/src/cache_iterators.c | 229 ++++ daemon/src/cache_lifetime.c | 65 ++ daemon/src/cache_timer.c | 72 ++ daemon/src/checksum.c | 32 + daemon/src/hash.c | 199 ++++ daemon/src/ignore_pool.c | 136 +++ daemon/src/local.c | 159 +++ daemon/src/lock.c | 32 + daemon/src/log.c | 57 + daemon/src/main.c | 302 ++++++ daemon/src/mcast.c | 287 +++++ daemon/src/netlink.c | 326 ++++++ daemon/src/network.c | 282 +++++ daemon/src/proxy.c | 124 +++ daemon/src/read_config_lex.l | 125 +++ daemon/src/read_config_yy.y | 550 ++++++++++ daemon/src/run.c | 227 ++++ daemon/src/state_helper.c | 44 + daemon/src/state_helper_tcp.c | 35 + daemon/src/stats-mode.c | 151 +++ daemon/src/sync-mode.c | 416 +++++++ daemon/src/sync-nack.c | 309 ++++++ daemon/src/sync-notrack.c | 127 +++ daemon/src/traffic_stats.c | 54 + extensions/Makefile.am | 16 - extensions/libct_proto_icmp.c | 108 -- extensions/libct_proto_icmp.man | 10 - extensions/libct_proto_sctp.c | 164 --- extensions/libct_proto_tcp.c | 180 ---- extensions/libct_proto_tcp.man | 16 - extensions/libct_proto_udp.c | 141 --- extensions/libct_proto_udp.man | 13 - include/Makefile.am | 2 - include/conntrack.h | 160 --- include/linux_list.h | 725 ------------- src/Makefile.am | 7 - src/conntrack.c | 1131 -------------------- test.sh | 110 -- 125 files changed, 11487 insertions(+), 3511 deletions(-) delete mode 100644 AUTHORS delete mode 100644 ChangeLog delete mode 100644 INSTALL delete mode 100644 Make_global.am delete mode 100644 Makefile.am create mode 100644 README delete mode 100755 autogen.sh create mode 100644 cli/AUTHORS create mode 100644 cli/ChangeLog create mode 100644 cli/INSTALL create mode 100644 cli/Make_global.am create mode 100644 cli/Makefile.am create mode 100755 cli/autogen.sh create mode 100644 cli/configure.in create mode 100644 cli/conntrack.8 create mode 100644 cli/extensions/Makefile.am create mode 100644 cli/extensions/libct_proto_icmp.c create mode 100644 cli/extensions/libct_proto_icmp.man create mode 100644 cli/extensions/libct_proto_sctp.c create mode 100644 cli/extensions/libct_proto_tcp.c create mode 100644 cli/extensions/libct_proto_tcp.man create mode 100644 cli/extensions/libct_proto_udp.c create mode 100644 cli/extensions/libct_proto_udp.man create mode 100644 cli/include/Makefile.am create mode 100644 cli/include/conntrack.h create mode 100644 cli/include/linux_list.h create mode 100644 cli/src/Makefile.am create mode 100644 cli/src/conntrack.c create mode 100644 cli/test.sh delete mode 100644 configure.in delete mode 100644 conntrack.8 create mode 100644 daemon/AUTHORS create mode 100644 daemon/CHANGELOG create mode 100644 daemon/CONTRIBUTORS create mode 100644 daemon/INSTALL create mode 100644 daemon/Make_global.am create mode 100644 daemon/Makefile.am create mode 100644 daemon/TODO create mode 100755 daemon/autogen.sh create mode 100644 daemon/configure.in create mode 100644 daemon/examples/Makefile.am create mode 100644 daemon/examples/debian.conntrackd.init.d create mode 100644 daemon/examples/stats/Makefile.am create mode 100644 daemon/examples/stats/conntrackd.conf create mode 100644 daemon/examples/sync/Makefile.am create mode 100644 daemon/examples/sync/nack/Makefile.am create mode 100644 daemon/examples/sync/nack/README create mode 100644 daemon/examples/sync/nack/node1/Makefile.am create mode 100644 daemon/examples/sync/nack/node1/conntrackd.conf create mode 100644 daemon/examples/sync/nack/node1/keepalived.conf create mode 100644 daemon/examples/sync/nack/node2/Makefile.am create mode 100644 daemon/examples/sync/nack/node2/conntrackd.conf create mode 100644 daemon/examples/sync/nack/node2/keepalived.conf create mode 100755 daemon/examples/sync/nack/script_backup.sh create mode 100755 daemon/examples/sync/nack/script_master.sh create mode 100644 daemon/examples/sync/persistent/Makefile.am create mode 100644 daemon/examples/sync/persistent/README create mode 100644 daemon/examples/sync/persistent/node1/Makefile.am create mode 100644 daemon/examples/sync/persistent/node1/conntrackd.conf create mode 100644 daemon/examples/sync/persistent/node1/keepalived.conf create mode 100644 daemon/examples/sync/persistent/node2/Makefile.am create mode 100644 daemon/examples/sync/persistent/node2/conntrackd.conf create mode 100644 daemon/examples/sync/persistent/node2/keepalived.conf create mode 100755 daemon/examples/sync/persistent/script_backup.sh create mode 100755 daemon/examples/sync/persistent/script_master.sh create mode 100644 daemon/include/Makefile.am create mode 100644 daemon/include/alarm.h create mode 100644 daemon/include/buffer.h create mode 100644 daemon/include/cache.h create mode 100644 daemon/include/conntrackd.h create mode 100644 daemon/include/debug.h create mode 100644 daemon/include/hash.h create mode 100644 daemon/include/ignore.h create mode 100644 daemon/include/jhash.h create mode 100644 daemon/include/linux_list.h create mode 100644 daemon/include/local.h create mode 100644 daemon/include/log.h create mode 100644 daemon/include/mcast.h create mode 100644 daemon/include/network.h create mode 100644 daemon/include/slist.h create mode 100644 daemon/include/state_helper.h create mode 100644 daemon/include/sync.h create mode 100644 daemon/include/us-conntrack.h create mode 100644 daemon/src/Makefile.am create mode 100644 daemon/src/alarm.c create mode 100644 daemon/src/buffer.c create mode 100644 daemon/src/cache.c create mode 100644 daemon/src/cache_iterators.c create mode 100644 daemon/src/cache_lifetime.c create mode 100644 daemon/src/cache_timer.c create mode 100644 daemon/src/checksum.c create mode 100644 daemon/src/hash.c create mode 100644 daemon/src/ignore_pool.c create mode 100644 daemon/src/local.c create mode 100644 daemon/src/lock.c create mode 100644 daemon/src/log.c create mode 100644 daemon/src/main.c create mode 100644 daemon/src/mcast.c create mode 100644 daemon/src/netlink.c create mode 100644 daemon/src/network.c create mode 100644 daemon/src/proxy.c create mode 100644 daemon/src/read_config_lex.l create mode 100644 daemon/src/read_config_yy.y create mode 100644 daemon/src/run.c create mode 100644 daemon/src/state_helper.c create mode 100644 daemon/src/state_helper_tcp.c create mode 100644 daemon/src/stats-mode.c create mode 100644 daemon/src/sync-mode.c create mode 100644 daemon/src/sync-nack.c create mode 100644 daemon/src/sync-notrack.c create mode 100644 daemon/src/traffic_stats.c delete mode 100644 extensions/Makefile.am delete mode 100644 extensions/libct_proto_icmp.c delete mode 100644 extensions/libct_proto_icmp.man delete mode 100644 extensions/libct_proto_sctp.c delete mode 100644 extensions/libct_proto_tcp.c delete mode 100644 extensions/libct_proto_tcp.man delete mode 100644 extensions/libct_proto_udp.c delete mode 100644 extensions/libct_proto_udp.man delete mode 100644 include/Makefile.am delete mode 100644 include/conntrack.h delete mode 100644 include/linux_list.h delete mode 100644 src/Makefile.am delete mode 100644 src/conntrack.c delete mode 100644 test.sh (limited to 'Makefile.am') diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index d1cb6fa..0000000 --- a/AUTHORS +++ /dev/null @@ -1,2 +0,0 @@ -Pablo Neira Ayuso -Harald Welte diff --git a/ChangeLog b/ChangeLog deleted file mode 100644 index 1524ef6..0000000 --- a/ChangeLog +++ /dev/null @@ -1,243 +0,0 @@ -2006-03-20 - - o fix ICMP protocol extension parse callback - -2006-01-15 - - o Added missing parameters to set the ports of an expectation tuple - o Add support to filter dumped entries. - ie: conntrack -L -p tcp --orig-port-dst 993 - display all the connections to IMAPS servers - conntrack -L -m 2 - display all the connection marked with 2 - o Bumped version to 1.00beta2 - -2005-12-26 - - o add IPv6 support: main change - o removed dead code: iptables_insmod and get_modprobe - o compact the commands vs. options table - o move working vars from the stack to the BSS section - o update manpage - o Bumped version to 1.0beta1 - - o check address family mismatch - o fix incomplete copying IPv6 addresses - -2005-12-19 - - o We only support ipv4 at the moment: set l3protonum to AF_INET - o Minor changes to prepare upcoming ipv6 support - -2005-12-03 - - o Add support to filter events. ie: -p tcp --orig-port-dst 80 in - conjuction with -E to get all the requests to HTTP servers - o Update manpage - o Missing static function declaration in the protocol handlers - o Use protocol flags defined in libnetfilter_conntrack - o Bumped version to 0.991 - -2005-11-22 - - o Fix oversized number of options - -2005-11-11 - - o don't check for kernel header path in configure, since we don't use - kernel headers - o don't check for libnfnetlink, we don't use it directly - o move plugins into pkglibdir - o remove 'lib' prefix of plugins, they're not really libraries - o remove version information from plugin filenames - o Bumped version to 0.99 -2005-11-09 - - o set status to zero, libnetfilter_conntrack now activate - IPS_CONFIRMED since all conntrack in hash must be confirmed. - o Bumped version to 0.98 - -2005-11-08 - - o Fix warnings generated by gcc -Wall - o Fix conntrack exit value at error - o Replace obsolete inet_addr by inet_aton - -2005-11-05 - - o Improved conntrack -h output - o add htons for icmp id. - - o -t and -u are optional at update. - o Fixed versioning :( - o Bumped version to 0.97 - -2005-11-03 - - o Use extra 'data' argument of nfct_register_callback() function that - I've introduced in libetfilter_conntrack. - - o moves conntrack tool from bin to sbin directory since this - application is an administration utility and it requires uid==0 or - CAP_NET_ADMIN - - o check if --state missing when -p is passed - o command type is passed to final_check: checkings based on the - command can be done now. - o kill duplicated definition of IPS_* bits: Already present in - libnetfilter_conntrack. - o Move action and command enum to conntrack.h - o kill NIPQUAD macro - o make conntrack handler cth static. - o Bumped version to 0.96 - -2005-11-01 - - o Fix error message describing illegal option -E -i - o -D -i ID requires tuple information: Display an error message - o Use NFCT_ALL_CT_GROUPS flag instead of NFCT_ALL_GROUPS - o Event mask doesn't make sense for expectations, kill dead code - o Bumped version to 0.95 - - o Fix wrong formating in conntrack -h - -2005-10-30 - - Special thanks to Deti Fiegl from the Leibniz Supercomputing Centre in - Munich, Germany for providing the "fast" hardware to reproduce - spurious bugs ;) - - o Replace misleading message "Not enough memory" by "Can't open handler" - o New option -i for expectation dumping: conntrack -L expect [-i] - o sed 's/VERSION/CONNTRACK_VERSION/g' - o Fix nfct_open flags, now uses NFCT_ALL_GROUPS when needed - o Bumped version to 0.94 - -2005-10-28 - - o New option -i for dumping: conntrack -L [-i] - o Fixed warning in findproto due to a stupid wrong type definition - o sed 's/nfct_set_callback/nfct_register_callback/g' - o killed the 'retry' logic, *sigh* it is broken in some cases - o killed broken and unneeded protocol handler destructors (fini) - o killed unregister_proto - o Fixed code indentation in the command selector - o Bumped version to 0.93 - -2005-10-27 - - o Use conntrack VERSION instead of the old LIBCT_VERSION - o proto_list and lib_dir are now static - o kill dead code: function dump_tuple - o Bumped version to 0.92 - -2005-10-25 - - o Add missing autogen.sh file - -2005-10-24 - - o use NFCT_ANY_GROUP flag in nfct_open() - -2005-10-21 - - o Bumped version to 0.90 - o Add support for id and marks - -2005-10-20 - - o Kill some more files that generated by the autocrap - o Resync with the lastest libnetfilter_conntrack API changes - -2005-10-16 - - o Rename libct_proto.h to conntrack.h - o Remove config.h.in from svn, it's autogenerated by the autocrap :) - o Remove dead functions in the SCTP protocol helper - -2005-10-14 - - o Kill config.h.in, it's generated by the autocrap - o The conntrack tool now uses libnetfilter_conntrack :) - o libct.c has been killed, now it's in libnetfilter_conntrack - o Check if you're root or CAP_NET_ADMIN - o Bumped version number to 0.86 - -2005-10-07 - - o Fixed ICMP options - - o Multiple fixes for the ICMP protocol handler - o Fix ICMP output: wrong output. type and code were set to zero. - -2005-10-05 - - o Fix up counters - o Fix up compilation (IPS_* stuff missing), still need a proper fix - o Bumped version number to 0.82 - -2005-09-24 - - o Get rid of C++ style comments - o Remove remaining bits of "-A --action", group-mask and dump-mask - o Clean up #include's - o Fix double-free when exiting via signal handler (Ctrl+C) - o Add "version" member to plugins - o Fix some Endianness issues when printing CTA_STATUS - -2005-08-31 - - o Fix packet and bytes counters (use __be64_to_cpu) - o Fix ip_conntrack_netlink load-on-demand - -2005-07-12 - - o Use conntrack netlink attributes: Major change - o Kill action setting: Mask based dumping - o Fix ChangeLog - -2005-05-23 - - o Fixed syntax error (tab/space issue) in help message - o Fixed getopt handling on big endian machines - o Fixed possible future read-over-end-of-array in TCP extension - o Add manpage - o Add missing space at output of libct_proto_icmp.c - o Add status bits that were introduced in 2.6.11 - o Add SCTP extension - o Add support for expect creation - o Bump version number to 0.63 - -2005-05-17 - - o Added descriptive error messages. - o Fix wrong flags check in [tcp|udp] proto helpers. - -2005-05-16 - - o Implemented ICMP proto helper - o Added help() and final_check() functions for proto helpers. - -2005-05-01 - - o Created changelog file - o Deleted libctnetlink.h and libnfnetlink.h from the include/ dir. - o Added support for version (-V) and help (-h) - o Added event mask based support - o Added GPLv2 headers - o Use fprintf instead of printf - o Defined print_tuple and print_proto output interfaces - o ctnl_[get|del]_conntrack handles return value from kernel via msgerr - o Added support for conntrack table flushing - o Added test case file (test.sh) - o Improve dump output - - - o Autoconf stuff for conntrack + some pablo's modifications. - o Fixed packet counters formatting (use %llu instead of %lu) - -2005-04-25 - - o Added support for mask based event dumping - o Added support for mask based event notification - o On-demand autoload of ip_conntrack_netlink diff --git a/INSTALL b/INSTALL deleted file mode 100644 index 54caf7c..0000000 --- a/INSTALL +++ /dev/null @@ -1,229 +0,0 @@ -Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software -Foundation, Inc. - - This file is free documentation; the Free Software Foundation gives -unlimited permission to copy, distribute and modify it. - -Basic Installation -================== - - These are generic installation instructions. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, and a -file `config.log' containing compiler output (useful mainly for -debugging `configure'). - - It can also use an optional file (typically called `config.cache' -and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. (Caching is -disabled by default to prevent problems with accidental use of stale -cache files.) - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If you are using the cache, and at -some point `config.cache' contains results you don't want to keep, you -may remove or edit it. - - The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You only need -`configure.ac' if you want to change it or regenerate `configure' using -a newer version of `autoconf'. - -The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. If you're - using `csh' on an old version of System V, you might need to type - `sh ./configure' instead to prevent `csh' from trying to execute - `configure' itself. - - Running `configure' takes awhile. While running, it prints some - messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package. - - 4. Type `make install' to install the programs and any data files and - documentation. - - 5. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - -Compilers and Options -===================== - - Some systems require unusual options for compilation or linking that -the `configure' script does not know about. Run `./configure --help' -for details on some of the pertinent environment variables. - - You can give `configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: - - ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix - - *Note Defining Variables::, for more details. - -Compiling For Multiple Architectures -==================================== - - You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you must use a version of `make' that -supports the `VPATH' variable, such as GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. - - If you have to use a `make' that does not support the `VPATH' -variable, you have to compile the package for one architecture at a -time in the source code directory. After you have installed the -package for one architecture, use `make distclean' before reconfiguring -for another architecture. - -Installation Names -================== - - By default, `make install' will install the package's files in -`/usr/local/bin', `/usr/local/man', etc. You can specify an -installation prefix other than `/usr/local' by giving `configure' the -option `--prefix=PATH'. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -give `configure' the option `--exec-prefix=PATH', the package will use -PATH as the prefix for installing programs and libraries. -Documentation and other data files will still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=PATH' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - -Optional Features -================= - - Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - -Specifying the System Type -========================== - - There may be some features `configure' cannot figure out -automatically, but needs to determine by the type of machine the package -will run on. Usually, assuming the package is built to be run on the -_same_ architectures, `configure' can figure that out, but if it prints -a message saying it cannot guess the machine type, give it the -`--build=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name which has the form: - - CPU-COMPANY-SYSTEM - -where SYSTEM can have one of these forms: - - OS KERNEL-OS - - See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the machine type. - - If you are _building_ compiler tools for cross-compiling, you should -use the `--target=TYPE' option to select the type of system they will -produce code for. - - If you want to _use_ a cross compiler, that generates code for a -platform different from the build platform, you should specify the -"host" platform (i.e., that on which the generated programs will -eventually be run) with `--host=TYPE'. - -Sharing Defaults -================ - - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Defining Variables -================== - - Variables not defined in a site shell script can be set in the -environment passed to `configure'. However, some packages may run -configure again during the build, and the customized values of these -variables may be lost. In order to avoid this problem, you should set -them in the `configure' command line, using `VAR=value'. For example: - - ./configure CC=/usr/local2/bin/gcc - -will cause the specified gcc to be used as the C compiler (unless it is -overridden in the site shell script). - -`configure' Invocation -====================== - - `configure' recognizes the following options to control how it -operates. - -`--help' -`-h' - Print a summary of the options to `configure', and exit. - -`--version' -`-V' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`--cache-file=FILE' - Enable the cache: use and save the results of the tests in FILE, - traditionally `config.cache'. FILE defaults to `/dev/null' to - disable caching. - -`--config-cache' -`-C' - Alias for `--cache-file=config.cache'. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`configure' also accepts some other, not widely useful, options. Run -`configure --help' for more details. - diff --git a/Make_global.am b/Make_global.am deleted file mode 100644 index 685add7..0000000 --- a/Make_global.am +++ /dev/null @@ -1 +0,0 @@ -INCLUDES=$(all_includes) -I$(top_srcdir)/include diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index d3b4ceb..0000000 --- a/Makefile.am +++ /dev/null @@ -1,21 +0,0 @@ -include Make_global.am - -# not a GNU package. You can remove this line, if -# have all needed files, that a GNU package needs -AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 - -man_MANS = conntrack.8 - -EXTRA_DIST = $(man_MANS) Make_global.am debian - -SUBDIRS = src extensions -DIST_SUBDIRS = include src extensions -LINKOPTS = -ldl -lnetfilter_conntrack -AM_CFLAGS = -g - -$(OBJECTS): libtool -libtool: $(LIBTOOL_DEPS) - $(SHELL) ./config.status --recheck - -dist-hook: - rm -rf `find $(distdir)/debian -name .svn` diff --git a/README b/README new file mode 100644 index 0000000..314a2e4 --- /dev/null +++ b/README @@ -0,0 +1,17 @@ +This package contains two subdirectories: + +cli (command line interface) +============================ +This subdirectory contains the command line tool `conntrack' that provides an +userspace interface to the connection tracking system. This tool let system +administrators perform different actions against the connection tracking +table. For more information see the manpage conntrack(8). + +daemon +====== +This subdirectory contains the userspace connection tracking daemon so-called +'conntrackd`. This daemon maintains a copy of the connection tracking table +in userspace. It is highly configurable and easily extensible. Currently it +covers the specific aspects of stateful GNU/Linux firewalls to enable high +availability solutions and can be used as statistics collector of the firewall +use. diff --git a/autogen.sh b/autogen.sh deleted file mode 100755 index e76d3ef..0000000 --- a/autogen.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -run () -{ - echo "running: $*" - eval $* - - if test $? != 0 ; then - echo "error: while running '$*'" - exit 1 - fi -} - -run aclocal -run libtoolize -f -#run autoheader -run automake -a -run autoconf diff --git a/cli/AUTHORS b/cli/AUTHORS new file mode 100644 index 0000000..d1cb6fa --- /dev/null +++ b/cli/AUTHORS @@ -0,0 +1,2 @@ +Pablo Neira Ayuso +Harald Welte diff --git a/cli/ChangeLog b/cli/ChangeLog new file mode 100644 index 0000000..1524ef6 --- /dev/null +++ b/cli/ChangeLog @@ -0,0 +1,243 @@ +2006-03-20 + + o fix ICMP protocol extension parse callback + +2006-01-15 + + o Added missing parameters to set the ports of an expectation tuple + o Add support to filter dumped entries. + ie: conntrack -L -p tcp --orig-port-dst 993 + display all the connections to IMAPS servers + conntrack -L -m 2 + display all the connection marked with 2 + o Bumped version to 1.00beta2 + +2005-12-26 + + o add IPv6 support: main change + o removed dead code: iptables_insmod and get_modprobe + o compact the commands vs. options table + o move working vars from the stack to the BSS section + o update manpage + o Bumped version to 1.0beta1 + + o check address family mismatch + o fix incomplete copying IPv6 addresses + +2005-12-19 + + o We only support ipv4 at the moment: set l3protonum to AF_INET + o Minor changes to prepare upcoming ipv6 support + +2005-12-03 + + o Add support to filter events. ie: -p tcp --orig-port-dst 80 in + conjuction with -E to get all the requests to HTTP servers + o Update manpage + o Missing static function declaration in the protocol handlers + o Use protocol flags defined in libnetfilter_conntrack + o Bumped version to 0.991 + +2005-11-22 + + o Fix oversized number of options + +2005-11-11 + + o don't check for kernel header path in configure, since we don't use + kernel headers + o don't check for libnfnetlink, we don't use it directly + o move plugins into pkglibdir + o remove 'lib' prefix of plugins, they're not really libraries + o remove version information from plugin filenames + o Bumped version to 0.99 +2005-11-09 + + o set status to zero, libnetfilter_conntrack now activate + IPS_CONFIRMED since all conntrack in hash must be confirmed. + o Bumped version to 0.98 + +2005-11-08 + + o Fix warnings generated by gcc -Wall + o Fix conntrack exit value at error + o Replace obsolete inet_addr by inet_aton + +2005-11-05 + + o Improved conntrack -h output + o add htons for icmp id. + + o -t and -u are optional at update. + o Fixed versioning :( + o Bumped version to 0.97 + +2005-11-03 + + o Use extra 'data' argument of nfct_register_callback() function that + I've introduced in libetfilter_conntrack. + + o moves conntrack tool from bin to sbin directory since this + application is an administration utility and it requires uid==0 or + CAP_NET_ADMIN + + o check if --state missing when -p is passed + o command type is passed to final_check: checkings based on the + command can be done now. + o kill duplicated definition of IPS_* bits: Already present in + libnetfilter_conntrack. + o Move action and command enum to conntrack.h + o kill NIPQUAD macro + o make conntrack handler cth static. + o Bumped version to 0.96 + +2005-11-01 + + o Fix error message describing illegal option -E -i + o -D -i ID requires tuple information: Display an error message + o Use NFCT_ALL_CT_GROUPS flag instead of NFCT_ALL_GROUPS + o Event mask doesn't make sense for expectations, kill dead code + o Bumped version to 0.95 + + o Fix wrong formating in conntrack -h + +2005-10-30 + + Special thanks to Deti Fiegl from the Leibniz Supercomputing Centre in + Munich, Germany for providing the "fast" hardware to reproduce + spurious bugs ;) + + o Replace misleading message "Not enough memory" by "Can't open handler" + o New option -i for expectation dumping: conntrack -L expect [-i] + o sed 's/VERSION/CONNTRACK_VERSION/g' + o Fix nfct_open flags, now uses NFCT_ALL_GROUPS when needed + o Bumped version to 0.94 + +2005-10-28 + + o New option -i for dumping: conntrack -L [-i] + o Fixed warning in findproto due to a stupid wrong type definition + o sed 's/nfct_set_callback/nfct_register_callback/g' + o killed the 'retry' logic, *sigh* it is broken in some cases + o killed broken and unneeded protocol handler destructors (fini) + o killed unregister_proto + o Fixed code indentation in the command selector + o Bumped version to 0.93 + +2005-10-27 + + o Use conntrack VERSION instead of the old LIBCT_VERSION + o proto_list and lib_dir are now static + o kill dead code: function dump_tuple + o Bumped version to 0.92 + +2005-10-25 + + o Add missing autogen.sh file + +2005-10-24 + + o use NFCT_ANY_GROUP flag in nfct_open() + +2005-10-21 + + o Bumped version to 0.90 + o Add support for id and marks + +2005-10-20 + + o Kill some more files that generated by the autocrap + o Resync with the lastest libnetfilter_conntrack API changes + +2005-10-16 + + o Rename libct_proto.h to conntrack.h + o Remove config.h.in from svn, it's autogenerated by the autocrap :) + o Remove dead functions in the SCTP protocol helper + +2005-10-14 + + o Kill config.h.in, it's generated by the autocrap + o The conntrack tool now uses libnetfilter_conntrack :) + o libct.c has been killed, now it's in libnetfilter_conntrack + o Check if you're root or CAP_NET_ADMIN + o Bumped version number to 0.86 + +2005-10-07 + + o Fixed ICMP options + + o Multiple fixes for the ICMP protocol handler + o Fix ICMP output: wrong output. type and code were set to zero. + +2005-10-05 + + o Fix up counters + o Fix up compilation (IPS_* stuff missing), still need a proper fix + o Bumped version number to 0.82 + +2005-09-24 + + o Get rid of C++ style comments + o Remove remaining bits of "-A --action", group-mask and dump-mask + o Clean up #include's + o Fix double-free when exiting via signal handler (Ctrl+C) + o Add "version" member to plugins + o Fix some Endianness issues when printing CTA_STATUS + +2005-08-31 + + o Fix packet and bytes counters (use __be64_to_cpu) + o Fix ip_conntrack_netlink load-on-demand + +2005-07-12 + + o Use conntrack netlink attributes: Major change + o Kill action setting: Mask based dumping + o Fix ChangeLog + +2005-05-23 + + o Fixed syntax error (tab/space issue) in help message + o Fixed getopt handling on big endian machines + o Fixed possible future read-over-end-of-array in TCP extension + o Add manpage + o Add missing space at output of libct_proto_icmp.c + o Add status bits that were introduced in 2.6.11 + o Add SCTP extension + o Add support for expect creation + o Bump version number to 0.63 + +2005-05-17 + + o Added descriptive error messages. + o Fix wrong flags check in [tcp|udp] proto helpers. + +2005-05-16 + + o Implemented ICMP proto helper + o Added help() and final_check() functions for proto helpers. + +2005-05-01 + + o Created changelog file + o Deleted libctnetlink.h and libnfnetlink.h from the include/ dir. + o Added support for version (-V) and help (-h) + o Added event mask based support + o Added GPLv2 headers + o Use fprintf instead of printf + o Defined print_tuple and print_proto output interfaces + o ctnl_[get|del]_conntrack handles return value from kernel via msgerr + o Added support for conntrack table flushing + o Added test case file (test.sh) + o Improve dump output + + + o Autoconf stuff for conntrack + some pablo's modifications. + o Fixed packet counters formatting (use %llu instead of %lu) + +2005-04-25 + + o Added support for mask based event dumping + o Added support for mask based event notification + o On-demand autoload of ip_conntrack_netlink diff --git a/cli/INSTALL b/cli/INSTALL new file mode 100644 index 0000000..54caf7c --- /dev/null +++ b/cli/INSTALL @@ -0,0 +1,229 @@ +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/cli/Make_global.am b/cli/Make_global.am new file mode 100644 index 0000000..685add7 --- /dev/null +++ b/cli/Make_global.am @@ -0,0 +1 @@ +INCLUDES=$(all_includes) -I$(top_srcdir)/include diff --git a/cli/Makefile.am b/cli/Makefile.am new file mode 100644 index 0000000..d3b4ceb --- /dev/null +++ b/cli/Makefile.am @@ -0,0 +1,21 @@ +include Make_global.am + +# not a GNU package. You can remove this line, if +# have all needed files, that a GNU package needs +AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 + +man_MANS = conntrack.8 + +EXTRA_DIST = $(man_MANS) Make_global.am debian + +SUBDIRS = src extensions +DIST_SUBDIRS = include src extensions +LINKOPTS = -ldl -lnetfilter_conntrack +AM_CFLAGS = -g + +$(OBJECTS): libtool +libtool: $(LIBTOOL_DEPS) + $(SHELL) ./config.status --recheck + +dist-hook: + rm -rf `find $(distdir)/debian -name .svn` diff --git a/cli/autogen.sh b/cli/autogen.sh new file mode 100755 index 0000000..e76d3ef --- /dev/null +++ b/cli/autogen.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +run () +{ + echo "running: $*" + eval $* + + if test $? != 0 ; then + echo "error: while running '$*'" + exit 1 + fi +} + +run aclocal +run libtoolize -f +#run autoheader +run automake -a +run autoconf diff --git a/cli/configure.in b/cli/configure.in new file mode 100644 index 0000000..1b1b391 --- /dev/null +++ b/cli/configure.in @@ -0,0 +1,72 @@ +AC_INIT + +AC_CANONICAL_SYSTEM + +AM_INIT_AUTOMAKE(conntrack, 1.00beta2) + +AC_PROG_CC +AM_PROG_LIBTOOL +AC_PROG_INSTALL +AC_PROG_LN_S + +case $target in +*-*-linux*) ;; +*) AC_MSG_ERROR([Linux only, dude!]);; +esac + +dnl Dependencies +LIBNFCONNTRACK_REQUIRED=0.0.31 + +AC_CHECK_LIB(dl, dlopen) + +PKG_CHECK_MODULES(LIBNFCONNTRACK, libnetfilter_conntrack >= $LIBNFCONNTRACK_REQUIRED,, + AC_MSG_ERROR(Cannot find libnetfilter_conntrack >= $LIBNFCONNTRACK_REQUIRED)) + +AC_CHECK_HEADERS(arpa/inet.h) +dnl check for inet_pton +AC_CHECK_FUNCS(inet_pton) +dnl Some systems have it, but not IPv6 +if test "$ac_cv_func_inet_pton" = "yes" ; then +AC_MSG_CHECKING(if inet_pton supports IPv6) +AC_TRY_RUN( + [ +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +int main() + { + struct in6_addr addr6; + if (inet_pton(AF_INET6, "::1", &addr6) < 1) + exit(1); + else + exit(0); + } + ], [ AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED(HAVE_INET_PTON_IPV6, 1, [Define to 1 if inet_pton supports IPv6.]) + ], AC_MSG_RESULT(no), AC_MSG_RESULT(no)) +fi + +dnl-------------------------------- + +if test ! -z "$libdir"; then + MODULE_DIR="\\\"$libdir/conntrack/\\\"" + CFLAGS="$CFLAGS -DCONNTRACK_LIB_DIR=$MODULE_DIR" +fi + +dnl-------------------------------- + +CFLAGS="$CFLAGS $LIBNFCONNTRACK_CFLAGS" +CONNTRACK_LIBS="$LIBNFCONNTRACK_LIBS" + +AC_SUBST(CONNTRACK_LIBS) + +AC_OUTPUT(Makefile src/Makefile extensions/Makefile include/Makefile) diff --git a/cli/conntrack.8 b/cli/conntrack.8 new file mode 100644 index 0000000..307180b --- /dev/null +++ b/cli/conntrack.8 @@ -0,0 +1,142 @@ +.TH CONNTRACK 8 "Jun 23, 2005" "" "" + +.\" Man page written by Harald Welte . diff --git a/cli/extensions/Makefile.am b/cli/extensions/Makefile.am new file mode 100644 index 0000000..5366ee3 --- /dev/null +++ b/cli/extensions/Makefile.am @@ -0,0 +1,16 @@ +include $(top_srcdir)/Make_global.am + +AM_CFLAGS=-fPIC -Wall +LIBS= + +pkglib_LTLIBRARIES = ct_proto_tcp.la ct_proto_udp.la \ + ct_proto_icmp.la ct_proto_sctp.la + +ct_proto_tcp_la_SOURCES = libct_proto_tcp.c +ct_proto_tcp_la_LDFLAGS = -module -avoid-version +ct_proto_udp_la_SOURCES = libct_proto_udp.c +ct_proto_udp_la_LDFLAGS = -module -avoid-version +ct_proto_icmp_la_SOURCES = libct_proto_icmp.c +ct_proto_icmp_la_LDFLAGS = -module -avoid-version +ct_proto_sctp_la_SOURCES = libct_proto_sctp.c +ct_proto_sctp_la_LDFLAGS = -module -avoid-version diff --git a/cli/extensions/libct_proto_icmp.c b/cli/extensions/libct_proto_icmp.c new file mode 100644 index 0000000..e7cb04d --- /dev/null +++ b/cli/extensions/libct_proto_icmp.c @@ -0,0 +1,108 @@ +/* + * (C) 2005 by Pablo Neira Ayuso + * Harald Welte + * + * 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 +#include +#include +#include /* For htons */ +#include +#include +#include +#include "conntrack.h" + +static struct option opts[] = { + {"icmp-type", 1, 0, '1'}, + {"icmp-code", 1, 0, '2'}, + {"icmp-id", 1, 0, '3'}, + {0, 0, 0, 0} +}; + +static void help() +{ + fprintf(stdout, "--icmp-type icmp type\n"); + fprintf(stdout, "--icmp-code icmp code\n"); + fprintf(stdout, "--icmp-id icmp id\n"); +} + +/* Add 1; spaces filled with 0. */ +static u_int8_t invmap[] + = { [ICMP_ECHO] = ICMP_ECHOREPLY + 1, + [ICMP_ECHOREPLY] = ICMP_ECHO + 1, + [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1, + [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1, + [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1, + [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1, + [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1, + [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1}; + +static int parse(char c, char *argv[], + struct nfct_tuple *orig, + struct nfct_tuple *reply, + struct nfct_tuple *exptuple, + struct nfct_tuple *mask, + union nfct_protoinfo *proto, + unsigned int *flags) +{ + switch(c) { + case '1': + if (optarg) { + orig->l4dst.icmp.type = atoi(optarg); + reply->l4dst.icmp.type = + invmap[orig->l4dst.icmp.type] - 1; + *flags |= ICMP_TYPE; + } + break; + case '2': + if (optarg) { + orig->l4dst.icmp.code = atoi(optarg); + reply->l4dst.icmp.code = 0; + *flags |= ICMP_CODE; + } + break; + case '3': + if (optarg) { + orig->l4src.icmp.id = htons(atoi(optarg)); + reply->l4dst.icmp.id = 0; + *flags |= ICMP_ID; + } + break; + } + return 1; +} + +static int final_check(unsigned int flags, + unsigned int command, + struct nfct_tuple *orig, + struct nfct_tuple *reply) +{ + if (!(flags & ICMP_TYPE)) + return 0; + else if (!(flags & ICMP_CODE)) + return 0; + + return 1; +} + +static struct ctproto_handler icmp = { + .name = "icmp", + .protonum = IPPROTO_ICMP, + .parse_opts = parse, + .final_check = final_check, + .help = help, + .opts = opts, + .version = VERSION, +}; + +static void __attribute__ ((constructor)) init(void); + +static void init(void) +{ + register_proto(&icmp); +} diff --git a/cli/extensions/libct_proto_icmp.man b/cli/extensions/libct_proto_icmp.man new file mode 100644 index 0000000..3b860d0 --- /dev/null +++ b/cli/extensions/libct_proto_icmp.man @@ -0,0 +1,10 @@ +This module matches on ICMP-specific fields. +.TP +.BI "--icmp-type " "TYPE" +ICMP Type. Has to be specified numerically. +.TP +.BI "--icmp-code " "CODE" +ICMP Code. Has to be specified numerically. +.TP +.BI "--icmp-id " "ID" +ICMP Id. Has to be specified numerically. diff --git a/cli/extensions/libct_proto_sctp.c b/cli/extensions/libct_proto_sctp.c new file mode 100644 index 0000000..1c8f0d1 --- /dev/null +++ b/cli/extensions/libct_proto_sctp.c @@ -0,0 +1,164 @@ +/* + * (C) 2005 by Harald Welte + * 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. + * + */ +#include +#include +#include +#include +#include /* For htons */ +#include "conntrack.h" +#include +#include + +static struct option opts[] = { + {"orig-port-src", 1, 0, '1'}, + {"orig-port-dst", 1, 0, '2'}, + {"reply-port-src", 1, 0, '3'}, + {"reply-port-dst", 1, 0, '4'}, + {"state", 1, 0, '5'}, + {"tuple-port-src", 1, 0, '6'}, + {"tuple-port-dst", 1, 0, '7'}, + {0, 0, 0, 0} +}; + +static const char *states[] = { + "NONE", + "CLOSED", + "COOKIE_WAIT", + "COOKIE_ECHOED", + "ESTABLISHED", + "SHUTDOWN_SENT", + "SHUTDOWN_RECV", + "SHUTDOWN_ACK_SENT", +}; + +static void help() +{ + fprintf(stdout, "--orig-port-src original source port\n"); + fprintf(stdout, "--orig-port-dst original destination port\n"); + fprintf(stdout, "--reply-port-src reply source port\n"); + fprintf(stdout, "--reply-port-dst reply destination port\n"); + fprintf(stdout, "--state SCTP state, fe. ESTABLISHED\n"); + fprintf(stdout, "--tuple-port-src expectation tuple src port\n"); + fprintf(stdout, "--tuple-port-src expectation tuple dst port\n"); +} + +static int parse_options(char c, char *argv[], + struct nfct_tuple *orig, + struct nfct_tuple *reply, + struct nfct_tuple *exptuple, + struct nfct_tuple *mask, + union nfct_protoinfo *proto, + unsigned int *flags) +{ + switch(c) { + case '1': + if (optarg) { + orig->l4src.sctp.port = htons(atoi(optarg)); + *flags |= SCTP_ORIG_SPORT; + } + break; + case '2': + if (optarg) { + orig->l4dst.sctp.port = htons(atoi(optarg)); + *flags |= SCTP_ORIG_DPORT; + } + break; + case '3': + if (optarg) { + reply->l4src.sctp.port = htons(atoi(optarg)); + *flags |= SCTP_REPL_SPORT; + } + break; + case '4': + if (optarg) { + reply->l4dst.sctp.port = htons(atoi(optarg)); + *flags |= SCTP_REPL_DPORT; + } + break; + case '5': + if (optarg) { + int i; + for (i=0; i<10; i++) { + if (strcmp(optarg, states[i]) == 0) { + /* FIXME: Add state to + * nfct_protoinfo + proto->sctp.state = i; */ + break; + } + } + if (i == 10) { + printf("doh?\n"); + return 0; + } + *flags |= SCTP_STATE; + } + break; + case '6': + if (optarg) { + exptuple->l4src.sctp.port = htons(atoi(optarg)); + *flags |= SCTP_EXPTUPLE_SPORT; + } + break; + case '7': + if (optarg) { + exptuple->l4dst.sctp.port = htons(atoi(optarg)); + *flags |= SCTP_EXPTUPLE_DPORT; + } + + } + return 1; +} + +static int final_check(unsigned int flags, + unsigned int command, + struct nfct_tuple *orig, + struct nfct_tuple *reply) +{ + int ret = 0; + + if ((flags & (SCTP_ORIG_SPORT|SCTP_ORIG_DPORT)) + && !(flags & (SCTP_REPL_SPORT|SCTP_REPL_DPORT))) { + reply->l4src.sctp.port = orig->l4dst.sctp.port; + reply->l4dst.sctp.port = orig->l4src.sctp.port; + ret = 1; + } else if (!(flags & (SCTP_ORIG_SPORT|SCTP_ORIG_DPORT)) + && (flags & (SCTP_REPL_SPORT|SCTP_REPL_DPORT))) { + orig->l4src.sctp.port = reply->l4dst.sctp.port; + orig->l4dst.sctp.port = reply->l4src.sctp.port; + ret = 1; + } + if ((flags & (SCTP_ORIG_SPORT|SCTP_ORIG_DPORT)) + && ((flags & (SCTP_REPL_SPORT|SCTP_REPL_DPORT)))) + ret = 1; + + /* --state is missing and we are trying to create a conntrack */ + if (ret && (command & CT_CREATE) && (!(flags & SCTP_STATE))) + ret = 0; + + return ret; +} + +static struct ctproto_handler sctp = { + .name = "sctp", + .protonum = IPPROTO_SCTP, + .parse_opts = parse_options, + .final_check = final_check, + .help = help, + .opts = opts, + .version = VERSION, +}; + +static void __attribute__ ((constructor)) init(void); + +static void init(void) +{ + register_proto(&sctp); +} diff --git a/cli/extensions/libct_proto_tcp.c b/cli/extensions/libct_proto_tcp.c new file mode 100644 index 0000000..ee24206 --- /dev/null +++ b/cli/extensions/libct_proto_tcp.c @@ -0,0 +1,180 @@ +/* + * (C) 2005 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 +#include +#include +#include +#include /* For htons */ +#include +#include + +#include "conntrack.h" + +static struct option opts[] = { + {"orig-port-src", 1, 0, '1'}, + {"orig-port-dst", 1, 0, '2'}, + {"reply-port-src", 1, 0, '3'}, + {"reply-port-dst", 1, 0, '4'}, + {"mask-port-src", 1, 0, '5'}, + {"mask-port-dst", 1, 0, '6'}, + {"state", 1, 0, '7'}, + {"tuple-port-src", 1, 0, '8'}, + {"tuple-port-dst", 1, 0, '9'}, + {0, 0, 0, 0} +}; + +static const char *states[] = { + "NONE", + "SYN_SENT", + "SYN_RECV", + "ESTABLISHED", + "FIN_WAIT", + "CLOSE_WAIT", + "LAST_ACK", + "TIME_WAIT", + "CLOSE", + "LISTEN" +}; + +static void help() +{ + fprintf(stdout, "--orig-port-src original source port\n"); + fprintf(stdout, "--orig-port-dst original destination port\n"); + fprintf(stdout, "--reply-port-src reply source port\n"); + fprintf(stdout, "--reply-port-dst reply destination port\n"); + fprintf(stdout, "--mask-port-src mask source port\n"); + fprintf(stdout, "--mask-port-dst mask destination port\n"); + fprintf(stdout, "--tuple-port-src expectation tuple src port\n"); + fprintf(stdout, "--tuple-port-src expectation tuple dst port\n"); + fprintf(stdout, "--state TCP state, fe. ESTABLISHED\n"); +} + +static int parse_options(char c, char *argv[], + struct nfct_tuple *orig, + struct nfct_tuple *reply, + struct nfct_tuple *exptuple, + struct nfct_tuple *mask, + union nfct_protoinfo *proto, + unsigned int *flags) +{ + switch(c) { + case '1': + if (optarg) { + orig->l4src.tcp.port = htons(atoi(optarg)); + *flags |= TCP_ORIG_SPORT; + } + break; + case '2': + if (optarg) { + orig->l4dst.tcp.port = htons(atoi(optarg)); + *flags |= TCP_ORIG_DPORT; + } + break; + case '3': + if (optarg) { + reply->l4src.tcp.port = htons(atoi(optarg)); + *flags |= TCP_REPL_SPORT; + } + break; + case '4': + if (optarg) { + reply->l4dst.tcp.port = htons(atoi(optarg)); + *flags |= TCP_REPL_DPORT; + } + break; + case '5': + if (optarg) { + mask->l4src.tcp.port = htons(atoi(optarg)); + *flags |= TCP_MASK_SPORT; + } + break; + case '6': + if (optarg) { + mask->l4dst.tcp.port = htons(atoi(optarg)); + *flags |= TCP_MASK_DPORT; + } + break; + case '7': + if (optarg) { + int i; + for (i=0; i<10; i++) { + if (strcmp(optarg, states[i]) == 0) { + proto->tcp.state = i; + break; + } + } + if (i == 10) { + printf("doh?\n"); + return 0; + } + *flags |= TCP_STATE; + } + break; + case '8': + if (optarg) { + exptuple->l4src.tcp.port = htons(atoi(optarg)); + *flags |= TCP_EXPTUPLE_SPORT; + } + break; + case '9': + if (optarg) { + exptuple->l4dst.tcp.port = htons(atoi(optarg)); + *flags |= TCP_EXPTUPLE_DPORT; + } + break; + } + return 1; +} + +static int final_check(unsigned int flags, + unsigned int command, + struct nfct_tuple *orig, + struct nfct_tuple *reply) +{ + int ret = 0; + + if ((flags & (TCP_ORIG_SPORT|TCP_ORIG_DPORT)) + && !(flags & (TCP_REPL_SPORT|TCP_REPL_DPORT))) { + reply->l4src.tcp.port = orig->l4dst.tcp.port; + reply->l4dst.tcp.port = orig->l4src.tcp.port; + ret = 1; + } else if (!(flags & (TCP_ORIG_SPORT|TCP_ORIG_DPORT)) + && (flags & (TCP_REPL_SPORT|TCP_REPL_DPORT))) { + orig->l4src.tcp.port = reply->l4dst.tcp.port; + orig->l4dst.tcp.port = reply->l4src.tcp.port; + ret = 1; + } + if ((flags & (TCP_ORIG_SPORT|TCP_ORIG_DPORT)) + && ((flags & (TCP_REPL_SPORT|TCP_REPL_DPORT)))) + ret = 1; + + /* --state is missing and we are trying to create a conntrack */ + if (ret && (command & CT_CREATE) && (!(flags & TCP_STATE))) + ret = 0; + + return ret; +} + +static struct ctproto_handler tcp = { + .name = "tcp", + .protonum = IPPROTO_TCP, + .parse_opts = parse_options, + .final_check = final_check, + .help = help, + .opts = opts, + .version = VERSION, +}; + +static void __attribute__ ((constructor)) init(void); + +static void init(void) +{ + register_proto(&tcp); +} diff --git a/cli/extensions/libct_proto_tcp.man b/cli/extensions/libct_proto_tcp.man new file mode 100644 index 0000000..41783f8 --- /dev/null +++ b/cli/extensions/libct_proto_tcp.man @@ -0,0 +1,16 @@ +This module matches on TCP-specific fields. +.TP +.BI "--orig-port-src " "PORT" +Source port in original direction +.TP +.BI "--orig-port-dst " "PORT" +Destination port in original direction +.TP +.BI "--reply-port-src " "PORT" +Source port in reply direction +.TP +.BI "--reply-port-dst " "PORT" +Destination port in reply direction +.TP +.BI "--state " "[NONE|SYN_SENT|SYN_RECV|ESTABLISHED|FIN_WAIT|CLOSE_WAIT|LAST_ACK|TIME_WAIT|CLOSE|LISTEN]" +TCP state diff --git a/cli/extensions/libct_proto_udp.c b/cli/extensions/libct_proto_udp.c new file mode 100644 index 0000000..48079e0 --- /dev/null +++ b/cli/extensions/libct_proto_udp.c @@ -0,0 +1,141 @@ +/* + * (C) 2005 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 +#include +#include +#include /* For htons */ +#include "conntrack.h" +#include +#include + +static struct option opts[] = { + {"orig-port-src", 1, 0, '1'}, + {"orig-port-dst", 1, 0, '2'}, + {"reply-port-src", 1, 0, '3'}, + {"reply-port-dst", 1, 0, '4'}, + {"mask-port-src", 1, 0, '5'}, + {"mask-port-dst", 1, 0, '6'}, + {"tuple-port-src", 1, 0, '7'}, + {"tuple-port-dst", 1, 0, '8'}, + {0, 0, 0, 0} +}; + +static void help() +{ + fprintf(stdout, "--orig-port-src original source port\n"); + fprintf(stdout, "--orig-port-dst original destination port\n"); + fprintf(stdout, "--reply-port-src reply source port\n"); + fprintf(stdout, "--reply-port-dst reply destination port\n"); + fprintf(stdout, "--mask-port-src mask source port\n"); + fprintf(stdout, "--mask-port-dst mask destination port\n"); + fprintf(stdout, "--tuple-port-src expectation tuple src port\n"); + fprintf(stdout, "--tuple-port-src expectation tuple dst port\n"); +} + +static int parse_options(char c, char *argv[], + struct nfct_tuple *orig, + struct nfct_tuple *reply, + struct nfct_tuple *exptuple, + struct nfct_tuple *mask, + union nfct_protoinfo *proto, + unsigned int *flags) +{ + switch(c) { + case '1': + if (optarg) { + orig->l4src.udp.port = htons(atoi(optarg)); + *flags |= UDP_ORIG_SPORT; + } + break; + case '2': + if (optarg) { + orig->l4dst.udp.port = htons(atoi(optarg)); + *flags |= UDP_ORIG_DPORT; + } + break; + case '3': + if (optarg) { + reply->l4src.udp.port = htons(atoi(optarg)); + *flags |= UDP_REPL_SPORT; + } + break; + case '4': + if (optarg) { + reply->l4dst.udp.port = htons(atoi(optarg)); + *flags |= UDP_REPL_DPORT; + } + break; + case '5': + if (optarg) { + mask->l4src.udp.port = htons(atoi(optarg)); + *flags |= UDP_MASK_SPORT; + } + break; + case '6': + if (optarg) { + mask->l4dst.udp.port = htons(atoi(optarg)); + *flags |= UDP_MASK_DPORT; + } + break; + case '7': + if (optarg) { + exptuple->l4src.udp.port = htons(atoi(optarg)); + *flags |= UDP_EXPTUPLE_SPORT; + } + break; + case '8': + if (optarg) { + exptuple->l4dst.udp.port = htons(atoi(optarg)); + *flags |= UDP_EXPTUPLE_DPORT; + } + + } + return 1; +} + +static int final_check(unsigned int flags, + unsigned int command, + struct nfct_tuple *orig, + struct nfct_tuple *reply) +{ + if ((flags & (UDP_ORIG_SPORT|UDP_ORIG_DPORT)) + && !(flags & (UDP_REPL_SPORT|UDP_REPL_DPORT))) { + reply->l4src.udp.port = orig->l4dst.udp.port; + reply->l4dst.udp.port = orig->l4src.udp.port; + return 1; + } else if (!(flags & (UDP_ORIG_SPORT|UDP_ORIG_DPORT)) + && (flags & (UDP_REPL_SPORT|UDP_REPL_DPORT))) { + orig->l4src.udp.port = reply->l4dst.udp.port; + orig->l4dst.udp.port = reply->l4src.udp.port; + return 1; + } + if ((flags & (UDP_ORIG_SPORT|UDP_ORIG_DPORT)) + && ((flags & (UDP_REPL_SPORT|UDP_REPL_DPORT)))) + return 1; + + return 0; +} + +static struct ctproto_handler udp = { + .name = "udp", + .protonum = IPPROTO_UDP, + .parse_opts = parse_options, + .final_check = final_check, + .help = help, + .opts = opts, + .version = VERSION, +}; + +static void __attribute__ ((constructor)) init(void); + +static void init(void) +{ + register_proto(&udp); +} diff --git a/cli/extensions/libct_proto_udp.man b/cli/extensions/libct_proto_udp.man new file mode 100644 index 0000000..c67fedf --- /dev/null +++ b/cli/extensions/libct_proto_udp.man @@ -0,0 +1,13 @@ +This module matches on UDP-specific fields. +.TP +.BI "--orig-port-src " "PORT" +Source port in original direction +.TP +.BI "--orig-port-dst " "PORT" +Destination port in original direction +.TP +.BI "--reply-port-src " "PORT" +Source port in reply direction +.TP +.BI "--reply-port-dst " "PORT" +Destination port in reply direction diff --git a/cli/include/Makefile.am b/cli/include/Makefile.am new file mode 100644 index 0000000..ef7ce45 --- /dev/null +++ b/cli/include/Makefile.am @@ -0,0 +1,2 @@ + +noinst_HEADERS = conntrack.h linux_list.h diff --git a/cli/include/conntrack.h b/cli/include/conntrack.h new file mode 100644 index 0000000..fb3b9b6 --- /dev/null +++ b/cli/include/conntrack.h @@ -0,0 +1,160 @@ +#ifndef _CONNTRACK_H +#define _CONNTRACK_H + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#include "linux_list.h" +#include +#include + +#define PROGNAME "conntrack" + +#include +#ifndef IPPROTO_SCTP +#define IPPROTO_SCTP 132 +#endif + +enum action { + CT_NONE = 0, + + CT_LIST_BIT = 0, + CT_LIST = (1 << CT_LIST_BIT), + + CT_CREATE_BIT = 1, + CT_CREATE = (1 << CT_CREATE_BIT), + + CT_UPDATE_BIT = 2, + CT_UPDATE = (1 << CT_UPDATE_BIT), + + CT_DELETE_BIT = 3, + CT_DELETE = (1 << CT_DELETE_BIT), + + CT_GET_BIT = 4, + CT_GET = (1 << CT_GET_BIT), + + CT_FLUSH_BIT = 5, + CT_FLUSH = (1 << CT_FLUSH_BIT), + + CT_EVENT_BIT = 6, + CT_EVENT = (1 << CT_EVENT_BIT), + + CT_VERSION_BIT = 7, + CT_VERSION = (1 << CT_VERSION_BIT), + + CT_HELP_BIT = 8, + CT_HELP = (1 << CT_HELP_BIT), + + EXP_LIST_BIT = 9, + EXP_LIST = (1 << EXP_LIST_BIT), + + EXP_CREATE_BIT = 10, + EXP_CREATE = (1 << EXP_CREATE_BIT), + + EXP_DELETE_BIT = 11, + EXP_DELETE = (1 << EXP_DELETE_BIT), + + EXP_GET_BIT = 12, + EXP_GET = (1 << EXP_GET_BIT), + + EXP_FLUSH_BIT = 13, + EXP_FLUSH = (1 << EXP_FLUSH_BIT), + + EXP_EVENT_BIT = 14, + EXP_EVENT = (1 << EXP_EVENT_BIT), +}; +#define NUMBER_OF_CMD 15 + +enum options { + CT_OPT_ORIG_SRC_BIT = 0, + CT_OPT_ORIG_SRC = (1 << CT_OPT_ORIG_SRC_BIT), + + CT_OPT_ORIG_DST_BIT = 1, + CT_OPT_ORIG_DST = (1 << CT_OPT_ORIG_DST_BIT), + + CT_OPT_ORIG = (CT_OPT_ORIG_SRC | CT_OPT_ORIG_DST), + + CT_OPT_REPL_SRC_BIT = 2, + CT_OPT_REPL_SRC = (1 << CT_OPT_REPL_SRC_BIT), + + CT_OPT_REPL_DST_BIT = 3, + CT_OPT_REPL_DST = (1 << CT_OPT_REPL_DST_BIT), + + CT_OPT_REPL = (CT_OPT_REPL_SRC | CT_OPT_REPL_DST), + + CT_OPT_PROTO_BIT = 4, + CT_OPT_PROTO = (1 << CT_OPT_PROTO_BIT), + + CT_OPT_TIMEOUT_BIT = 5, + CT_OPT_TIMEOUT = (1 << CT_OPT_TIMEOUT_BIT), + + CT_OPT_STATUS_BIT = 6, + CT_OPT_STATUS = (1 << CT_OPT_STATUS_BIT), + + CT_OPT_ZERO_BIT = 7, + CT_OPT_ZERO = (1 << CT_OPT_ZERO_BIT), + + CT_OPT_EVENT_MASK_BIT = 8, + CT_OPT_EVENT_MASK = (1 << CT_OPT_EVENT_MASK_BIT), + + CT_OPT_EXP_SRC_BIT = 9, + CT_OPT_EXP_SRC = (1 << CT_OPT_EXP_SRC_BIT), + + CT_OPT_EXP_DST_BIT = 10, + CT_OPT_EXP_DST = (1 << CT_OPT_EXP_DST_BIT), + + CT_OPT_MASK_SRC_BIT = 11, + CT_OPT_MASK_SRC = (1 << CT_OPT_MASK_SRC_BIT), + + CT_OPT_MASK_DST_BIT = 12, + CT_OPT_MASK_DST = (1 << CT_OPT_MASK_DST_BIT), + + CT_OPT_NATRANGE_BIT = 13, + CT_OPT_NATRANGE = (1 << CT_OPT_NATRANGE_BIT), + + CT_OPT_MARK_BIT = 14, + CT_OPT_MARK = (1 << CT_OPT_MARK_BIT), + + CT_OPT_ID_BIT = 15, + CT_OPT_ID = (1 << CT_OPT_ID_BIT), + + CT_OPT_FAMILY_BIT = 16, + CT_OPT_FAMILY = (1 << CT_OPT_FAMILY_BIT), + + CT_OPT_MAX_BIT = CT_OPT_FAMILY_BIT +}; +#define NUMBER_OF_OPT CT_OPT_MAX_BIT+1 + +struct ctproto_handler { + struct list_head head; + + char *name; + u_int16_t protonum; + char *version; + + enum ctattr_protoinfo protoinfo_attr; + + int (*parse_opts)(char c, char *argv[], + struct nfct_tuple *orig, + struct nfct_tuple *reply, + struct nfct_tuple *exptuple, + struct nfct_tuple *mask, + union nfct_protoinfo *proto, + unsigned int *flags); + + int (*final_check)(unsigned int flags, + unsigned int command, + struct nfct_tuple *orig, + struct nfct_tuple *reply); + + void (*help)(); + + struct option *opts; + + unsigned int option_offset; +}; + +extern void register_proto(struct ctproto_handler *h); + +#endif diff --git a/cli/include/linux_list.h b/cli/include/linux_list.h new file mode 100644 index 0000000..57b56d7 --- /dev/null +++ b/cli/include/linux_list.h @@ -0,0 +1,725 @@ +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H + +#undef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +/** + * container_of - cast a member of a structure out to the containing structure + * + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +/* + * Check at compile time that something is of a particular type. + * Always evaluates to 1 so you may use it easily in comparisons. + */ +#define typecheck(type,x) \ +({ type __dummy; \ + typeof(x) __dummy2; \ + (void)(&__dummy == &__dummy2); \ + 1; \ +}) + +#define prefetch(x) 1 + +/* empty define to make this work in userspace -HW */ +#ifndef smp_wmb +#define smp_wmb() +#endif + +/* + * These are non-NULL pointers that will result in page faults + * under normal circumstances, used to verify that nobody uses + * non-initialized list entries. + */ +#define LIST_POISON1 ((void *) 0x00100100) +#define LIST_POISON2 ((void *) 0x00200200) + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add_rcu(struct list_head * new, + struct list_head * prev, struct list_head * next) +{ + new->next = next; + new->prev = prev; + smp_wmb(); + next->prev = new; + prev->next = new; +} + +/** + * list_add_rcu - add a new entry to rcu-protected list + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as list_add_rcu() + * or list_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * list_for_each_entry_rcu(). + */ +static inline void list_add_rcu(struct list_head *new, struct list_head *head) +{ + __list_add_rcu(new, head, head->next); +} + +/** + * list_add_tail_rcu - add a new entry to rcu-protected list + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as list_add_tail_rcu() + * or list_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * list_for_each_entry_rcu(). + */ +static inline void list_add_tail_rcu(struct list_head *new, + struct list_head *head) +{ + __list_add_rcu(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} + +/** + * list_del_rcu - deletes entry from list without re-initialization + * @entry: the element to delete from the list. + * + * Note: list_empty on entry does not return true after this, + * the entry is in an undefined state. It is useful for RCU based + * lockfree traversal. + * + * In particular, it means that we can not poison the forward + * pointers that may still be used for walking the list. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as list_del_rcu() + * or list_add_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * list_for_each_entry_rcu(). + * + * Note that the caller is not permitted to immediately free + * the newly deleted entry. Instead, either synchronize_kernel() + * or call_rcu() must be used to defer freeing until an RCU + * grace period has elapsed. + */ +static inline void list_del_rcu(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->prev = LIST_POISON2; +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_empty_careful - tests whether a list is + * empty _and_ checks that no other CPU might be + * in the process of still modifying either member + * + * NOTE: using list_empty_careful() without synchronization + * can only be safe if the only activity that can happen + * to the list entry is list_del_init(). Eg. it cannot be used + * if another CPU could re-list_add() it. + * + * @head: the list to test. + */ +static inline int list_empty_careful(const struct list_head *head) +{ + struct list_head *next = head->next; + return (next == head) && (next == head->prev); +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, prefetch(pos->next)) + +/** + * __list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This variant differs from list_for_each() in that it's the + * simplest possible list iteration code, no prefetching is done. + * Use this for code that knows the list to be very short (empty + * or 1 entry) most of the time. + */ +#define __list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ + pos = pos->prev, prefetch(pos->prev)) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member), \ + prefetch(pos->member.prev); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member), \ + prefetch(pos->member.prev)) + +/** + * list_prepare_entry - prepare a pos entry for use as a start point in + * list_for_each_entry_continue + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the list_struct within the struct. + */ +#define list_prepare_entry(pos, head, member) \ + ((pos) ? : list_entry(head, typeof(*pos), member)) + +/** + * list_for_each_entry_continue - iterate over list of given type + * continuing after existing point + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_rcu - iterate over an rcu-protected list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_rcu(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next)) + +#define __list_for_each_rcu(pos, head) \ + for (pos = (head)->next; pos != (head); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0;})) + +/** + * list_for_each_safe_rcu - iterate over an rcu-protected list safe + * against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_safe_rcu(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next) + +/** + * list_for_each_entry_rcu - iterate over rcu list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_entry_rcu(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + ({ smp_read_barrier_depends(); 0;}), \ + prefetch(pos->member.next)) + + +/** + * list_for_each_continue_rcu - iterate over an rcu-protected list + * continuing after existing point. + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_continue_rcu(pos, head) \ + for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \ + (pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next)) + +/* + * Double linked lists with a single pointer list head. + * Mostly useful for hash tables where the two pointer list head is + * too wasteful. + * You lose the ability to access the tail in O(1). + */ + +struct hlist_head { + struct hlist_node *first; +}; + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +#define HLIST_HEAD_INIT { .first = NULL } +#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } +#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) +#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL) + +static inline int hlist_unhashed(const struct hlist_node *h) +{ + return !h->pprev; +} + +static inline int hlist_empty(const struct hlist_head *h) +{ + return !h->first; +} + +static inline void __hlist_del(struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + *pprev = next; + if (next) + next->pprev = pprev; +} + +static inline void hlist_del(struct hlist_node *n) +{ + __hlist_del(n); + n->next = LIST_POISON1; + n->pprev = LIST_POISON2; +} + +/** + * hlist_del_rcu - deletes entry from hash list without re-initialization + * @n: the element to delete from the hash list. + * + * Note: list_unhashed() on entry does not return true after this, + * the entry is in an undefined state. It is useful for RCU based + * lockfree traversal. + * + * In particular, it means that we can not poison the forward + * pointers that may still be used for walking the hash list. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as hlist_add_head_rcu() + * or hlist_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * hlist_for_each_entry(). + */ +static inline void hlist_del_rcu(struct hlist_node *n) +{ + __hlist_del(n); + n->pprev = LIST_POISON2; +} + +static inline void hlist_del_init(struct hlist_node *n) +{ + if (n->pprev) { + __hlist_del(n); + INIT_HLIST_NODE(n); + } +} + +#define hlist_del_rcu_init hlist_del_init + +static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + if (first) + first->pprev = &n->next; + h->first = n; + n->pprev = &h->first; +} + + +/** + * hlist_add_head_rcu - adds the specified element to the specified hlist, + * while permitting racing traversals. + * @n: the element to add to the hash list. + * @h: the list to add to. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as hlist_add_head_rcu() + * or hlist_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * hlist_for_each_entry(), but only if smp_read_barrier_depends() + * is used to prevent memory-consistency problems on Alpha CPUs. + * Regardless of the type of CPU, the list-traversal primitive + * must be guarded by rcu_read_lock(). + * + * OK, so why don't we have an hlist_for_each_entry_rcu()??? + */ +static inline void hlist_add_head_rcu(struct hlist_node *n, + struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + n->pprev = &h->first; + smp_wmb(); + if (first) + first->pprev = &n->next; + h->first = n; +} + +/* next must be != NULL */ +static inline void hlist_add_before(struct hlist_node *n, + struct hlist_node *next) +{ + n->pprev = next->pprev; + n->next = next; + next->pprev = &n->next; + *(n->pprev) = n; +} + +static inline void hlist_add_after(struct hlist_node *n, + struct hlist_node *next) +{ + next->next = n->next; + n->next = next; + next->pprev = &n->next; + + if(next->next) + next->next->pprev = &next->next; +} + +#define hlist_entry(ptr, type, member) container_of(ptr,type,member) + +#define hlist_for_each(pos, head) \ + for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \ + pos = pos->next) + +#define hlist_for_each_safe(pos, n, head) \ + for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ + pos = n) + +/** + * hlist_for_each_entry - iterate over list of given type + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry(tpos, pos, head, member) \ + for (pos = (head)->first; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_continue - iterate over a hlist continuing after existing point + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_continue(tpos, pos, member) \ + for (pos = (pos)->next; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_from - iterate over a hlist continuing from existing point + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_from(tpos, pos, member) \ + for (; pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @n: another &struct hlist_node to use as temporary storage + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ + for (pos = (head)->first; \ + pos && ({ n = pos->next; 1; }) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = n) + +/** + * hlist_for_each_entry_rcu - iterate over rcu list of given type + * @pos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as hlist_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define hlist_for_each_entry_rcu(tpos, pos, head, member) \ + for (pos = (head)->first; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0; }) ) + +#endif diff --git a/cli/src/Makefile.am b/cli/src/Makefile.am new file mode 100644 index 0000000..83cad99 --- /dev/null +++ b/cli/src/Makefile.am @@ -0,0 +1,7 @@ +include $(top_srcdir)/Make_global.am +LIBS = @CONNTRACK_LIBS@ + +sbin_PROGRAMS = conntrack +conntrack_SOURCES = conntrack.c +conntrack_LDFLAGS = -rdynamic + diff --git a/cli/src/conntrack.c b/cli/src/conntrack.c new file mode 100644 index 0000000..30fbf69 --- /dev/null +++ b/cli/src/conntrack.c @@ -0,0 +1,1131 @@ +/* + * (C) 2005 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. + * + * Note: + * Yes, portions of this code has been stolen from iptables ;) + * Special thanks to the the Netfilter Core Team. + * Thanks to Javier de Miguel Rodriguez + * for introducing me to advanced firewalling stuff. + * + * --pablo 13/04/2005 + * + * 2005-04-16 Harald Welte : + * Add support for conntrack accounting and conntrack mark + * 2005-06-23 Harald Welte : + * Add support for expect creation + * 2005-09-24 Harald Welte : + * Remove remaints of "-A" + * + */ +#include +#include +#include +#include +#include +#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'}; + +static const char cmd_need_param[NUMBER_OF_CMD] += { 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2 }; + +static const char optflags[NUMBER_OF_OPT] += {'s','d','r','q','p','t','u','z','e','[',']','{','}','a','m','i','f'}; + +static struct option original_opts[] = { + {"dump", 2, 0, 'L'}, + {"create", 1, 0, 'I'}, + {"delete", 1, 0, 'D'}, + {"update", 1, 0, 'U'}, + {"get", 1, 0, 'G'}, + {"flush", 1, 0, 'F'}, + {"event", 1, 0, 'E'}, + {"version", 0, 0, 'V'}, + {"help", 0, 0, 'h'}, + {"orig-src", 1, 0, 's'}, + {"orig-dst", 1, 0, 'd'}, + {"reply-src", 1, 0, 'r'}, + {"reply-dst", 1, 0, 'q'}, + {"protonum", 1, 0, 'p'}, + {"timeout", 1, 0, 't'}, + {"status", 1, 0, 'u'}, + {"zero", 0, 0, 'z'}, + {"event-mask", 1, 0, 'e'}, + {"tuple-src", 1, 0, '['}, + {"tuple-dst", 1, 0, ']'}, + {"mask-src", 1, 0, '{'}, + {"mask-dst", 1, 0, '}'}, + {"nat-range", 1, 0, 'a'}, + {"mark", 1, 0, 'm'}, + {"id", 2, 0, 'i'}, + {"family", 1, 0, 'f'}, + {0, 0, 0, 0} +}; + +#define OPTION_OFFSET 256 + +static struct nfct_handle *cth; +static struct option *opts = original_opts; +static unsigned int global_option_offset = 0; + +/* Table of legal combinations of commands and options. If any of the + * given commands make an option legal, that option is legal (applies to + * CMD_LIST and CMD_ZERO only). + * Key: + * 0 illegal + * 1 compulsory + * 2 optional + */ + +static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = +/* Well, it's better than "Re: Linux vs FreeBSD" */ +{ + /* s d r q p t u z e x y k l a m i f*/ +/*CT_LIST*/ {2,2,2,2,2,0,0,2,0,0,0,0,0,0,2,2,2}, +/*CT_CREATE*/ {2,2,2,2,1,1,1,0,0,0,0,0,0,2,2,0,0}, +/*CT_UPDATE*/ {2,2,2,2,1,2,2,0,0,0,0,0,0,0,2,2,0}, +/*CT_DELETE*/ {2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,0}, +/*CT_GET*/ {2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,2,0}, +/*CT_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*CT_EVENT*/ {2,2,2,2,2,0,0,0,2,0,0,0,0,0,2,0,0}, +/*VERSION*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*HELP*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_LIST*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2}, +/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0}, +/*EXP_DELETE*/{1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_GET*/ {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +}; + +static char *lib_dir = CONNTRACK_LIB_DIR; + +static LIST_HEAD(proto_list); + +void register_proto(struct ctproto_handler *h) +{ + if (strcmp(h->version, VERSION) != 0) { + fprintf(stderr, "plugin `%s': version %s (I'm %s)\n", + h->name, h->version, VERSION); + exit(1); + } + list_add(&h->head, &proto_list); +} + +static struct ctproto_handler *findproto(char *name) +{ + struct list_head *i; + struct ctproto_handler *cur = NULL, *handler = NULL; + + if (!name) + return handler; + + lib_dir = getenv("CONNTRACK_LIB_DIR"); + if (!lib_dir) + lib_dir = CONNTRACK_LIB_DIR; + + list_for_each(i, &proto_list) { + cur = (struct ctproto_handler *) i; + if (strcmp(cur->name, name) == 0) { + handler = cur; + break; + } + } + + if (!handler) { + char path[sizeof("ct_proto_.so") + + strlen(name) + strlen(lib_dir)]; + sprintf(path, "%s/ct_proto_%s.so", lib_dir, name); + if (dlopen(path, RTLD_NOW)) + handler = findproto(name); + else + fprintf(stderr, "%s\n", dlerror()); + } + + return handler; +} + +enum exittype { + OTHER_PROBLEM = 1, + PARAMETER_PROBLEM, + VERSION_PROBLEM +}; + +void extension_help(struct ctproto_handler *h) +{ + fprintf(stdout, "\n"); + fprintf(stdout, "Proto `%s' help:\n", h->name); + h->help(); +} + +void +exit_tryhelp(int status) +{ + fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n", + PROGNAME, PROGNAME); + exit(status); +} + +static void +exit_error(enum exittype status, char *msg, ...) +{ + va_list args; + + /* On error paths, make sure that we don't leak the memory + * reserved during options merging */ + if (opts != original_opts) { + free(opts); + opts = original_opts; + global_option_offset = 0; + } + va_start(args, msg); + fprintf(stderr,"%s v%s: ", PROGNAME, VERSION); + vfprintf(stderr, msg, args); + va_end(args); + fprintf(stderr, "\n"); + if (status == PARAMETER_PROBLEM) + exit_tryhelp(status); + exit(status); +} + +static void +generic_cmd_check(int command, int options) +{ + int i; + + for (i = 0; i < NUMBER_OF_CMD; i++) { + if (!(command & (1< illegal, 1 => legal, 0 => undecided. */ + + for (j = 0; j < NUMBER_OF_CMD; j++) { + if (!(command & (1<size; i++) + if (strncasecmp(str, p->parameter[i], strlen) == 0) { + *value |= p->value[i]; + ret = 1; + break; + } + + return ret; +} + +static void +parse_parameter(const char *arg, unsigned int *status, int parse_type) +{ + const char *comma; + + while ((comma = strchr(arg, ',')) != NULL) { + if (comma == arg + || !do_parse_parameter(arg, comma-arg, status, parse_type)) + exit_error(PARAMETER_PROBLEM,"Bad parameter `%s'", arg); + arg = comma+1; + } + + if (strlen(arg) == 0 + || !do_parse_parameter(arg, strlen(arg), status, parse_type)) + exit_error(PARAMETER_PROBLEM, "Bad parameter `%s'", arg); +} + +static void +add_command(unsigned int *cmd, const int newcmd, const int othercmds) +{ + if (*cmd & (~othercmds)) + exit_error(PARAMETER_PROBLEM, "Invalid commands combination\n"); + *cmd |= newcmd; +} + +unsigned int check_type(int argc, char *argv[]) +{ + char *table = NULL; + + /* Nasty bug or feature in getopt_long ? + * It seems that it behaves badly with optional arguments. + * Fortunately, I just stole the fix from iptables ;) */ + if (optarg) + return 0; + else if (optind < argc && argv[optind][0] != '-' + && argv[optind][0] != '!') + table = argv[optind++]; + + if (!table) + return 0; + + if (strncmp("expect", table, 6) == 0) + return 1; + else if (strncmp("conntrack", table, 9) == 0) + return 0; + else + exit_error(PARAMETER_PROBLEM, "unknown type `%s'\n", table); + + return 0; +} + +static void set_family(int *family, int new) +{ + if (*family == AF_UNSPEC) + *family = new; + else if (*family != new) + exit_error(PARAMETER_PROBLEM, "mismatched address family\n"); +} + +struct addr_parse { + struct in_addr addr; + struct in6_addr addr6; + unsigned int family; +}; + +int __parse_inetaddr(const char *cp, struct addr_parse *parse) +{ + if (inet_aton(cp, &parse->addr)) + return AF_INET; +#ifdef HAVE_INET_PTON_IPV6 + else if (inet_pton(AF_INET6, cp, &parse->addr6) > 0) + return AF_INET6; +#endif + + exit_error(PARAMETER_PROBLEM, "Invalid IP address `%s'.", cp); +} + +int parse_inetaddr(const char *cp, union nfct_address *address) +{ + struct addr_parse parse; + int ret; + + if ((ret = __parse_inetaddr(cp, &parse)) == AF_INET) + address->v4 = parse.addr.s_addr; + else if (ret == AF_INET6) + memcpy(address->v6, &parse.addr6, sizeof(parse.addr6)); + + return ret; +} + +/* Shamelessly stolen from libipt_DNAT ;). Ranges expected in network order. */ +static void +nat_parse(char *arg, int portok, struct nfct_nat *range) +{ + char *colon, *dash, *error; + struct addr_parse parse; + + memset(range, 0, sizeof(range)); + colon = strchr(arg, ':'); + + if (colon) { + int port; + + if (!portok) + exit_error(PARAMETER_PROBLEM, + "Need TCP or UDP with port specification"); + + port = atoi(colon+1); + if (port == 0 || port > 65535) + exit_error(PARAMETER_PROBLEM, + "Port `%s' not valid\n", colon+1); + + error = strchr(colon+1, ':'); + if (error) + exit_error(PARAMETER_PROBLEM, + "Invalid port:port syntax - use dash\n"); + + dash = strchr(colon, '-'); + if (!dash) { + range->l4min.tcp.port + = range->l4max.tcp.port + = htons(port); + } else { + int maxport; + + maxport = atoi(dash + 1); + if (maxport == 0 || maxport > 65535) + exit_error(PARAMETER_PROBLEM, + "Port `%s' not valid\n", dash+1); + if (maxport < port) + /* People are stupid. */ + exit_error(PARAMETER_PROBLEM, + "Port range `%s' funky\n", colon+1); + range->l4min.tcp.port = htons(port); + range->l4max.tcp.port = htons(maxport); + } + /* Starts with a colon? No IP info... */ + if (colon == arg) + return; + *colon = '\0'; + } + + dash = strchr(arg, '-'); + if (colon && dash && dash > colon) + dash = NULL; + + if (dash) + *dash = '\0'; + + if (__parse_inetaddr(arg, &parse) != AF_INET) + return; + + range->min_ip = parse.addr.s_addr; + if (dash) { + if (__parse_inetaddr(dash+1, &parse) != AF_INET) + return; + range->max_ip = parse.addr.s_addr; + } else + range->max_ip = parse.addr.s_addr; +} + +static void event_sighandler(int s) +{ + fprintf(stdout, "Now closing conntrack event dumping...\n"); + nfct_close(cth); + exit(0); +} + +static const char usage_commands[] = + "Commands:\n" + " -L [table] [options]\t\tList conntrack or expectation table\n" + " -G [table] parameters\t\tGet conntrack or expectation\n" + " -D [table] parameters\t\tDelete conntrack or expectation\n" + " -I [table] parameters\t\tCreate a conntrack or expectation\n" + " -U [table] parameters\t\tUpdate a conntrack\n" + " -E [table] [options]\t\tShow events\n" + " -F [table]\t\t\tFlush table\n"; + +static const char usage_tables[] = + "Tables: conntrack, expect\n"; + +static const char usage_conntrack_parameters[] = + "Conntrack parameters and options:\n" + " -a, --nat-range min_ip[-max_ip]\tNAT ip range\n" + " -m, --mark mark\t\t\tSet mark\n" + " -e, --event-mask eventmask\t\tEvent mask, eg. NEW,DESTROY\n" + " -z, --zero \t\t\t\tZero counters while listing\n" + ; + +static const char usage_expectation_parameters[] = + "Expectation parameters and options:\n" + " --tuple-src ip\tSource address in expect tuple\n" + " --tuple-dst ip\tDestination address in expect tuple\n" + " --mask-src ip\t\tSource mask address\n" + " --mask-dst ip\t\tDestination mask address\n"; + +static const char usage_parameters[] = + "Common parameters and options:\n" + " -s, --orig-src ip\t\tSource address from original direction\n" + " -d, --orig-dst ip\t\tDestination address from original direction\n" + " -r, --reply-src ip\t\tSource addres from reply direction\n" + " -q, --reply-dst ip\t\tDestination address from reply direction\n" + " -p, --protonum proto\t\tLayer 4 Protocol, eg. 'tcp'\n" + " -f, --family proto\t\tLayer 3 Protocol, eg. 'ipv6'\n" + " -t, --timeout timeout\t\tSet timeout\n" + " -u, --status status\t\tSet status, eg. ASSURED\n" + " -i, --id [id]\t\t\tShow or set conntrack ID\n" + ; + + +void usage(char *prog) { + fprintf(stdout, "Tool to manipulate conntrack and expectations. Version %s\n", VERSION); + fprintf(stdout, "Usage: %s [commands] [options]\n", prog); + + fprintf(stdout, "\n%s", usage_commands); + fprintf(stdout, "\n%s", usage_tables); + fprintf(stdout, "\n%s", usage_conntrack_parameters); + fprintf(stdout, "\n%s", usage_expectation_parameters); + fprintf(stdout, "\n%s", usage_parameters); +} + +#define CT_COMPARISON (CT_OPT_PROTO | CT_OPT_ORIG | CT_OPT_REPL | CT_OPT_MARK) + +static struct nfct_tuple orig, reply, mask; +static struct nfct_tuple exptuple; +static struct ctproto_handler *h; +static union nfct_protoinfo proto; +static struct nfct_nat range; +static struct nfct_conntrack *ct; +static struct nfct_expect *exp; +static unsigned long timeout; +static unsigned int status; +static unsigned int mark; +static unsigned int id = NFCT_ANY_ID; +static struct nfct_conntrack_compare cmp; + +int main(int argc, char *argv[]) +{ + int c; + unsigned int command = 0, options = 0; + unsigned int type = 0, event_mask = 0; + unsigned int l3flags = 0, l4flags = 0, metaflags = 0; + int res = 0; + int family = AF_UNSPEC; + struct nfct_conntrack_compare *pcmp; + + while ((c = getopt_long(argc, argv, + "L::I::U::D::G::E::F::hVs:d:r:q:p:t:u:e:a:z[:]:{:}:m:i::f:", + opts, NULL)) != -1) { + switch(c) { + case 'L': + type = check_type(argc, argv); + if (type == 0) + add_command(&command, CT_LIST, CT_NONE); + else if (type == 1) + add_command(&command, EXP_LIST, CT_NONE); + break; + case 'I': + type = check_type(argc, argv); + if (type == 0) + add_command(&command, CT_CREATE, CT_NONE); + else if (type == 1) + add_command(&command, EXP_CREATE, CT_NONE); + break; + case 'U': + type = check_type(argc, argv); + if (type == 0) + add_command(&command, CT_UPDATE, CT_NONE); + else + exit_error(PARAMETER_PROBLEM, "Can't update " + "expectations"); + break; + case 'D': + type = check_type(argc, argv); + if (type == 0) + add_command(&command, CT_DELETE, CT_NONE); + else if (type == 1) + add_command(&command, EXP_DELETE, CT_NONE); + break; + case 'G': + type = check_type(argc, argv); + if (type == 0) + add_command(&command, CT_GET, CT_NONE); + else if (type == 1) + add_command(&command, EXP_GET, CT_NONE); + break; + case 'F': + type = check_type(argc, argv); + if (type == 0) + add_command(&command, CT_FLUSH, CT_NONE); + else if (type == 1) + add_command(&command, EXP_FLUSH, CT_NONE); + break; + case 'E': + type = check_type(argc, argv); + if (type == 0) + add_command(&command, CT_EVENT, CT_NONE); + else if (type == 1) + add_command(&command, EXP_EVENT, CT_NONE); + break; + case 'V': + add_command(&command, CT_VERSION, CT_NONE); + break; + case 'h': + add_command(&command, CT_HELP, CT_NONE); + break; + case 's': + options |= CT_OPT_ORIG_SRC; + if (optarg) { + orig.l3protonum = + parse_inetaddr(optarg, &orig.src); + set_family(&family, orig.l3protonum); + if (orig.l3protonum == AF_INET) + l3flags |= IPV4_ORIG_SRC; + else if (orig.l3protonum == AF_INET6) + l3flags |= IPV6_ORIG_SRC; + } + break; + case 'd': + options |= CT_OPT_ORIG_DST; + if (optarg) { + orig.l3protonum = + parse_inetaddr(optarg, &orig.dst); + set_family(&family, orig.l3protonum); + if (orig.l3protonum == AF_INET) + l3flags |= IPV4_ORIG_DST; + else if (orig.l3protonum == AF_INET6) + l3flags |= IPV6_ORIG_DST; + } + break; + case 'r': + options |= CT_OPT_REPL_SRC; + if (optarg) { + reply.l3protonum = + parse_inetaddr(optarg, &reply.src); + set_family(&family, reply.l3protonum); + if (orig.l3protonum == AF_INET) + l3flags |= IPV4_REPL_SRC; + else if (orig.l3protonum == AF_INET6) + l3flags |= IPV6_REPL_SRC; + } + break; + case 'q': + options |= CT_OPT_REPL_DST; + if (optarg) { + reply.l3protonum = + parse_inetaddr(optarg, &reply.dst); + set_family(&family, reply.l3protonum); + if (orig.l3protonum == AF_INET) + l3flags |= IPV4_REPL_DST; + else if (orig.l3protonum == AF_INET6) + l3flags |= IPV6_REPL_DST; + } + break; + case 'p': + options |= CT_OPT_PROTO; + h = findproto(optarg); + if (!h) + exit_error(PARAMETER_PROBLEM, "proto needed\n"); + orig.protonum = h->protonum; + reply.protonum = h->protonum; + exptuple.protonum = h->protonum; + mask.protonum = h->protonum; + opts = merge_options(opts, h->opts, + &h->option_offset); + break; + case 't': + options |= CT_OPT_TIMEOUT; + if (optarg) + timeout = atol(optarg); + break; + case 'u': { + if (!optarg) + continue; + + options |= CT_OPT_STATUS; + parse_parameter(optarg, &status, PARSE_STATUS); + break; + } + case 'e': + options |= CT_OPT_EVENT_MASK; + parse_parameter(optarg, &event_mask, PARSE_EVENT); + break; + case 'z': + options |= CT_OPT_ZERO; + break; + case '{': + options |= CT_OPT_MASK_SRC; + if (optarg) { + mask.l3protonum = + parse_inetaddr(optarg, &mask.src); + set_family(&family, mask.l3protonum); + } + break; + case '}': + options |= CT_OPT_MASK_DST; + if (optarg) { + mask.l3protonum = + parse_inetaddr(optarg, &mask.dst); + set_family(&family, mask.l3protonum); + } + break; + case '[': + options |= CT_OPT_EXP_SRC; + if (optarg) { + exptuple.l3protonum = + parse_inetaddr(optarg, &exptuple.src); + set_family(&family, exptuple.l3protonum); + } + break; + case ']': + options |= CT_OPT_EXP_DST; + if (optarg) { + exptuple.l3protonum = + parse_inetaddr(optarg, &exptuple.dst); + set_family(&family, exptuple.l3protonum); + } + break; + case 'a': + options |= CT_OPT_NATRANGE; + set_family(&family, AF_INET); + nat_parse(optarg, 1, &range); + break; + case 'm': + options |= CT_OPT_MARK; + mark = atol(optarg); + metaflags |= NFCT_MARK; + break; + case 'i': { + char *s = NULL; + options |= CT_OPT_ID; + if (optarg) + break; + else if (optind < argc && argv[optind][0] != '-' + && argv[optind][0] != '!') + s = argv[optind++]; + + if (s) + id = atol(s); + break; + } + case 'f': + options |= CT_OPT_FAMILY; + if (strncmp(optarg, "ipv4", strlen("ipv4")) == 0) + set_family(&family, AF_INET); + else if (strncmp(optarg, "ipv6", strlen("ipv6")) == 0) + set_family(&family, AF_INET6); + else + exit_error(PARAMETER_PROBLEM, "Unknown " + "protocol family\n"); + break; + default: + if (h && h->parse_opts + &&!h->parse_opts(c - h->option_offset, argv, &orig, + &reply, &exptuple, &mask, &proto, + &l4flags)) + exit_error(PARAMETER_PROBLEM, "parse error\n"); + + /* Unknown argument... */ + if (!h) { + usage(argv[0]); + exit_error(PARAMETER_PROBLEM, "Missing " + "arguments...\n"); + } + break; + } + } + + /* default family */ + if (family == AF_UNSPEC) + family = AF_INET; + + generic_cmd_check(command, options); + generic_opt_check(command, options); + + if (!(command & CT_HELP) + && h && h->final_check + && !h->final_check(l4flags, command, &orig, &reply)) { + usage(argv[0]); + extension_help(h); + exit_error(PARAMETER_PROBLEM, "Missing protocol arguments!\n"); + } + + switch(command) { + + case CT_LIST: + cth = nfct_open(CONNTRACK, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + + if (options & CT_COMPARISON) { + + if (options & CT_OPT_ZERO) + exit_error(PARAMETER_PROBLEM, "Can't use -z " + "with filtering parameters"); + + ct = nfct_conntrack_alloc(&orig, &reply, timeout, + &proto, status, mark, id, + NULL); + if (!ct) + exit_error(OTHER_PROBLEM, "Not enough memory"); + + cmp.ct = ct; + cmp.flags = metaflags; + cmp.l3flags = l3flags; + cmp.l4flags = l4flags; + pcmp = &cmp; + } + + if (options & CT_OPT_ID) + nfct_register_callback(cth, + nfct_default_conntrack_display_id, + (void *) pcmp); + else + nfct_register_callback(cth, + nfct_default_conntrack_display, + (void *) pcmp); + + if (options & CT_OPT_ZERO) + res = + nfct_dump_conntrack_table_reset_counters(cth, family); + else + res = nfct_dump_conntrack_table(cth, family); + nfct_close(cth); + break; + + case EXP_LIST: + cth = nfct_open(EXPECT, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + if (options & CT_OPT_ID) + nfct_register_callback(cth, + nfct_default_expect_display_id, + NULL); + else + nfct_register_callback(cth, + nfct_default_expect_display, + NULL); + res = nfct_dump_expect_list(cth, family); + nfct_close(cth); + break; + + case CT_CREATE: + if ((options & CT_OPT_ORIG) + && !(options & CT_OPT_REPL)) { + reply.l3protonum = orig.l3protonum; + memcpy(&reply.src, &orig.dst, sizeof(reply.src)); + memcpy(&reply.dst, &orig.src, sizeof(reply.dst)); + } else if (!(options & CT_OPT_ORIG) + && (options & CT_OPT_REPL)) { + orig.l3protonum = reply.l3protonum; + memcpy(&orig.src, &reply.dst, sizeof(orig.src)); + memcpy(&orig.dst, &reply.src, sizeof(orig.dst)); + } + if (options & CT_OPT_NATRANGE) + ct = nfct_conntrack_alloc(&orig, &reply, timeout, + &proto, status, mark, id, + &range); + else + ct = nfct_conntrack_alloc(&orig, &reply, timeout, + &proto, status, mark, id, + NULL); + if (!ct) + exit_error(OTHER_PROBLEM, "Not Enough memory"); + + cth = nfct_open(CONNTRACK, 0); + if (!cth) { + nfct_conntrack_free(ct); + exit_error(OTHER_PROBLEM, "Can't open handler"); + } + res = nfct_create_conntrack(cth, ct); + nfct_close(cth); + nfct_conntrack_free(ct); + break; + + case EXP_CREATE: + if (options & CT_OPT_ORIG) + exp = nfct_expect_alloc(&orig, &exptuple, + &mask, timeout, id); + else if (options & CT_OPT_REPL) + exp = nfct_expect_alloc(&reply, &exptuple, + &mask, timeout, id); + if (!exp) + exit_error(OTHER_PROBLEM, "Not enough memory"); + + cth = nfct_open(EXPECT, 0); + if (!cth) { + nfct_expect_free(exp); + exit_error(OTHER_PROBLEM, "Can't open handler"); + } + res = nfct_create_expectation(cth, exp); + nfct_expect_free(exp); + nfct_close(cth); + break; + + case CT_UPDATE: + if ((options & CT_OPT_ORIG) + && !(options & CT_OPT_REPL)) { + reply.l3protonum = orig.l3protonum; + memcpy(&reply.src, &orig.dst, sizeof(reply.src)); + memcpy(&reply.dst, &orig.src, sizeof(reply.dst)); + } else if (!(options & CT_OPT_ORIG) + && (options & CT_OPT_REPL)) { + orig.l3protonum = reply.l3protonum; + memcpy(&orig.src, &reply.dst, sizeof(orig.src)); + memcpy(&orig.dst, &reply.src, sizeof(orig.dst)); + } + ct = nfct_conntrack_alloc(&orig, &reply, timeout, + &proto, status, mark, id, + NULL); + if (!ct) + exit_error(OTHER_PROBLEM, "Not enough memory"); + + cth = nfct_open(CONNTRACK, 0); + if (!cth) { + nfct_conntrack_free(ct); + exit_error(OTHER_PROBLEM, "Can't open handler"); + } + res = nfct_update_conntrack(cth, ct); + nfct_conntrack_free(ct); + nfct_close(cth); + break; + + case CT_DELETE: + if (!(options & CT_OPT_ORIG) && !(options & CT_OPT_REPL)) + exit_error(PARAMETER_PROBLEM, "Can't kill conntracks " + "just by its ID"); + cth = nfct_open(CONNTRACK, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + if (options & CT_OPT_ORIG) + res = nfct_delete_conntrack(cth, &orig, + NFCT_DIR_ORIGINAL, + id); + else if (options & CT_OPT_REPL) + res = nfct_delete_conntrack(cth, &reply, + NFCT_DIR_REPLY, + id); + nfct_close(cth); + break; + + case EXP_DELETE: + cth = nfct_open(EXPECT, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + if (options & CT_OPT_ORIG) + res = nfct_delete_expectation(cth, &orig, id); + else if (options & CT_OPT_REPL) + res = nfct_delete_expectation(cth, &reply, id); + nfct_close(cth); + break; + + case CT_GET: + cth = nfct_open(CONNTRACK, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + nfct_register_callback(cth, nfct_default_conntrack_display, + NULL); + if (options & CT_OPT_ORIG) + res = nfct_get_conntrack(cth, &orig, + NFCT_DIR_ORIGINAL, id); + else if (options & CT_OPT_REPL) + res = nfct_get_conntrack(cth, &reply, + NFCT_DIR_REPLY, id); + nfct_close(cth); + break; + + case EXP_GET: + cth = nfct_open(EXPECT, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + nfct_register_callback(cth, nfct_default_expect_display, + NULL); + if (options & CT_OPT_ORIG) + res = nfct_get_expectation(cth, &orig, id); + else if (options & CT_OPT_REPL) + res = nfct_get_expectation(cth, &reply, id); + nfct_close(cth); + break; + + case CT_FLUSH: + cth = nfct_open(CONNTRACK, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + res = nfct_flush_conntrack_table(cth, AF_INET); + nfct_close(cth); + break; + + case EXP_FLUSH: + cth = nfct_open(EXPECT, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + res = nfct_flush_expectation_table(cth, AF_INET); + nfct_close(cth); + break; + + case CT_EVENT: + if (options & CT_OPT_EVENT_MASK) + cth = nfct_open(CONNTRACK, event_mask); + else + cth = nfct_open(CONNTRACK, NFCT_ALL_CT_GROUPS); + + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + signal(SIGINT, event_sighandler); + + if (options & CT_COMPARISON) { + ct = nfct_conntrack_alloc(&orig, &reply, timeout, + &proto, status, mark, id, + NULL); + if (!ct) + exit_error(OTHER_PROBLEM, "Not enough memory"); + + cmp.ct = ct; + cmp.flags = metaflags; + cmp.l3flags = l3flags; + cmp.l4flags = l4flags; + pcmp = &cmp; + } + + nfct_register_callback(cth, + nfct_default_conntrack_event_display, + (void *) pcmp); + res = nfct_event_conntrack(cth); + nfct_close(cth); + break; + + case EXP_EVENT: + cth = nfct_open(EXPECT, NF_NETLINK_CONNTRACK_EXP_NEW); + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + signal(SIGINT, event_sighandler); + nfct_register_callback(cth, nfct_default_expect_display, + NULL); + res = nfct_event_expectation(cth); + nfct_close(cth); + break; + + case CT_VERSION: + fprintf(stdout, "%s v%s\n", PROGNAME, VERSION); + break; + case CT_HELP: + usage(argv[0]); + if (options & CT_OPT_PROTO) + extension_help(h); + break; + default: + usage(argv[0]); + break; + } + + if (opts != original_opts) { + free(opts); + opts = original_opts; + global_option_offset = 0; + } + + if (res < 0) { + fprintf(stderr, "Operation failed: %s\n", err2str(res, command)); + exit(OTHER_PROBLEM); + } + + return 0; +} diff --git a/cli/test.sh b/cli/test.sh new file mode 100644 index 0000000..4694236 --- /dev/null +++ b/cli/test.sh @@ -0,0 +1,110 @@ +CONNTRACK=conntrack + +SRC=1.1.1.1 +DST=2.2.2.2 +SPORT=2005 +DPORT=21 + +case $1 in + dump) + echo "Dumping conntrack table" + $CONNTRACK -L + ;; + flush) + echo "Flushing conntrack table" + $CONNTRACK -F + ;; + new) + echo "creating a new conntrack" + $CONNTRACK -I --orig-src $SRC --orig-dst $DST \ + --reply-src $DST --reply-dst $SRC -p tcp \ + --orig-port-src $SPORT --orig-port-dst $DPORT \ + --reply-port-src $DPORT --reply-port-dst $SPORT \ + --state LISTEN -u SEEN_REPLY -t 50 + ;; + new-simple) + echo "creating a new conntrack (simplified)" + $CONNTRACK -I --orig-src $SRC --orig-dst $DST \ + -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \ + --state LISTEN -u SEEN_REPLY -t 50 + ;; + new-nat) + echo "creating a new conntrack (NAT)" + $CONNTRACK -I --orig-src $SRC --orig-dst $DST \ + -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \ + --state LISTEN -u SEEN_REPLY,SRC_NAT -t 50 -a 8.8.8.8 + ;; + get) + echo "getting a conntrack" + $CONNTRACK -G --orig-src $SRC --orig-dst $DST \ + -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \ + --reply-port-src $DPORT --reply-port-dst $SPORT + ;; + change) + echo "change a conntrack" + $CONNTRACK -U --orig-src $SRC --orig-dst $DST \ + --reply-src $DST --reply-dst $SRC -p tcp \ + --orig-port-src $SPORT --orig-port-dst $DPORT \ + --reply-port-src $DPORT --reply-port-dst $SPORT \ + --state TIME_WAIT -u ASSURED,SEEN_REPLY -t 500 + ;; + delete) + $CONNTRACK -D --orig-src $SRC --orig-dst $DST \ + -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT + ;; + output) + proc=$(cat /proc/net/ip_conntrack | wc -l) + netl=$($CONNTRACK -L | wc -l) + count=$(cat /proc/sys/net/ipv4/netfilter/ip_conntrack_count) + if [ $proc -ne $netl ]; then + echo "proc is $proc and netl is $netl and count is $count" + else + if [ $proc -ne $count ]; then + echo "proc is $proc and netl is $netl and count is $count" + else + echo "now $proc" + fi + fi + ;; + dump-expect) + $CONNTRACK -L expect + ;; + flush-expect) + $CONNTRACK -F expect + ;; + create-expect) + # requires modprobe ip_conntrack_ftp + $CONNTRACK -I expect --orig-src $SRC --orig-dst $DST \ + --tuple-src 4.4.4.4 --tuple-dst 5.5.5.5 \ + --mask-src 255.255.255.0 --mask-dst 255.255.255.255 \ + -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \ + -t 200 --tuple-port-src 10 --tuple-port-dst 300 \ + --mask-port-src 10 --mask-port-dst 300 + ;; + get-expect) + $CONNTRACK -G expect --orig-src 4.4.4.4 --orig-dst 5.5.5.5 \ + --p tcp --orig-port-src 0 --orig-port-dst 0 \ + --mask-port-src 10 --mask-port-dst 11 + ;; + delete-expect) + $CONNTRACK -D expect --orig-src 4.4.4.4 \ + --orig-dst 5.5.5.5 -p tcp --orig-port-src 0 \ + --orig-port-dst 0 --mask-port-src 10 --mask-port-dst 11 + ;; + *) + echo "Usage: $0 [dump" + echo " |new" + echo " |new-simple" + echo " |new-nat" + echo " |get" + echo " |change" + echo " |delete" + echo " |output" + echo " |flush" + echo " |dump-expect" + echo " |flush-expect" + echo " |create-expect" + echo " |get-expect" + echo " |delete-expect]" + ;; +esac diff --git a/configure.in b/configure.in deleted file mode 100644 index 1b1b391..0000000 --- a/configure.in +++ /dev/null @@ -1,72 +0,0 @@ -AC_INIT - -AC_CANONICAL_SYSTEM - -AM_INIT_AUTOMAKE(conntrack, 1.00beta2) - -AC_PROG_CC -AM_PROG_LIBTOOL -AC_PROG_INSTALL -AC_PROG_LN_S - -case $target in -*-*-linux*) ;; -*) AC_MSG_ERROR([Linux only, dude!]);; -esac - -dnl Dependencies -LIBNFCONNTRACK_REQUIRED=0.0.31 - -AC_CHECK_LIB(dl, dlopen) - -PKG_CHECK_MODULES(LIBNFCONNTRACK, libnetfilter_conntrack >= $LIBNFCONNTRACK_REQUIRED,, - AC_MSG_ERROR(Cannot find libnetfilter_conntrack >= $LIBNFCONNTRACK_REQUIRED)) - -AC_CHECK_HEADERS(arpa/inet.h) -dnl check for inet_pton -AC_CHECK_FUNCS(inet_pton) -dnl Some systems have it, but not IPv6 -if test "$ac_cv_func_inet_pton" = "yes" ; then -AC_MSG_CHECKING(if inet_pton supports IPv6) -AC_TRY_RUN( - [ -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -int main() - { - struct in6_addr addr6; - if (inet_pton(AF_INET6, "::1", &addr6) < 1) - exit(1); - else - exit(0); - } - ], [ AC_MSG_RESULT(yes) - AC_DEFINE_UNQUOTED(HAVE_INET_PTON_IPV6, 1, [Define to 1 if inet_pton supports IPv6.]) - ], AC_MSG_RESULT(no), AC_MSG_RESULT(no)) -fi - -dnl-------------------------------- - -if test ! -z "$libdir"; then - MODULE_DIR="\\\"$libdir/conntrack/\\\"" - CFLAGS="$CFLAGS -DCONNTRACK_LIB_DIR=$MODULE_DIR" -fi - -dnl-------------------------------- - -CFLAGS="$CFLAGS $LIBNFCONNTRACK_CFLAGS" -CONNTRACK_LIBS="$LIBNFCONNTRACK_LIBS" - -AC_SUBST(CONNTRACK_LIBS) - -AC_OUTPUT(Makefile src/Makefile extensions/Makefile include/Makefile) diff --git a/conntrack.8 b/conntrack.8 deleted file mode 100644 index 307180b..0000000 --- a/conntrack.8 +++ /dev/null @@ -1,142 +0,0 @@ -.TH CONNTRACK 8 "Jun 23, 2005" "" "" - -.\" Man page written by Harald Welte . diff --git a/daemon/AUTHORS b/daemon/AUTHORS new file mode 100644 index 0000000..e6c2f6b --- /dev/null +++ b/daemon/AUTHORS @@ -0,0 +1 @@ +Pablo Neira Ayuso diff --git a/daemon/CHANGELOG b/daemon/CHANGELOG new file mode 100644 index 0000000..afab61d --- /dev/null +++ b/daemon/CHANGELOG @@ -0,0 +1,184 @@ +version 0.9.3 (yet unreleased) +------------------------------ +o fix commit of confirmed expectations (reported by Nishit Shah) +o fix double increment of counters in cache_update_force() (Niko Tyni) +o nl_dump_handler must return NFCT_CB_CONTINUE (Niko Tyni) +o initialize buffer in nl_event_handler() and nl_dump_handler() (Niko Tyni) +o CacheCommit value can be set via conntrackd.conf for the NACK approach +o fix leaks in the hashtable/cache flush path (Niko Tyni) +o fix leak if a connection already exists in the cache (Niko Tyni) +o introduce a new header that encapsulates netlink messages +o remove all '_entry' tail from all functions in cache.c +o split cache.c: move cache iterators to file cache_iterators.c +o fix inconsistencies in the cache API related to counters +o cleanup 'usage' message +o fix typo in examples/sync/nack/node1/conntrackd.conf +o introduce message checksumming as described in RFC1071 (enabled by default) +o major cleanups in the synchronization code +o just warn once that the maximum netlink socket buffer has been reached +o fix ignore conntrack entries by IP and introduce ignore pool abstraction layer +o introduce netlink socket buffer overrun handler +o constification of hash, compare and hashtable_test functions in hash.c +o introduce ACKnowledgement mechanisms to reduce the size of the resend queue +o remove OK messages at startup since provide useless data +o fix compilation warning in mcast.c: recvfrom takes socklen_t not size_t +o add a lock per buffer: makes buffer code thread safe +o introduce 'Replicate' clause to explicitely set states to be replicated +o kill cache feature abuse: introduce nicer cache hooks for sync algorithms +o fix oversized buffer allocated in the stack in the cache functions +o add support to dump internal/external cache in XML format '-x' + +version 0.9.2 (2006/01/17) +-------------------------- +o remove spamming packet lost messages +o generalize network netlink sequence tracking +o fix bogus error message on resync `-R' +o fix endianess issues in the network netlink message +o introduce generic netlink multicast primitives to send and receive +o fix bogus replayed multicast message due to sequence numbering wraparound +o introduce counter for malformed netlink messages received +o introduce a new syntax for the `Sync' section in the configuration file +o several cleanups and remove unused variables +o add autostuff to include examples in the tarball (reported by Victor Lozano) +o use the new API available in libnetfilter_conntrack-0.0.50 +o implement a NACK based protocol for replication + +version 0.9.1 (2006/11/06) +-------------------------- +o conntrackd requires kernel >= 2.6.18 +o remove bogus TIMERS_MODE constant +o implement bulk mode '-B': first works to address the preemption issue +o fix minor reduction conflicts in the configfile grammar +o check for CAP_NET_ADMIN instead of requiring root privileges +o check that linux/capability.h exists +o fix formatting at dump statistics '-s' +o move dump traffic stats before multicast traffic stats +o move event and dump handler to a generic infrastructure: kill events.c file +o kill unused function inc_ct_stats +o kill file resync.h +o cleanup broadcast_sync: renamed to mcast_send_sync +o sed 's/perror/debug/g' local.c +o fix bogus increment of update_fail stats at dump stage +o display descriptive error if we can't connect to conntrackd via UNIX socket +o remove debugging message from alarm.c +o move dump_mcast_stats to mcast.c where it really belongs +o rename stats.c to traffic_stats.c +o check for replayed/lost multicast message: simple seq tracking w/o recovery +o reissue nfnl_catch on ENOENT error: a message for other subsystem +o remove test/ directory in tree +o improve cache commit stats +o kill last_commit and last_flush from cache statistics: use the logfile +o recover cache naming for dump stats `-s' +o display multicast sequence tracking statistics: packets lost and replayed +o zero ct_sync_state and ct_stats_state structures after allocation +o improve keepalived scripts: + - resync with conntrack table on transition to master + - send bulk on transition to backup +o implement alarm cascade of ten levels +o implement timer cache flavour: limited life of entries in the external cache +o implement a global lock that protects operation with conntrack entries +o remove debug checking in cache_del_entry +o set a reduced timeout for committed entries: 180 seconds by default +o update comments on the sync-mode code +o introduce delay destroy messages facility +o increase timer for external states from 60 to 180 seconds +o remove unused replicate/dont_replicated constants +o fix cache entry clashing issue (reported by Maik Hentsche) +o fix bogus increment of error stats in the external cache +o remove pollution generated by `[REQ] cache dump' message from logfile + +version 0.9.0 (2006/09/17) +-------------------------- +o implement initial for IPv6 (untested) +o implement generic extensible cache: kill the internal and external caches +o implement persistence cache feature +o implement lifetime cache feature +o modify UNIX facilities identification numbers: + separate master conntrack facilities and internal plugin facilities +o break backward compatibility of configuration file: + remove IgnoreLoopback, use IgnoreTrafficFor instead + remove IgnoreMulticastTraffic, use IgnoreTrafficFor instead +o merge event/event_subsys and sync/sync_subsys initialization to run.c +o improve control of the iteration process in the hashtables +o fix wrong locking in the alarm thread +o supersede AcceptNAT by StripNAT clause +o replace ignore traffic array by a hashtable +o move lockfile checking before daemonization +o on initialization error give a descriptive error +o introduce netlink socket size grown limitator +o introduce force resync with master conntrack table facility '-R' +o ignore SIGPIPE signal +o kill post_step since it is not used anymore + +version 0.8.3 (2006/09/03) +-------------------------- +Author: Maik Hentsche + +o Fix typo in conntrackd -h +o Disable debugging messages by default +o No signals while signals handlings +o Add extra checkings at forking +o Check maximum size for file passed via -C + +Author: Pablo Neira Ayuso + +o retry select() if EINTR is returned (Reported by Maik Hentsche) +o Fix bug in slist_for_each_entry (Reported by Maik Hetsche) +o Signal handler registration done after intialization +o Implement alarm thread (based on Maik Hentsche's patch) +o Fix segfault on conntrackd -k (Reported by Maik Hentsche) +o Fix bug on alarm removal (Reported by Maik Hentsche) +o configure stops if bison, flex or yacc are not installed + +version 0.8.2 (2006/07/05) +-------------------------- +o RelaxTransitions clause introduced in Sync mode +o multicast messages sequence tracking +o SocketBufferSize clause to set up the netlink socket buffer +o use new libnfnetlink API to solve limitations of nfnl_listen +o extra sanity checkings for netlink multicast messages +o improve statistics +o tons of cleanups 8) + +version 0.8.1 (2006/06/13) +-------------------------- +o -f now just flushes the internal and external caches +o -F flushes the master conntrack table +o fix segfault under heavy load and signal received +o added -S mode for statistics: still needs more thinking + +version 0.8.0 (2006/06/11) +-------------------------- +o more work to generalize the daemon: now it's ready to implement +modular support for adaptive timers and conntrack statistics, time +to implement them ;). This is *still* a work in progress. + +version 0.7.2 (2006/06/05) +-------------------------- +o stupid bug in normal and alarm caches initialization: flush unset +o fix racy signal handling + +version 0.7.1 (2006/06/05) +-------------------------- +o Bugfix for multicast sockets communication + +version 0.7 (2006/06/01) +------------------------ +o Major code re-structuration: internal and external cache abstraction +o sequence tracking for event messages +o expect more changes, I still dislike some stuff in its current status ;) + +version 0.6 (2006/05/31) +------------------------ +o Lock file support +o use new API nfct_conntrack_event_raw +o major code clean ups + +version 0.5 (2006/05/30) +------------------------- +o Fix multicast server binds to wrong interface +o Include clause `IgnoreProtocol', deprecates IgnoreUDP and IgnoreICMP + +version 0.4 (2006/05/29) +------------------------ +o Initial release diff --git a/daemon/CONTRIBUTORS b/daemon/CONTRIBUTORS new file mode 100644 index 0000000..c5e40b4 --- /dev/null +++ b/daemon/CONTRIBUTORS @@ -0,0 +1,3 @@ +Maik Hentsche : + - Feedback & Brainstorming + - Bug hunting diff --git a/daemon/INSTALL b/daemon/INSTALL new file mode 100644 index 0000000..0de8dc0 --- /dev/null +++ b/daemon/INSTALL @@ -0,0 +1,199 @@ +Copyright (C) 2006-2007 Pablo Neira Ayuso + +1.Basic Installation +==================== + + To compile and install 'conntrackd' just follow the classical steps: + + $ ./configure + $ make + # make install + # mkdir /etc/conntrackd/ + +2.1. Synchronization Mode +========================= + + Conntrackd can replicate the status of the connections that are currently + being processed by your stateful firewall based on Linux. This section + describes how to setup the daemon in synchronization mode: + +2.1.1. Requirements + + You have to install the following software in order to get conntrackd working, + make sure that you have installed them correctly before going forward: + + o linux kernel version >= 2.6.18 (http://www.kernel.org) with support for: + - connection tracking system (quite obvious ;) + - nfnetlink + - ctnetlink (ip_conntrack_netlink) + - connection tracking event notification API + + o libnfnetlink: the netfilter netlink library + + Since conntrackd version 0.9.2 you can used the official release availble at + http://www.netfilter.org/projects/libnfnetlink/files/ + + Up to conntrackd version 0.9.1 use the unofficial release available at the + download section + + o libnetfilter_conntrack: the netfilter conntrack library + + Since conntrackd version 0.9.2 you can used the official release availble at + http://www.netfilter.org/projects/libnetfilter_conntrack/files/ + + Up to conntrackd version 0.9.1 use the unnoficial release available at the + download section + + o Keepalived version 1.x (http://www.keepalived.org) + check if your distribution comes with a recent version + +2.1.2. Configuration + + 1) Setting up keepalived + + There is an example file available inside the conntrackd tarball: + + For node 1: conntrackd-x.x.x/examples/sync/node1/keepalived.conf + For node 2: conntrackd-x.x.x/examples/sync/node2/keepalived.conf + + These files can be used to set up a simple VRRP cluster composed of + two machines that hold the virtual IPs 192.168.0.100 on eth0 and + 192.168.1.100 on eth1. + + If you are not familiar with keepalived, please read the official + docs available at http://www.keepalived.org + + Please, make sure that keepalived is correctly working before passing + to step 2) + + 2) Setting up conntrackd + + To setup 'conntrackd' in synchronization mode, you have to put the + configuration file in the directory /etc/conntrackd. + + On node 1: + # cp examples/sync/_type_/node1/conntrackd.conf /etc/conntrackd.conf + + On node 2: + # cp examples/sync/_type_/node1/conntrackd.conf /etc/conntrackd.conf + + Where _type_ is the synchronization type selected, currently there are + two: the persistent mode and the NACK mode. The persistent mode consumes + more resources than the NACK mode, however the NACK mode is still + experimental + + Do not forget to edit the files in order to adapt them to the + setting that you are deploying. + + Note: If you don't want to put the config file under /etc/conntrackd, + just tell conntrackd where to find it passing the option -C + + 3) Running conntrackd + + Conntrackd can run in console mode, in that case just type 'conntrackd', + otherwise, if you want to run it in daemon mode the type 'conntrackd -d'. + + 4) Checking that conntrackd is working fine + + Conntrackd comes with several facilities to check its status: + + - Dump the cache of connections that are currently being processed by + this node (aka. internal cache): + + # conntrackd -i + + - Dump the cache of connections that has been transfered from + others active nodes in the network (aka. external cache) + + # conntrackd -e + + - Dump statistics collected by the replication daemon: + + # conntrackd -s + + 5) Setting up interaction with keepalived + + If keepalived detects the failure of the active node, then it designates + a candidate node that will replace the failing active. On such event, + the external cache, eg. the cache that contains the connections processed + by other nodes, must be commited. To commit the external cache, just type: + + # conntrackd -c + + See that keepalived provides a shell script interface to interact with + other programs, so we can automate the process of commiting the external + cache by introducing the following line in the keepalived file: + + notify_master /etc/conntrackd/script_master.sh + + The script 'script_master.sh' just the following: + + #!/bin/sh + /usr/sbin/conntrackd -c + + Therefore, on failure event, the candidate node takes over the virtual + IPs and the connections that the failing active was processing. Observe + that this file differs for the NACK mode. + + 6) Disable TCP window tracking + + Until the appropiate patches don't go into kernel mainline, you will have + to disable TCP window tracking, consider this as a temporary solution: + + # echo 1 > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_be_liberal + +2.2. Statistics mode +==================== + + Conntrackd can also run as statistics daemon, if you are not interested in + this mode, just skip it. It is not required in order to get the + synchronization mode working. This section details how to setup the daemon + in statistics mode: + +2.2.1. Requirements + + You have to install the following software in order to get conntrackd working, + make sure that you have them installed correctly before going forward: + + o linux kernel version >= 2.6.18 (http://www.kernel.org) with support for: + - connection tracking system + - nfnetlink + - ctnetlink (ip_conntrack_netlink) + - connection tracking event notification API + + o libnfnetlink: the netfilter netlink library + + Since conntrackd version 0.9.2 you can used the official release availble at + http://www.netfilter.org/projects/libnfnetlink/files/ + + Up to conntrackd version 0.9.1 use the unofficial release available at the + download section + + o libnetfilter_conntrack: the netfilter conntrack library + + Since conntrackd version 0.9.2 you can used the official release availble at + http://www.netfilter.org/projects/libnetfilter_conntrack/files/ + + Up to conntrackd version 0.9.1 use the unnoficial release available at the + download section + +2.2.2. Configuration + + Setting up conntrackd in statistics mode is rather easy. Just copy the + configuration file + + # cp examples/stats/conntrackd.conf /etc/conntrackd.conf + +2.2.3. Running conntrackd in statistics mode + + To run conntrackd in statistics mode: + + # conntrackd -S + + Alternatively, you can run conntrackd in daemon mode: + + # conntrackd -S -d + + In order to dump the statistics, just type: + + # conntrackd -s diff --git a/daemon/Make_global.am b/daemon/Make_global.am new file mode 100644 index 0000000..685add7 --- /dev/null +++ b/daemon/Make_global.am @@ -0,0 +1 @@ +INCLUDES=$(all_includes) -I$(top_srcdir)/include diff --git a/daemon/Makefile.am b/daemon/Makefile.am new file mode 100644 index 0000000..998f4c6 --- /dev/null +++ b/daemon/Makefile.am @@ -0,0 +1,21 @@ +include Make_global.am + +# not a GNU package. You can remove this line, if +# have all needed files, that a GNU package needs +AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 + +# man_MANS = "" +# EXTRA_DIST = $(man_MANS) Make_global.am debian +EXTRA_DIST = Make_global.am CHANGELOG TODO + +SUBDIRS = src +DIST_SUBDIRS = include src examples +LINKOPTS = -lnfnetlink -lnetfilter_conntrack -lpthread +AM_CFLAGS = -g + +$(OBJECTS): libtool +libtool: $(LIBTOOL_DEPS) + $(SHELL) ./config.status --recheck + +dist-hook: + rm -rf `find $(distdir)/debian -name .svn` diff --git a/daemon/TODO b/daemon/TODO new file mode 100644 index 0000000..130b1f8 --- /dev/null +++ b/daemon/TODO @@ -0,0 +1,18 @@ +There are several tasks that are pending to be done, I have classified them +by dificulty levels: + +Relatively easy +=============== + +- test ipv6 support +- improve shell scripts +- test NACK based protocol +- manpage for conntrackd + +Requires some work +================== + +- study better keepalived transitions +- implement support for TCP window tracking (patches are on the table) + - at the moment you have to disable it: + echo 1 > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_be_liberal diff --git a/daemon/autogen.sh b/daemon/autogen.sh new file mode 100755 index 0000000..e76d3ef --- /dev/null +++ b/daemon/autogen.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +run () +{ + echo "running: $*" + eval $* + + if test $? != 0 ; then + echo "error: while running '$*'" + exit 1 + fi +} + +run aclocal +run libtoolize -f +#run autoheader +run automake -a +run autoconf diff --git a/daemon/configure.in b/daemon/configure.in new file mode 100644 index 0000000..92e512a --- /dev/null +++ b/daemon/configure.in @@ -0,0 +1,106 @@ +AC_INIT(conntrackd, 0.9.2, pablo@netfilter.org) + +AC_CANONICAL_SYSTEM + +AM_INIT_AUTOMAKE + +AC_PROG_CC +AM_PROG_LIBTOOL +AC_PROG_INSTALL +AC_PROG_LN_S +AM_PROG_LEX +AC_PROG_YACC + +case $target in +*-*-linux*) ;; +*) AC_MSG_ERROR([Linux only, dude!]);; +esac + +AC_CHECK_PROGS(XYACC,$YACC bison yacc,none) +if test "$XYACC" = "none" +then + echo "*** Error: No suitable bison/yacc found. ***" + echo " Please install the 'bison' package." + exit 1 +fi +AC_CHECK_PROGS(XLEX,$LEX flex lex,none) +if test "$XLEX" = "none" +then + echo "*** Error: No suitable bison/yacc found. ***" + echo " Please install the 'bison' package." + exit 1 +fi + +AC_CHECK_HEADERS([linux/capability.h],, [AC_MSG_ERROR([Cannot find linux/capabibility.h])]) + +# Checks for libraries. +# FIXME: Replace `main' with a function in `-lc': +dnl AC_CHECK_LIB([c], [main]) +# FIXME: Replace `main' with a function in `-ldl': + +AC_CHECK_LIB([nfnetlink], [nfnl_talk] ,,,[-lnfnetlink]) +AC_CHECK_LIB([netfilter_conntrack], [nfct_dump_conntrack_table] ,,,[-lnetfilter_conntrack]) +AC_CHECK_LIB([pthread], [pthread_create] ,,,[-lpthread]) + +AC_CHECK_HEADERS(arpa/inet.h) +dnl check for inet_pton +AC_CHECK_FUNCS(inet_pton) +dnl Some systems have it, but not IPv6 +if test "$ac_cv_func_inet_pton" = "yes" ; then +AC_MSG_CHECKING(if inet_pton supports IPv6) +AC_TRY_RUN( + [ +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +int main() + { + struct in6_addr addr6; + if (inet_pton(AF_INET6, "::1", &addr6) < 1) + exit(1); + else + exit(0); + } + ], [ AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED(HAVE_INET_PTON_IPV6, 1, [Define to 1 if inet_pton supports IPv6.]) + ], AC_MSG_RESULT(no), AC_MSG_RESULT(no)) +fi + +# Checks for header files. +dnl AC_HEADER_STDC +dnl AC_CHECK_HEADERS([netinet/in.h stdlib.h]) + +# Checks for typedefs, structures, and compiler characteristics. +dnl AC_C_CONST +dnl AC_C_INLINE + +# Checks for library functions. +dnl AC_FUNC_MALLOC +dnl AC_FUNC_VPRINTF +dnl AC_CHECK_FUNCS([memset]) + +dnl-------------------------------- + +dnl if test ! -z "$libdir"; then +dnl MODULE_DIR="\\\"$libdir/conntrack/\\\"" +dnl CFLAGS="$CFLAGS -DCONNTRACK_LIB_DIR=$MODULE_DIR" +dnl fi + +dnl-------------------------------- + +dnl AC_CONFIG_FILES([Makefile +dnl debug/Makefile +dnl debug/src/Makefile +dnl extensions/Makefile +dnl src/Makefile]) + +AC_OUTPUT(Makefile src/Makefile include/Makefile examples/Makefile examples/stats/Makefile examples/sync/Makefile examples/sync/persistent/Makefile examples/sync/nack/Makefile examples/sync/persistent/node1/Makefile examples/sync/persistent/node2/Makefile examples/sync/nack/node1/Makefile examples/sync/nack/node2/Makefile) diff --git a/daemon/examples/Makefile.am b/daemon/examples/Makefile.am new file mode 100644 index 0000000..be83d42 --- /dev/null +++ b/daemon/examples/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = stats sync diff --git a/daemon/examples/debian.conntrackd.init.d b/daemon/examples/debian.conntrackd.init.d new file mode 100644 index 0000000..ba847dd --- /dev/null +++ b/daemon/examples/debian.conntrackd.init.d @@ -0,0 +1,48 @@ +#!/bin/sh +# +# /etc/init.d/conntrackd +# +# Maximilian Wilhelm +# -- Mon, 06 Nov 2006 18:39:07 +0100 +# + +export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + +NAME="conntrackd" +DAEMON=`command -v conntrackd` +CONFIG="/etc/conntrack/conntrackd.conf" +PIDFILE="/var/run/${NAME}.pid" + + +# Gracefully exit if there is no daemon (debian way of life) +if [ ! -x "${DAEMON}" ]; then + exit 0 +fi + +# Check for config file +if [ ! -f /etc/conntrackd/conntrackd.conf ]; then + echo "Error: There is no config file for $NAME" >&2 + exit 1; +fi + +case "$1" in + start) + echo -n "Starting $NAME: " + start-stop-daemon --start --quiet --make-pidfile --pidfile "/var/run/${NAME}.pid" --background --exec "${DAEMON}" && echo "done." || echo "FAILED!" + ;; + stop) + echo -n "Stopping $NAME:" + start-stop-daemon --stop --quiet --oknodo --pidfile "/var/run/${NAME}.pid" && echo "done." || echo "FAILED!" + ;; + + restart) + $0 start + $0 stop + ;; + + *) + echo "Usage: /etc/init.d/conntrackd {start|stop|restart}" + exit 1 +esac + +exit 0 diff --git a/daemon/examples/stats/Makefile.am b/daemon/examples/stats/Makefile.am new file mode 100644 index 0000000..b43c3b8 --- /dev/null +++ b/daemon/examples/stats/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = conntrackd.conf diff --git a/daemon/examples/stats/conntrackd.conf b/daemon/examples/stats/conntrackd.conf new file mode 100644 index 0000000..e514ac0 --- /dev/null +++ b/daemon/examples/stats/conntrackd.conf @@ -0,0 +1,69 @@ +# +# General settings +# +General { + # + # Number of buckets in the caches: hash table + # + HashSize 8192 + + # + # Maximum number of conntracks: + # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max + # + HashLimit 65535 + + # + # Logfile + # + LogFile /var/log/conntrackd.log + + # + # Lockfile + # + LockFile /var/lock/conntrack.lock + + # + # Unix socket configuration + # + UNIX { + Path /tmp/sync.sock + Backlog 20 + } + + # + # Netlink socket buffer size + # + SocketBufferSize 262142 + + # + # Increase the socket buffer up to maximun if required + # + SocketBufferSizeMaxGrown 655355 +} + +# +# Ignore traffic for a certain set of IP's: Usually +# all the IP assigned to the firewall since local +# traffic must be ignored, just forwarded connections +# are worth to replicate +# +IgnoreTrafficFor { + IPv4_address 127.0.0.1 # loopback +} + +# +# Do not replicate certain protocol traffic +# +IgnoreProtocol { + UDP +# ICMP +# IGMP +# VRRP + # numeric numbers also valid +} + +# +# Strip NAT traffic +# +StripNAT diff --git a/daemon/examples/sync/Makefile.am b/daemon/examples/sync/Makefile.am new file mode 100644 index 0000000..28e7643 --- /dev/null +++ b/daemon/examples/sync/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = persistent nack diff --git a/daemon/examples/sync/nack/Makefile.am b/daemon/examples/sync/nack/Makefile.am new file mode 100644 index 0000000..6fd99b1 --- /dev/null +++ b/daemon/examples/sync/nack/Makefile.am @@ -0,0 +1,2 @@ +EXTRA_DIST = script_backup.sh script_master.sh +SUBDIRS = node1 node2 diff --git a/daemon/examples/sync/nack/README b/daemon/examples/sync/nack/README new file mode 100644 index 0000000..66987f7 --- /dev/null +++ b/daemon/examples/sync/nack/README @@ -0,0 +1 @@ +This directory contains the files for the NACK based protocol diff --git a/daemon/examples/sync/nack/node1/Makefile.am b/daemon/examples/sync/nack/node1/Makefile.am new file mode 100644 index 0000000..edc0ed7 --- /dev/null +++ b/daemon/examples/sync/nack/node1/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = conntrackd.conf keepalived.conf diff --git a/daemon/examples/sync/nack/node1/conntrackd.conf b/daemon/examples/sync/nack/node1/conntrackd.conf new file mode 100644 index 0000000..f24fa7e --- /dev/null +++ b/daemon/examples/sync/nack/node1/conntrackd.conf @@ -0,0 +1,125 @@ +# +# Synchronizer settings +# +Sync { + Mode NACK { + # + # Size of the buffer that hold destroy messages for + # possible resends (in bytes) + # + ResendBufferSize 262144 + + # + # Entries committed to the connection tracking table + # starts with a limited timeout of N seconds until the + # takeover process is completed. + # + CommitTimeout 180 + + # Set Acknowledgement window size + ACKWindowSize 20 + } + + # + # Multicast IP and interface where messages are + # broadcasted (dedicated link). IMPORTANT: Make sure + # that iptables accepts traffic for destination + # 225.0.0.50, eg: + # + # iptables -I INPUT -d 225.0.0.50 -j ACCEPT + # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT + # + Multicast { + IPv4_address 225.0.0.50 + IPv4_interface 192.168.100.100 # IP of dedicated link + Group 3780 + Backlog 20 + } + + # Enable/Disable message checksumming + Checksum on + + # Uncomment this if you want to replicate just certain TCP states. + # This option introduces a tradeoff in the replication: it reduces + # CPU consumption and lost messages rate at the cost of having + # backup replicas that don't contain the current state that the active + # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, + # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. + # + # Replicate ESTABLISHED TIME_WAIT for TCP +} + +# +# General settings +# +General { + # + # Number of buckets in the caches: hash table + # + HashSize 8192 + + # + # Maximum number of conntracks: + # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max + # + HashLimit 65535 + + # + # Logfile + # + LogFile /var/log/conntrackd.log + + # + # Lockfile + # + LockFile /var/lock/conntrack.lock + + # + # Unix socket configuration + # + UNIX { + Path /tmp/sync.sock + Backlog 20 + } + + # + # Netlink socket buffer size + # + SocketBufferSize 262142 + + # + # Increase the socket buffer up to maximum if required + # + SocketBufferSizeMaxGrown 655355 +} + +# +# Ignore traffic for a certain set of IP's: Usually +# all the IP assigned to the firewall since local +# traffic must be ignored, just forwarded connections +# are worth to replicate +# +IgnoreTrafficFor { + IPv4_address 127.0.0.1 # loopback + IPv4_address 192.168.0.1 + IPv4_address 192.168.1.1 + IPv4_address 192.168.100.100 # dedicated link ip + IPv4_address 192.168.0.100 # virtual IP 1 + IPv4_address 192.168.1.100 # virtual IP 2 +} + +# +# Do not replicate certain protocol traffic +# +IgnoreProtocol { + UDP + ICMP + IGMP + VRRP + # numeric numbers also valid +} + +# +# Strip NAT traffic +# +StripNAT diff --git a/daemon/examples/sync/nack/node1/keepalived.conf b/daemon/examples/sync/nack/node1/keepalived.conf new file mode 100644 index 0000000..41aa35b --- /dev/null +++ b/daemon/examples/sync/nack/node1/keepalived.conf @@ -0,0 +1,38 @@ +vrrp_sync_group G1 { # must be before vrrp_instance declaration + group { + VI_1 + VI_2 + } + notify_master /etc/conntrackd/script_master.sh + notify_backup /etc/conntrackd/script_backup.sh +} + +vrrp_instance VI_1 { + interface eth1 + state SLAVE + virtual_router_id 61 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.0.100 # default CIDR mask is /32 + } +} + +vrrp_instance VI_2 { + interface eth0 + state SLAVE + virtual_router_id 62 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.1.100 + } +} diff --git a/daemon/examples/sync/nack/node2/Makefile.am b/daemon/examples/sync/nack/node2/Makefile.am new file mode 100644 index 0000000..edc0ed7 --- /dev/null +++ b/daemon/examples/sync/nack/node2/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = conntrackd.conf keepalived.conf diff --git a/daemon/examples/sync/nack/node2/conntrackd.conf b/daemon/examples/sync/nack/node2/conntrackd.conf new file mode 100644 index 0000000..4f15773 --- /dev/null +++ b/daemon/examples/sync/nack/node2/conntrackd.conf @@ -0,0 +1,124 @@ +# +# Synchronizer settings +# +Sync { + Mode NACK { + # + # Size of the buffer that hold destroy messages for + # possible resends (in bytes) + # + ResendBufferSize 262144 + + # Entries committed to the connection tracking table + # starts with a limited timeout of N seconds until the + # takeover process is completed. + # + CommitTimeout 180 + + # Set Acknowledgement window size + ACKWindowSize 20 + } + + # + # Multicast IP and interface where messages are + # broadcasted (dedicated link). IMPORTANT: Make sure + # that iptables accepts traffic for destination + # 225.0.0.50, eg: + # + # iptables -I INPUT -d 225.0.0.50 -j ACCEPT + # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT + # + Multicast { + IPv4_address 225.0.0.50 + IPv4_interface 192.168.100.200 # IP of dedicated link + Group 3780 + Backlog 20 + } + + # Enable/Disable message checksumming + Checksum on + + # Uncomment this if you want to replicate just certain TCP states. + # This option introduces a tradeoff in the replication: it reduces + # CPU consumption and lost messages rate at the cost of having + # backup replicas that don't contain the current state that the active + # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, + # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. + # + # Replicate ESTABLISHED TIME_WAIT for TCP +} + +# +# General settings +# +General { + # + # Number of buckets in the caches: hash table + # + HashSize 8192 + + # + # Maximum number of conntracks: + # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max + # + HashLimit 65535 + + # + # Logfile + # + LogFile /var/log/conntrackd.log + + # + # Lockfile + # + LockFile /var/lock/conntrack.lock + + # + # Unix socket configuration + # + UNIX { + Path /tmp/sync.sock + Backlog 20 + } + + # + # Netlink socket buffer size + # + SocketBufferSize 262142 + + # + # Increase the socket buffer up to maximum if required + # + SocketBufferSizeMaxGrown 655355 +} + +# +# Ignore traffic for a certain set of IP's: Usually +# all the IP assigned to the firewall since local +# traffic must be ignored, just forwarded connections +# are worth to replicate +# +IgnoreTrafficFor { + IPv4_address 127.0.0.1 # loopback + IPv4_address 192.168.0.2 + IPv4_address 192.168.1.2 + IPv4_address 192.168.100.200 # dedicated link ip + IPv4_address 192.168.0.200 # virtual IP 1 + IPv4_address 192.168.1.200 # virtual IP 2 +} + +# +# Do not replicate certain protocol traffic +# +IgnoreProtocol { + UDP + ICMP + IGMP + VRRP + # numeric numbers also valid +} + +# +# Strip NAT traffic +# +StripNAT diff --git a/daemon/examples/sync/nack/node2/keepalived.conf b/daemon/examples/sync/nack/node2/keepalived.conf new file mode 100644 index 0000000..41aa35b --- /dev/null +++ b/daemon/examples/sync/nack/node2/keepalived.conf @@ -0,0 +1,38 @@ +vrrp_sync_group G1 { # must be before vrrp_instance declaration + group { + VI_1 + VI_2 + } + notify_master /etc/conntrackd/script_master.sh + notify_backup /etc/conntrackd/script_backup.sh +} + +vrrp_instance VI_1 { + interface eth1 + state SLAVE + virtual_router_id 61 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.0.100 # default CIDR mask is /32 + } +} + +vrrp_instance VI_2 { + interface eth0 + state SLAVE + virtual_router_id 62 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.1.100 + } +} diff --git a/daemon/examples/sync/nack/script_backup.sh b/daemon/examples/sync/nack/script_backup.sh new file mode 100755 index 0000000..813e375 --- /dev/null +++ b/daemon/examples/sync/nack/script_backup.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +/usr/sbin/conntrackd -n # request a resync from other nodes via multicast diff --git a/daemon/examples/sync/nack/script_master.sh b/daemon/examples/sync/nack/script_master.sh new file mode 100755 index 0000000..ff1dbc0 --- /dev/null +++ b/daemon/examples/sync/nack/script_master.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +/usr/sbin/conntrackd -c # commit the cache +/usr/sbin/conntrackd -f # flush the caches +/usr/sbin/conntrackd -R # resync with kernel conntrack table diff --git a/daemon/examples/sync/persistent/Makefile.am b/daemon/examples/sync/persistent/Makefile.am new file mode 100644 index 0000000..6fd99b1 --- /dev/null +++ b/daemon/examples/sync/persistent/Makefile.am @@ -0,0 +1,2 @@ +EXTRA_DIST = script_backup.sh script_master.sh +SUBDIRS = node1 node2 diff --git a/daemon/examples/sync/persistent/README b/daemon/examples/sync/persistent/README new file mode 100644 index 0000000..36b5989 --- /dev/null +++ b/daemon/examples/sync/persistent/README @@ -0,0 +1 @@ +This directory contains the files for the PERSISTENT based protocol diff --git a/daemon/examples/sync/persistent/node1/Makefile.am b/daemon/examples/sync/persistent/node1/Makefile.am new file mode 100644 index 0000000..edc0ed7 --- /dev/null +++ b/daemon/examples/sync/persistent/node1/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = conntrackd.conf keepalived.conf diff --git a/daemon/examples/sync/persistent/node1/conntrackd.conf b/daemon/examples/sync/persistent/node1/conntrackd.conf new file mode 100644 index 0000000..90afeb7 --- /dev/null +++ b/daemon/examples/sync/persistent/node1/conntrackd.conf @@ -0,0 +1,130 @@ +# +# Synchronizer settings +# +Sync { + Mode PERSISTENT { + # + # If a conntrack entry is not modified in <= 15 seconds, then + # a message is broadcasted. This mechanism is used to + # resynchronize nodes that just joined the multicast group + # + RefreshTime 15 + + # + # If we don't receive a notification about the state of + # an entry in the external cache after N seconds, then + # remove it. + # + CacheTimeout 180 + + # + # Entries committed to the connection tracking table + # starts with a limited timeout of N seconds until the + # takeover process is completed. + # + CommitTimeout 180 + } + + # + # Multicast IP and interface where messages are + # broadcasted (dedicated link). IMPORTANT: Make sure + # that iptables accepts traffic for destination + # 225.0.0.50, eg: + # + # iptables -I INPUT -d 225.0.0.50 -j ACCEPT + # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT + # + Multicast { + IPv4_address 225.0.0.50 + IPv4_interface 192.168.100.100 # IP of dedicated link + Group 3780 + Backlog 20 + } + + # Enable/Disable message checksumming + Checksum on + + # Uncomment this if you want to replicate just certain TCP states. + # This option introduces a tradeoff in the replication: it reduces + # CPU consumption and lost messages rate at the cost of having + # backup replicas that don't contain the current state that the active + # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, + # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. + # + # Replicate ESTABLISHED TIME_WAIT for TCP +} + +# +# General settings +# +General { + # + # Number of buckets in the caches: hash table + # + HashSize 8192 + + # + # Maximum number of conntracks: + # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max + # + HashLimit 65535 + + # + # Logfile + # + LogFile /var/log/conntrackd.log + + # + # Lockfile + # + LockFile /var/lock/conntrack.lock + + # + # Unix socket configuration + # + UNIX { + Path /tmp/sync.sock + Backlog 20 + } + + # + # Netlink socket buffer size + # + SocketBufferSize 262142 + + # + # Increase the socket buffer up to maximum if required + # + SocketBufferSizeMaxGrown 655355 +} + +# +# Ignore traffic for a certain set of IP's: Usually +# all the IP assigned to the firewall since local +# traffic must be ignored, just forwarded connections +# are worth to replicate +# +IgnoreTrafficFor { + IPv4_address 127.0.0.1 # loopback + IPv4_address 192.168.0.1 + IPv4_address 192.168.1.1 + IPv4_address 192.168.100.100 # dedicated link ip + IPv4_address 192.168.0.100 # virtual IP 1 + IPv4_address 192.168.1.100 # virtual IP 2 +} + +# +# Do not replicate certain protocol traffic +# +IgnoreProtocol { + UDP + ICMP + IGMP + VRRP + # numeric numbers also valid +} + +# +# Strip NAT traffic +# +StripNAT diff --git a/daemon/examples/sync/persistent/node1/keepalived.conf b/daemon/examples/sync/persistent/node1/keepalived.conf new file mode 100644 index 0000000..41aa35b --- /dev/null +++ b/daemon/examples/sync/persistent/node1/keepalived.conf @@ -0,0 +1,38 @@ +vrrp_sync_group G1 { # must be before vrrp_instance declaration + group { + VI_1 + VI_2 + } + notify_master /etc/conntrackd/script_master.sh + notify_backup /etc/conntrackd/script_backup.sh +} + +vrrp_instance VI_1 { + interface eth1 + state SLAVE + virtual_router_id 61 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.0.100 # default CIDR mask is /32 + } +} + +vrrp_instance VI_2 { + interface eth0 + state SLAVE + virtual_router_id 62 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.1.100 + } +} diff --git a/daemon/examples/sync/persistent/node2/Makefile.am b/daemon/examples/sync/persistent/node2/Makefile.am new file mode 100644 index 0000000..edc0ed7 --- /dev/null +++ b/daemon/examples/sync/persistent/node2/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = conntrackd.conf keepalived.conf diff --git a/daemon/examples/sync/persistent/node2/conntrackd.conf b/daemon/examples/sync/persistent/node2/conntrackd.conf new file mode 100644 index 0000000..aee4a29 --- /dev/null +++ b/daemon/examples/sync/persistent/node2/conntrackd.conf @@ -0,0 +1,130 @@ +# +# Synchronizer settings +# +Sync { + Mode PERSISTENT { + # + # If a conntrack entry is not modified in <= 15 seconds, then + # a message is broadcasted. This mechanism is used to + # resynchronize nodes that just joined the multicast group + # + RefreshTime 15 + + # + # If we don't receive a notification about the state of + # an entry in the external cache after N seconds, then + # remove it. + # + CacheTimeout 180 + + # + # Entries committed to the connection tracking table + # starts with a limited timeout of N seconds until the + # takeover process is completed. + # + CommitTimeout 180 + } + + # + # Multicast IP and interface where messages are + # broadcasted (dedicated link). IMPORTANT: Make sure + # that iptables accepts traffic for destination + # 225.0.0.50, eg: + # + # iptables -I INPUT -d 225.0.0.50 -j ACCEPT + # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT + # + Multicast { + IPv4_address 225.0.0.50 + IPv4_interface 192.168.100.200 # IP of dedicated link + Group 3780 + Backlog 20 + } + + # Enable/Disable message checksumming + Checksum on + + # Uncomment this if you want to replicate just certain TCP states. + # This option introduces a tradeoff in the replication: it reduces + # CPU consumption and lost messages rate at the cost of having + # backup replicas that don't contain the current state that the active + # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, + # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. + # + # Replicate ESTABLISHED TIME_WAIT for TCP +} + +# +# General settings +# +General { + # + # Number of buckets in the caches: hash table + # + HashSize 8192 + + # + # Maximum number of conntracks: + # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max + # + HashLimit 65535 + + # + # Logfile + # + LogFile /var/log/conntrackd.log + + # + # Lockfile + # + LockFile /var/lock/conntrack.lock + + # + # Unix socket configuration + # + UNIX { + Path /tmp/sync.sock + Backlog 20 + } + + # + # Netlink socket buffer size + # + SocketBufferSize 262142 + + # + # Increase the socket buffer up to maximum if required + # + SocketBufferSizeMaxGrown 655355 +} + +# +# Ignore traffic for a certain set of IP's: Usually +# all the IP assigned to the firewall since local +# traffic must be ignored, just forwarded connections +# are worth to replicate +# +IgnoreTrafficFor { + IPv4_address 127.0.0.1 # loopback + IPv4_address 192.168.0.2 + IPv4_address 192.168.1.2 + IPv4_address 192.168.100.200 # dedicated link ip + IPv4_address 192.168.0.200 # virtual IP 1 + IPv4_address 192.168.1.200 # virtual IP 2 +} + +# +# Do not replicate certain protocol traffic +# +IgnoreProtocol { + UDP + ICMP + IGMP + VRRP + # numeric numbers also valid +} + +# +# Strip NAT traffic +# +StripNAT diff --git a/daemon/examples/sync/persistent/node2/keepalived.conf b/daemon/examples/sync/persistent/node2/keepalived.conf new file mode 100644 index 0000000..41aa35b --- /dev/null +++ b/daemon/examples/sync/persistent/node2/keepalived.conf @@ -0,0 +1,38 @@ +vrrp_sync_group G1 { # must be before vrrp_instance declaration + group { + VI_1 + VI_2 + } + notify_master /etc/conntrackd/script_master.sh + notify_backup /etc/conntrackd/script_backup.sh +} + +vrrp_instance VI_1 { + interface eth1 + state SLAVE + virtual_router_id 61 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.0.100 # default CIDR mask is /32 + } +} + +vrrp_instance VI_2 { + interface eth0 + state SLAVE + virtual_router_id 62 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.1.100 + } +} diff --git a/daemon/examples/sync/persistent/script_backup.sh b/daemon/examples/sync/persistent/script_backup.sh new file mode 100755 index 0000000..8ea2ad8 --- /dev/null +++ b/daemon/examples/sync/persistent/script_backup.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +/usr/sbin/conntrackd -B diff --git a/daemon/examples/sync/persistent/script_master.sh b/daemon/examples/sync/persistent/script_master.sh new file mode 100755 index 0000000..70c26c9 --- /dev/null +++ b/daemon/examples/sync/persistent/script_master.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +/usr/sbin/conntrackd -c +/usr/sbin/conntrackd -R diff --git a/daemon/include/Makefile.am b/daemon/include/Makefile.am new file mode 100644 index 0000000..e669d73 --- /dev/null +++ b/daemon/include/Makefile.am @@ -0,0 +1,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 + diff --git a/daemon/include/alarm.h b/daemon/include/alarm.h new file mode 100644 index 0000000..93e6482 --- /dev/null +++ b/daemon/include/alarm.h @@ -0,0 +1,13 @@ +#ifndef _TIMER_H_ +#define _TIMER_H_ + +#include "linux_list.h" + +struct alarm_list { + struct list_head head; + unsigned long expires; + void *data; + void (*function)(struct alarm_list *a, void *data); +}; + +#endif diff --git a/daemon/include/buffer.h b/daemon/include/buffer.h new file mode 100644 index 0000000..8d72dfb --- /dev/null +++ b/daemon/include/buffer.h @@ -0,0 +1,32 @@ +#ifndef _BUFFER_H_ +#define _BUFFER_H_ + +#include +#include +#include +#include +#include "linux_list.h" + +struct buffer { + pthread_mutex_t lock; + size_t max_size; + size_t cur_size; + struct list_head head; +}; + +struct buffer_node { + struct list_head head; + size_t size; + char data[0]; +}; + +struct buffer *buffer_create(size_t max_size); +void buffer_destroy(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)); + +#endif diff --git a/daemon/include/cache.h b/daemon/include/cache.h new file mode 100644 index 0000000..7d9559a --- /dev/null +++ b/daemon/include/cache.h @@ -0,0 +1,92 @@ +#ifndef _CACHE_H_ +#define _CACHE_H_ + +#include +#include + +/* cache features */ +enum { + NO_FEATURES = 0, + + TIMER_FEATURE = 0, + TIMER = (1 << TIMER_FEATURE), + + LIFETIME_FEATURE = 2, + LIFETIME = (1 << LIFETIME_FEATURE), + + __CACHE_MAX_FEATURE +}; +#define CACHE_MAX_FEATURE __CACHE_MAX_FEATURE + +struct cache; +struct us_conntrack; + +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); +}; + +extern struct cache_feature lifetime_feature; +extern struct cache_feature timer_feature; + +#define CACHE_MAX_NAMELEN 32 + +struct cache { + char name[CACHE_MAX_NAMELEN]; + struct hashtable *h; + + unsigned int num_features; + struct cache_feature **features; + unsigned int feature_type[CACHE_MAX_FEATURE]; + unsigned int *feature_offset; + struct cache_extra *extra; + unsigned int extra_offset; + + /* statistics */ + 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 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); +}; + +struct nf_conntrack; + +struct cache *cache_create(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); +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_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 *); + +/* iterators */ +void cache_dump(struct cache *c, int fd, int type); +void cache_commit(struct cache *c); +void cache_flush(struct cache *c); +void cache_bulk(struct cache *c); + +#endif diff --git a/daemon/include/conntrackd.h b/daemon/include/conntrackd.h new file mode 100644 index 0000000..a5f7a3a --- /dev/null +++ b/daemon/include/conntrackd.h @@ -0,0 +1,174 @@ +#ifndef _CONNTRACKD_H_ +#define _CONNTRACKD_H_ + +#include "mcast.h" +#include "local.h" + +#include +#include +#include "cache.h" +#include "debug.h" +#include +#include "state_helper.h" +#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 DEFAULT_CONFIGFILE "/etc/conntrackd/conntrackd.conf" +#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 = (1 << SYNC_MODE_PERSISTENT_BIT), + + SYNC_MODE_NACK_BIT = 4, + SYNC_MODE_NACK = (1 << SYNC_MODE_NACK_BIT), + + DONT_CHECKSUM_BIT = 5, + DONT_CHECKSUM = (1 << DONT_CHECKSUM_BIT), +}; + +/* daemon/request modes */ +#define NOT_SET 0 +#define DAEMON 1 +#define REQUEST 2 + +/* conntrackd modes */ +#define SYNC_MODE 0 +#define STATS_MODE 1 + +/* FILENAME_MAX is 4096 on my system, perhaps too much? */ +#ifndef FILENAME_MAXLEN +#define FILENAME_MAXLEN 256 +#endif + +union inet_address { + u_int32_t ipv4; + u_int32_t ipv6[4]; + u_int32_t all[4]; +}; + +#define CONFIG(x) conf.x + +struct ct_conf { + char logfile[FILENAME_MAXLEN]; + char lockfile[FILENAME_MAXLEN]; + int hashsize; /* hashtable size */ + struct mcast_conf mcast; /* multicast settings */ + struct local_conf local; /* unix socket facilities */ + int limit; + int refresh; + int cache_timeout; /* cache entries timeout */ + int commit_timeout; /* committed entries timeout */ + unsigned int netlink_buffer_size; + unsigned int netlink_buffer_size_max_grown; + unsigned char ignore_protocol[IPPROTO_MAX]; + union inet_address *listen_to; + unsigned int listen_to_len; + unsigned int flags; + int family; /* protocol family */ + unsigned int resend_buffer_size;/* NACK protocol */ + unsigned int window_size; +}; + +#define STATE(x) st.x + +struct ct_general_state { + sigset_t block; + FILE *log; + int local; + struct ct_mode *mode; + 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 */ + u_int64_t malformed; + u_int64_t bytes[NFCT_DIR_MAX]; + u_int64_t packets[NFCT_DIR_MAX]; +}; + +#define STATE_SYNC(x) state.sync->x + +struct ct_sync_state { + struct cache *internal; /* internal events cache (netlink) */ + struct cache *external; /* external events cache (mcast) */ + + struct mcast_sock *mcast_server; /* multicast socket: incoming */ + struct mcast_sock *mcast_client; /* multicast socket: outgoing */ + + struct sync_mode *mcast_sync; + struct buffer *buffer; + + u_int32_t last_seq_sent; /* last sequence number sent */ + u_int32_t last_seq_recv; /* last sequence number recv */ + u_int64_t packets_replayed; /* number of replayed packets */ + u_int64_t packets_lost; /* lost packets: sequence tracking */ +}; + +#define STATE_STATS(x) state.stats->x + +struct ct_stats_state { + struct cache *cache; /* internal events cache (netlink) */ +}; + +union ct_state { + struct ct_sync_state *sync; + struct ct_stats_state *stats; +}; + +extern struct ct_conf conf; +extern union ct_state state; +extern struct ct_general_state st; + +#ifndef IPPROTO_VRRP +#define IPPROTO_VRRP 112 +#endif + +struct ct_mode { + int (*init)(void); + int (*add_fds_to_set)(fd_set *readfds); + void (*step)(fd_set *readfds); + 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 (*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); +}; + +/* conntrackd modes */ +extern struct ct_mode sync_mode; +extern struct ct_mode stats_mode; + +#define MAX(x, y) x > y ? x : y + +#endif diff --git a/daemon/include/debug.h b/daemon/include/debug.h new file mode 100644 index 0000000..67f2c71 --- /dev/null +++ b/daemon/include/debug.h @@ -0,0 +1,53 @@ +#ifndef _DEBUG_H +#define _DEBUG_H + +#if 0 +#define debug printf +#else +#define debug +#endif + +#include +#include +#include + +static inline void debug_ct(struct nf_conntrack *ct, char *msg) +{ + 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"); +} + +#endif diff --git a/daemon/include/hash.h b/daemon/include/hash.h new file mode 100644 index 0000000..fd971e7 --- /dev/null +++ b/daemon/include/hash.h @@ -0,0 +1,47 @@ +#ifndef _NF_SET_HASH_H_ +#define _NF_SET_HASH_H_ + +#include +#include +#include "slist.h" +#include "linux_list.h" + +struct hashtable; +struct hashtable_node; + +struct hashtable { + u_int32_t hashsize; + u_int32_t limit; + u_int32_t count; + u_int32_t initval; + u_int32_t datasize; + + u_int32_t (*hash)(const void *data, struct hashtable *table); + int (*compare)(const void *data1, const void *data2); + + struct slist_head members[0]; +}; + +struct hashtable_node { + struct slist_head head; + char data[0]; +}; + +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, + u_int32_t (*hash)(const void *data, 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_test(struct hashtable *table, const void *data); +int hashtable_del(struct hashtable *table, void *data); +int hashtable_flush(struct hashtable *table); +int hashtable_iterate(struct hashtable *table, void *data, + int (*iterate)(void *data1, void *data2)); +unsigned int hashtable_counter(struct hashtable *table); + +#endif diff --git a/daemon/include/ignore.h b/daemon/include/ignore.h new file mode 100644 index 0000000..40cb02d --- /dev/null +++ b/daemon/include/ignore.h @@ -0,0 +1,12 @@ +#ifndef _IGNORE_H_ +#define _IGNORE_H_ + +struct ignore_pool { + struct hashtable *h; +}; + +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); + +#endif diff --git a/daemon/include/jhash.h b/daemon/include/jhash.h new file mode 100644 index 0000000..38b8780 --- /dev/null +++ b/daemon/include/jhash.h @@ -0,0 +1,146 @@ +#ifndef _LINUX_JHASH_H +#define _LINUX_JHASH_H + +#define u32 unsigned int +#define u8 char + +/* jhash.h: Jenkins hash support. + * + * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net) + * + * http://burtleburtle.net/bob/hash/ + * + * These are the credits from Bob's sources: + * + * lookup2.c, by Bob Jenkins, December 1996, Public Domain. + * hash(), hash2(), hash3, and mix() are externally useful functions. + * Routines to test the hash are included if SELF_TEST is defined. + * You can use this free for any purpose. It has no warranty. + * + * Copyright (C) 2003 David S. Miller (davem@redhat.com) + * + * I've modified Bob's hash to be useful in the Linux kernel, and + * any bugs present are surely my fault. -DaveM + */ + +/* NOTE: Arguments are modified. */ +#define __jhash_mix(a, b, c) \ +{ \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<<8); \ + c -= a; c -= b; c ^= (b>>13); \ + a -= b; a -= c; a ^= (c>>12); \ + b -= c; b -= a; b ^= (a<<16); \ + c -= a; c -= b; c ^= (b>>5); \ + a -= b; a -= c; a ^= (c>>3); \ + b -= c; b -= a; b ^= (a<<10); \ + c -= a; c -= b; c ^= (b>>15); \ +} + +/* The golden ration: an arbitrary value */ +#define JHASH_GOLDEN_RATIO 0x9e3779b9 + +/* The most generic version, hashes an arbitrary sequence + * of bytes. No alignment or length assumptions are made about + * the input key. + */ +static inline u32 jhash(const void *key, u32 length, u32 initval) +{ + u32 a, b, c, len; + const u8 *k = key; + + len = length; + a = b = JHASH_GOLDEN_RATIO; + c = initval; + + while (len >= 12) { + a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24)); + b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24)); + c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24)); + + __jhash_mix(a,b,c); + + k += 12; + len -= 12; + } + + c += length; + switch (len) { + case 11: c += ((u32)k[10]<<24); + case 10: c += ((u32)k[9]<<16); + case 9 : c += ((u32)k[8]<<8); + case 8 : b += ((u32)k[7]<<24); + case 7 : b += ((u32)k[6]<<16); + case 6 : b += ((u32)k[5]<<8); + case 5 : b += k[4]; + case 4 : a += ((u32)k[3]<<24); + case 3 : a += ((u32)k[2]<<16); + case 2 : a += ((u32)k[1]<<8); + case 1 : a += k[0]; + }; + + __jhash_mix(a,b,c); + + return c; +} + +/* A special optimized version that handles 1 or more of u32s. + * The length parameter here is the number of u32s in the key. + */ +static inline u32 jhash2(u32 *k, u32 length, u32 initval) +{ + u32 a, b, c, len; + + a = b = JHASH_GOLDEN_RATIO; + c = initval; + len = length; + + while (len >= 3) { + a += k[0]; + b += k[1]; + c += k[2]; + __jhash_mix(a, b, c); + k += 3; len -= 3; + } + + c += length * 4; + + switch (len) { + case 2 : b += k[1]; + case 1 : a += k[0]; + }; + + __jhash_mix(a,b,c); + + return c; +} + + +/* A special ultra-optimized versions that knows they are hashing exactly + * 3, 2 or 1 word(s). + * + * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally + * done at the end is not done here. + */ +static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval) +{ + a += JHASH_GOLDEN_RATIO; + b += JHASH_GOLDEN_RATIO; + c += initval; + + __jhash_mix(a, b, c); + + return c; +} + +static inline u32 jhash_2words(u32 a, u32 b, u32 initval) +{ + return jhash_3words(a, b, 0, initval); +} + +static inline u32 jhash_1word(u32 a, u32 initval) +{ + return jhash_3words(a, 0, 0, initval); +} + +#endif /* _LINUX_JHASH_H */ diff --git a/daemon/include/linux_list.h b/daemon/include/linux_list.h new file mode 100644 index 0000000..57b56d7 --- /dev/null +++ b/daemon/include/linux_list.h @@ -0,0 +1,725 @@ +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H + +#undef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +/** + * container_of - cast a member of a structure out to the containing structure + * + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +/* + * Check at compile time that something is of a particular type. + * Always evaluates to 1 so you may use it easily in comparisons. + */ +#define typecheck(type,x) \ +({ type __dummy; \ + typeof(x) __dummy2; \ + (void)(&__dummy == &__dummy2); \ + 1; \ +}) + +#define prefetch(x) 1 + +/* empty define to make this work in userspace -HW */ +#ifndef smp_wmb +#define smp_wmb() +#endif + +/* + * These are non-NULL pointers that will result in page faults + * under normal circumstances, used to verify that nobody uses + * non-initialized list entries. + */ +#define LIST_POISON1 ((void *) 0x00100100) +#define LIST_POISON2 ((void *) 0x00200200) + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add_rcu(struct list_head * new, + struct list_head * prev, struct list_head * next) +{ + new->next = next; + new->prev = prev; + smp_wmb(); + next->prev = new; + prev->next = new; +} + +/** + * list_add_rcu - add a new entry to rcu-protected list + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as list_add_rcu() + * or list_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * list_for_each_entry_rcu(). + */ +static inline void list_add_rcu(struct list_head *new, struct list_head *head) +{ + __list_add_rcu(new, head, head->next); +} + +/** + * list_add_tail_rcu - add a new entry to rcu-protected list + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as list_add_tail_rcu() + * or list_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * list_for_each_entry_rcu(). + */ +static inline void list_add_tail_rcu(struct list_head *new, + struct list_head *head) +{ + __list_add_rcu(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} + +/** + * list_del_rcu - deletes entry from list without re-initialization + * @entry: the element to delete from the list. + * + * Note: list_empty on entry does not return true after this, + * the entry is in an undefined state. It is useful for RCU based + * lockfree traversal. + * + * In particular, it means that we can not poison the forward + * pointers that may still be used for walking the list. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as list_del_rcu() + * or list_add_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * list_for_each_entry_rcu(). + * + * Note that the caller is not permitted to immediately free + * the newly deleted entry. Instead, either synchronize_kernel() + * or call_rcu() must be used to defer freeing until an RCU + * grace period has elapsed. + */ +static inline void list_del_rcu(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->prev = LIST_POISON2; +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_empty_careful - tests whether a list is + * empty _and_ checks that no other CPU might be + * in the process of still modifying either member + * + * NOTE: using list_empty_careful() without synchronization + * can only be safe if the only activity that can happen + * to the list entry is list_del_init(). Eg. it cannot be used + * if another CPU could re-list_add() it. + * + * @head: the list to test. + */ +static inline int list_empty_careful(const struct list_head *head) +{ + struct list_head *next = head->next; + return (next == head) && (next == head->prev); +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, prefetch(pos->next)) + +/** + * __list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This variant differs from list_for_each() in that it's the + * simplest possible list iteration code, no prefetching is done. + * Use this for code that knows the list to be very short (empty + * or 1 entry) most of the time. + */ +#define __list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ + pos = pos->prev, prefetch(pos->prev)) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member), \ + prefetch(pos->member.prev); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member), \ + prefetch(pos->member.prev)) + +/** + * list_prepare_entry - prepare a pos entry for use as a start point in + * list_for_each_entry_continue + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the list_struct within the struct. + */ +#define list_prepare_entry(pos, head, member) \ + ((pos) ? : list_entry(head, typeof(*pos), member)) + +/** + * list_for_each_entry_continue - iterate over list of given type + * continuing after existing point + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_rcu - iterate over an rcu-protected list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_rcu(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next)) + +#define __list_for_each_rcu(pos, head) \ + for (pos = (head)->next; pos != (head); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0;})) + +/** + * list_for_each_safe_rcu - iterate over an rcu-protected list safe + * against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_safe_rcu(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next) + +/** + * list_for_each_entry_rcu - iterate over rcu list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_entry_rcu(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + ({ smp_read_barrier_depends(); 0;}), \ + prefetch(pos->member.next)) + + +/** + * list_for_each_continue_rcu - iterate over an rcu-protected list + * continuing after existing point. + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_continue_rcu(pos, head) \ + for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \ + (pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next)) + +/* + * Double linked lists with a single pointer list head. + * Mostly useful for hash tables where the two pointer list head is + * too wasteful. + * You lose the ability to access the tail in O(1). + */ + +struct hlist_head { + struct hlist_node *first; +}; + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +#define HLIST_HEAD_INIT { .first = NULL } +#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } +#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) +#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL) + +static inline int hlist_unhashed(const struct hlist_node *h) +{ + return !h->pprev; +} + +static inline int hlist_empty(const struct hlist_head *h) +{ + return !h->first; +} + +static inline void __hlist_del(struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + *pprev = next; + if (next) + next->pprev = pprev; +} + +static inline void hlist_del(struct hlist_node *n) +{ + __hlist_del(n); + n->next = LIST_POISON1; + n->pprev = LIST_POISON2; +} + +/** + * hlist_del_rcu - deletes entry from hash list without re-initialization + * @n: the element to delete from the hash list. + * + * Note: list_unhashed() on entry does not return true after this, + * the entry is in an undefined state. It is useful for RCU based + * lockfree traversal. + * + * In particular, it means that we can not poison the forward + * pointers that may still be used for walking the hash list. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as hlist_add_head_rcu() + * or hlist_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * hlist_for_each_entry(). + */ +static inline void hlist_del_rcu(struct hlist_node *n) +{ + __hlist_del(n); + n->pprev = LIST_POISON2; +} + +static inline void hlist_del_init(struct hlist_node *n) +{ + if (n->pprev) { + __hlist_del(n); + INIT_HLIST_NODE(n); + } +} + +#define hlist_del_rcu_init hlist_del_init + +static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + if (first) + first->pprev = &n->next; + h->first = n; + n->pprev = &h->first; +} + + +/** + * hlist_add_head_rcu - adds the specified element to the specified hlist, + * while permitting racing traversals. + * @n: the element to add to the hash list. + * @h: the list to add to. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as hlist_add_head_rcu() + * or hlist_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * hlist_for_each_entry(), but only if smp_read_barrier_depends() + * is used to prevent memory-consistency problems on Alpha CPUs. + * Regardless of the type of CPU, the list-traversal primitive + * must be guarded by rcu_read_lock(). + * + * OK, so why don't we have an hlist_for_each_entry_rcu()??? + */ +static inline void hlist_add_head_rcu(struct hlist_node *n, + struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + n->pprev = &h->first; + smp_wmb(); + if (first) + first->pprev = &n->next; + h->first = n; +} + +/* next must be != NULL */ +static inline void hlist_add_before(struct hlist_node *n, + struct hlist_node *next) +{ + n->pprev = next->pprev; + n->next = next; + next->pprev = &n->next; + *(n->pprev) = n; +} + +static inline void hlist_add_after(struct hlist_node *n, + struct hlist_node *next) +{ + next->next = n->next; + n->next = next; + next->pprev = &n->next; + + if(next->next) + next->next->pprev = &next->next; +} + +#define hlist_entry(ptr, type, member) container_of(ptr,type,member) + +#define hlist_for_each(pos, head) \ + for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \ + pos = pos->next) + +#define hlist_for_each_safe(pos, n, head) \ + for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ + pos = n) + +/** + * hlist_for_each_entry - iterate over list of given type + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry(tpos, pos, head, member) \ + for (pos = (head)->first; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_continue - iterate over a hlist continuing after existing point + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_continue(tpos, pos, member) \ + for (pos = (pos)->next; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_from - iterate over a hlist continuing from existing point + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_from(tpos, pos, member) \ + for (; pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @n: another &struct hlist_node to use as temporary storage + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ + for (pos = (head)->first; \ + pos && ({ n = pos->next; 1; }) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = n) + +/** + * hlist_for_each_entry_rcu - iterate over rcu list of given type + * @pos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as hlist_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define hlist_for_each_entry_rcu(tpos, pos, head, member) \ + for (pos = (head)->first; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0; }) ) + +#endif diff --git a/daemon/include/local.h b/daemon/include/local.h new file mode 100644 index 0000000..350b8bf --- /dev/null +++ b/daemon/include/local.h @@ -0,0 +1,29 @@ +#ifndef _LOCAL_SOCKET_H_ +#define _LOCAL_SOCKET_H_ + +#include + +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX 108 +#endif + +struct local_conf { + int backlog; + int reuseaddr; + char path[UNIX_PATH_MAX]; +}; + +/* local server */ +int local_server_create(struct local_conf *conf); +void local_server_destroy(int fd); +int do_local_server_step(int fd, void *data, + void (*process)(int fd, void *data)); + +/* local client */ +int local_client_create(struct local_conf *conf); +void local_client_destroy(int fd); +int do_local_client_step(int fd, void (*process)(char *buf)); +int do_local_request(int, struct local_conf *,void (*step)(char *buf)); +void local_step(char *buf); + +#endif diff --git a/daemon/include/log.h b/daemon/include/log.h new file mode 100644 index 0000000..9ecff30 --- /dev/null +++ b/daemon/include/log.h @@ -0,0 +1,10 @@ +#ifndef _LOG_H_ +#define _LOG_H_ + +#include + +FILE *init_log(char *filename); +void dlog(FILE *fd, char *format, ...); +void close_log(FILE *fd); + +#endif diff --git a/daemon/include/mcast.h b/daemon/include/mcast.h new file mode 100644 index 0000000..0f3e3cd --- /dev/null +++ b/daemon/include/mcast.h @@ -0,0 +1,48 @@ +#ifndef _MCAST_H_ +#define _MCAST_H_ + +#include + +struct mcast_conf { + int ipproto; + int backlog; + int reuseaddr; + unsigned short port; + union { + struct in_addr inet_addr; + struct in6_addr inet_addr6; + } in; + union { + struct in_addr interface_addr; + struct in6_addr interface_addr6; + } ifa; +}; + +struct mcast_stats { + u_int64_t bytes; + u_int64_t messages; + u_int64_t error; +}; + +struct mcast_sock { + int fd; + union { + struct sockaddr_in ipv4; + struct sockaddr_in6 ipv6; + } addr; + struct mcast_stats stats; +}; + +struct mcast_sock *mcast_server_create(struct mcast_conf *conf); +void mcast_server_destroy(struct mcast_sock *m); + +struct mcast_sock *mcast_client_create(struct mcast_conf *conf); +void mcast_client_destroy(struct mcast_sock *m); + +int mcast_send(struct mcast_sock *m, void *data, int size); +int mcast_recv(struct mcast_sock *m, void *data, int size); + +struct mcast_stats *mcast_get_stats(struct mcast_sock *m); +void mcast_dump_stats(int fd, struct mcast_sock *s, struct mcast_sock *r); + +#endif diff --git a/daemon/include/network.h b/daemon/include/network.h new file mode 100644 index 0000000..dab50db --- /dev/null +++ b/daemon/include/network.h @@ -0,0 +1,34 @@ +#ifndef _NETWORK_H_ +#define _NETWORK_H_ + +#include + +struct nlnetwork { + u_int16_t flags; + u_int16_t checksum; + u_int32_t seq; +}; + +struct nlnetwork_ack { + u_int16_t flags; + u_int16_t checksum; + u_int32_t seq; + u_int32_t from; + u_int32_t to; +}; + +enum { + NET_HELLO_BIT = 0, + NET_HELLO = (1 << NET_HELLO_BIT), + + NET_RESYNC_BIT = 1, + NET_RESYNC = (1 << NET_RESYNC_BIT), + + NET_NACK_BIT = 2, + NET_NACK = (1 << NET_NACK_BIT), + + NET_ACK_BIT = 3, + NET_ACK = (1 << NET_ACK_BIT), +}; + +#endif diff --git a/daemon/include/slist.h b/daemon/include/slist.h new file mode 100644 index 0000000..ab7fa34 --- /dev/null +++ b/daemon/include/slist.h @@ -0,0 +1,41 @@ +#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 && ({ prefetch(pos.next); 1; }); \ + 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/daemon/include/state_helper.h b/daemon/include/state_helper.h new file mode 100644 index 0000000..1ed0b79 --- /dev/null +++ b/daemon/include/state_helper.h @@ -0,0 +1,20 @@ +#ifndef _STATE_HELPER_H_ +#define _STATE_HELPER_H_ + +enum { + ST_H_SKIP, + ST_H_REPLICATE +}; + +struct state_replication_helper { + u_int8_t proto; + unsigned int state; + + int (*verdict)(const struct state_replication_helper *h, + const struct nf_conntrack *ct); +}; + +int state_helper_verdict(int type, struct nf_conntrack *ct); +void state_helper_register(struct state_replication_helper *h, int state); + +#endif diff --git a/daemon/include/sync.h b/daemon/include/sync.h new file mode 100644 index 0000000..7756c87 --- /dev/null +++ b/daemon/include/sync.h @@ -0,0 +1,23 @@ +#ifndef _SYNC_HOOKS_H_ +#define _SYNC_HOOKS_H_ + +struct nlnetwork; +struct us_conntrack; + +struct sync_mode { + int internal_cache_flags; + int external_cache_flags; + struct cache_extra *internal_cache_extra; + struct cache_extra *external_cache_extra; + + int (*init)(void); + void (*kill)(void); + int (*local)(int fd, int type, void *data); + int (*pre_recv)(const struct nlnetwork *net); + void (*post_send)(const struct nlnetwork *net, struct us_conntrack *u); +}; + +extern struct sync_mode notrack; +extern struct sync_mode nack; + +#endif diff --git a/daemon/include/us-conntrack.h b/daemon/include/us-conntrack.h new file mode 100644 index 0000000..3d71e22 --- /dev/null +++ b/daemon/include/us-conntrack.h @@ -0,0 +1,13 @@ +#ifndef _US_CONNTRACK_H_ +#define _US_CONNTRACK_H_ + +#include + +/* be careful, do not modify the layout */ +struct us_conntrack { + struct nf_conntrack *ct; + struct cache *cache; /* add new attributes here */ + char data[0]; +}; + +#endif diff --git a/daemon/src/Makefile.am b/daemon/src/Makefile.am new file mode 100644 index 0000000..5d1c6cb --- /dev/null +++ b/daemon/src/Makefile.am @@ -0,0 +1,22 @@ +include $(top_srcdir)/Make_global.am + +YACC=@YACC@ -d + +CLEANFILES = read_config_yy.c read_config_lex.c + +sbin_PROGRAMS = conntrackd +conntrackd_SOURCES = alarm.c main.c run.c hash.c buffer.c \ + local.c log.c mcast.c netlink.c proxy.c lock.c \ + ignore_pool.c \ + cache.c cache_iterators.c \ + cache_lifetime.c cache_timer.c \ + sync-mode.c sync-notrack.c sync-nack.c \ + traffic_stats.c stats-mode.c \ + network.c checksum.c \ + state_helper.c state_helper_tcp.c \ + read_config_yy.y read_config_lex.l + +conntrackd_LDFLAGS = $(all_libraries) -lnfnetlink -lnetfilter_conntrack \ + -lpthread + +EXTRA_DIST = read_config_yy.h diff --git a/daemon/src/alarm.c b/daemon/src/alarm.c new file mode 100644 index 0000000..1a465c2 --- /dev/null +++ b/daemon/src/alarm.c @@ -0,0 +1,141 @@ +/* + * (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 +#include "linux_list.h" +#include "conntrackd.h" +#include "alarm.h" +#include "jhash.h" +#include +#include +#include + +/* alarm cascade */ +#define ALARM_CASCADE_SIZE 10 +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)); +} + +void destroy_alarm(struct alarm_list *t) +{ + free(t); +} + +void set_alarm_expiration(struct alarm_list *t, unsigned long expires) +{ + t->expires = expires; +} + +void set_alarm_function(struct alarm_list *t, + void (*fcn)(struct alarm_list *a, void *data)) +{ + t->function = fcn; +} + +void set_alarm_data(struct alarm_list *t, void *data) +{ + t->data = data; +} + +void init_alarm(struct alarm_list *t) +{ + INIT_LIST_HEAD(&t->head); + + t->expires = 0; + t->data = 0; + t->function = NULL; +} + +void add_alarm(struct alarm_list *alarm) +{ + unsigned int pos = jhash(alarm, sizeof(alarm), 0) % ALARM_CASCADE_SIZE; + + list_add(&alarm->head, &alarm_cascade[pos]); +} + +void del_alarm(struct alarm_list *alarm) +{ + list_del(&alarm->head); +} + +int mod_alarm(struct alarm_list *alarm, unsigned long expires) +{ + alarm->expires = expires; + return 0; +} + +void __run_alarms() +{ + 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; + + t->expires--; + 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 i; + + alarm_cascade = malloc(sizeof(struct list_head) * ALARM_CASCADE_SIZE); + if (alarm_cascade == NULL) + return -1; + + for (i=0; i + * + * 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" + +struct buffer *buffer_create(size_t max_size) +{ + struct buffer *b; + + b = malloc(sizeof(struct buffer)); + if (b == NULL) + return NULL; + memset(b, 0, sizeof(struct buffer)); + + b->max_size = max_size; + INIT_LIST_HEAD(&b->head); + pthread_mutex_init(&b->lock, NULL); + + return b; +} + +void buffer_destroy(struct buffer *b) +{ + struct list_head *i, *tmp; + struct buffer_node *node; + + pthread_mutex_lock(&b->lock); + 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); +} + +static struct buffer_node *buffer_node_create(const void *data, size_t size) +{ + struct buffer_node *n; + + n = malloc(sizeof(struct buffer_node) + size); + if (n == NULL) + return NULL; + + INIT_LIST_HEAD(&n->head); + n->size = size; + memcpy(n->data, data, size); + + return n; +} + +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; + ret = -1; + goto err; + } + +retry: + /* buffer is full: kill the oldest entry */ + if (b->cur_size + size > b->max_size) { + n = (struct buffer_node *) b->head.prev; + list_del(b->head.prev); + b->cur_size -= n->size; + free(n); + goto retry; + } + + n = buffer_node_create(data, size); + if (n == NULL) { + ret = -1; + goto err; + } + + list_add(&n->head, &b->head); + b->cur_size += size; + +err: + pthread_mutex_unlock(&b->lock); + return ret; +} + +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; + 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)) +{ + 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); +} diff --git a/daemon/src/cache.c b/daemon/src/cache.c new file mode 100644 index 0000000..6f7442b --- /dev/null +++ b/daemon/src/cache.c @@ -0,0 +1,446 @@ +/* + * (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 "jhash.h" +#include "hash.h" +#include "conntrackd.h" +#include +#include +#include "us-conntrack.h" +#include "cache.h" +#include "debug.h" + +static u_int32_t hash(const void *data, 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(u_int32_t), + ((nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16) | + (nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)))); + + b = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV4_DST), sizeof(u_int32_t), + ((nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16) | + (nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)))); + + return jhash_2words(a, b, 0) % table->hashsize; +} + +static u_int32_t hash6(const void *data, 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(u_int32_t), + ((nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16) | + (nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)))); + + b = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV6_DST), sizeof(u_int32_t), + ((nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16) | + (nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)))); + + return jhash_2words(a, b, 0) % table->hashsize; +} + +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) == + 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 compare(const void *data1, const void *data2) +{ + 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) == + 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 void *data1, const void *data2) +{ + 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)); +} + +struct cache_feature *cache_feature[CACHE_MAX_FEATURE] = { + [TIMER_FEATURE] = &timer_feature, + [LIFETIME_FEATURE] = &lifetime_feature, +}; + +struct cache *cache_create(char *name, + unsigned int features, + u_int8_t proto, + struct cache_extra *extra) +{ + size_t size = sizeof(struct us_conntrack); + int i, j = 0; + struct cache *c; + struct cache_feature *feature_array[CACHE_MAX_FEATURE] = {}; + unsigned int feature_offset[CACHE_MAX_FEATURE] = {}; + unsigned int feature_type[CACHE_MAX_FEATURE] = {}; + + c = malloc(sizeof(struct cache)); + if (!c) + return NULL; + memset(c, 0, sizeof(struct cache)); + + strcpy(c->name, name); + + for (i = 0; i < CACHE_MAX_FEATURE; i++) { + if ((1 << i) & features) { + feature_array[j] = cache_feature[i]; + feature_offset[j] = size; + feature_type[i] = j; + size += cache_feature[i]->size; + j++; + } + } + + memcpy(c->feature_type, feature_type, sizeof(feature_type)); + + c->features = malloc(sizeof(struct cache_feature) * j); + if (!c->features) { + free(c); + return NULL; + } + memcpy(c->features, feature_array, sizeof(struct cache_feature) * j); + c->num_features = j; + + c->extra_offset = size; + c->extra = extra; + if (extra) + size += extra->size; + + c->feature_offset = malloc(sizeof(unsigned int) * j); + if (!c->feature_offset) { + free(c->features); + free(c); + return NULL; + } + 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; + } + + if (!c->h) { + free(c->features); + free(c->feature_offset); + free(c); + return NULL; + } + + return c; +} + +void cache_destroy(struct cache *c) +{ + lock(); + hashtable_destroy(c->h); + unlock(); + free(c->features); + free(c->feature_offset); + free(c); +} + +static struct us_conntrack *__add(struct cache *c, struct nf_conntrack *ct) +{ + int i; + size_t size = c->h->datasize; + char buf[size]; + struct us_conntrack *u = (struct us_conntrack *) buf; + struct nf_conntrack *newct; + + memset(u, 0, size); + + u->cache = c; + if ((u->ct = newct = nfct_new()) == NULL) { + errno = ENOMEM; + return 0; + } + memcpy(u->ct, ct, nfct_sizeof(ct)); + + u = hashtable_add(c->h, u); + if (u) { + void *data = u->data; + + for (i = 0; i < c->num_features; i++) { + c->features[i]->add(u, data); + data += c->features[i]->size; + } + + if (c->extra) + c->extra->add(u, ((void *) u) + c->extra_offset); + + return u; + } + free(newct); + + return NULL; +} + +struct us_conntrack *__cache_add(struct cache *c, struct nf_conntrack *ct) +{ + struct us_conntrack *u; + + u = __add(c, ct); + if (u) { + c->add_ok++; + return u; + } + c->add_fail++; + + 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; + char buf[size]; + struct us_conntrack *u = (struct us_conntrack *) buf; + + u->ct = ct; + + u = (struct us_conntrack *) hashtable_test(c->h, u); + if (u) { + int i; + void *data = u->data; + + for (i = 0; i < c->num_features; i++) { + c->features[i]->update(u, data); + data += c->features[i]->size; + } + + if (c->extra) + c->extra->update(u, ((void *) u) + c->extra_offset); + + 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)); + + return u; + } + return NULL; +} + +struct us_conntrack *__cache_update(struct cache *c, struct nf_conntrack *ct) +{ + struct us_conntrack *u; + + u = __update(c, ct); + if (u) { + c->upd_ok++; + return u; + } + c->upd_fail++; + + return NULL; +} + +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; +} + +struct us_conntrack *cache_update_force(struct cache *c, + struct nf_conntrack *ct) +{ + 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; +} + +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; + + lock(); + ret = hashtable_test(c->h, u); + unlock(); + + return ret != NULL; +} + +static int __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; + + u = (struct us_conntrack *) hashtable_test(c->h, u); + if (u) { + int i; + void *data = u->data; + struct nf_conntrack *p = u->ct; + + for (i = 0; i < c->num_features; i++) { + c->features[i]->destroy(u, data); + data += c->features[i]->size; + } + + if (c->extra) + c->extra->destroy(u, ((void *) u) + c->extra_offset); + + hashtable_del(c->h, u); + free(p); + return 1; + } + return 0; +} + +int __cache_del(struct cache *c, struct nf_conntrack *ct) +{ + if (__del(c, ct)) { + c->del_ok++; + return 1; + } + c->del_fail++; + + 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; +} + +void *cache_get_extra(struct cache *c, void *data) +{ + return data + c->extra_offset; +} + +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" + "connections updated:\t\t%12u\tfailed:\t%12u\n" + "connections destroyed:\t\t%12u\tfailed:\t%12u\n\n", + c->name, + hashtable_counter(c->h), + c->add_ok, + c->add_fail, + c->upd_ok, + c->upd_fail, + c->del_ok, + c->del_fail); + unlock(); + send(fd, buf, size, 0); +} diff --git a/daemon/src/cache_iterators.c b/daemon/src/cache_iterators.c new file mode 100644 index 0000000..5d5d22b --- /dev/null +++ b/daemon/src/cache_iterators.c @@ -0,0 +1,229 @@ +/* + * (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 "jhash.h" +#include "hash.h" +#include "conntrackd.h" +#include +#include +#include "us-conntrack.h" +#include "debug.h" + +struct __dump_container { + int fd; + int type; +}; + +static int do_dump(void *data1, void *data2) +{ + char buf[1024]; + int size; + struct __dump_container *container = data1; + struct us_conntrack *u = data2; + void *data = u->data; + int i; + + memset(buf, 0, sizeof(buf)); + size = nfct_snprintf(buf, + sizeof(buf), + u->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; + } + } + 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 + }; + + lock(); + hashtable_iterate(c->h, (void *) &tmp, do_dump); + unlock(); +} + +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; + + 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); + + /* + * Set a reduced timeout for candidate-to-be-committed + * conntracks that live in the external cache + */ + nfct_set_attr_u32(ct, ATTR_TIMEOUT, CONFIG(commit_timeout)); + + ret = nfct_build_query(STATE(subsys_sync), + NFCT_Q_CREATE, + ct, + nlh, + sizeof(buf)); + + free(ct); + + if (ret == -1) { + /* XXX: Please cleanup this debug crap, default in logfile */ + debug("--- failed to build: %s --- \n", strerror(errno)); + return 0; + } + + ret = nfnl_query(STATE(sync), nlh); + if (ret == -1) { + switch(errno) { + case EEXIST: + c->commit_exist++; + break; + default: + 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 */ + return 0; +} + +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; + + lock(); + hashtable_iterate(c->h, c, do_commit); + unlock(); + + /* 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; + + /* log results */ + dlog(STATE(log), "Committed %u new entries", commit_ok); + + if (commit_exist) + dlog(STATE(log), "%u entries ignored, " + "already exist", commit_exist); + if (commit_fail) + dlog(STATE(log), "%u entries can't be " + "committed", commit_fail); +} + +static int do_flush(void *data1, void *data2) +{ + struct cache *c = data1; + struct us_conntrack *u = data2; + void *data = u->data; + int i; + + for (i = 0; i < c->num_features; i++) { + c->features[i]->destroy(u, data); + data += c->features[i]->size; + } + free(u->ct); + + return 0; +} + +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; + char buf[4096]; + struct nlnetwork *net = (struct nlnetwork *) buf; + + ret = build_network_msg(NFCT_Q_UPDATE, + STATE(subsys_sync), + u->ct, + buf, + sizeof(buf)); + if (ret == -1) + debug_ct(u->ct, "failed to build"); + + mcast_send_netmsg(STATE_SYNC(mcast_client), net); + STATE_SYNC(mcast_sync)->post_send(net, 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/daemon/src/cache_lifetime.c b/daemon/src/cache_lifetime.c new file mode 100644 index 0000000..ae54df2 --- /dev/null +++ b/daemon/src/cache_lifetime.c @@ -0,0 +1,65 @@ +/* + * (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 "conntrackd.h" +#include "us-conntrack.h" +#include "cache.h" +#include "alarm.h" + +static void lifetime_add(struct us_conntrack *u, void *data) +{ + long *lifetime = data; + struct timeval tv; + + gettimeofday(&tv, NULL); + + *lifetime = tv.tv_sec; +} + +static void lifetime_update(struct us_conntrack *u, void *data) +{ +} + +static void lifetime_destroy(struct us_conntrack *u, void *data) +{ +} + +static int lifetime_dump(struct us_conntrack *u, + 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/daemon/src/cache_timer.c b/daemon/src/cache_timer.c new file mode 100644 index 0000000..213b59a --- /dev/null +++ b/daemon/src/cache_timer.c @@ -0,0 +1,72 @@ +/* + * (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 "conntrackd.h" +#include "us-conntrack.h" +#include "cache.h" +#include "alarm.h" + +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); +} + +static void timer_add(struct us_conntrack *u, void *data) +{ + struct alarm_list *alarm = data; + + init_alarm(alarm); + set_alarm_expiration(alarm, CONFIG(cache_timeout)); + set_alarm_data(alarm, u); + set_alarm_function(alarm, timeout); + add_alarm(alarm); +} + +static void timer_update(struct us_conntrack *u, void *data) +{ + struct alarm_list *alarm = data; + mod_alarm(alarm, CONFIG(cache_timeout)); +} + +static void timer_destroy(struct us_conntrack *u, void *data) +{ + struct alarm_list *alarm = data; + del_alarm(alarm); +} + +static int timer_dump(struct us_conntrack *u, void *data, char *buf, int type) +{ + struct alarm_list *alarm = data; + + if (type == NFCT_O_XML) + return 0; + + return sprintf(buf, " [expires in %ds]", alarm->expires); +} + +struct cache_feature timer_feature = { + .size = sizeof(struct alarm_list), + .add = timer_add, + .update = timer_update, + .destroy = timer_destroy, + .dump = timer_dump +}; diff --git a/daemon/src/checksum.c b/daemon/src/checksum.c new file mode 100644 index 0000000..41866ff --- /dev/null +++ b/daemon/src/checksum.c @@ -0,0 +1,32 @@ +/* + * Extracted from RFC 1071 with some minor changes to fix compilation on GCC, + * this can probably be improved + * --pablo 11/feb/07 + */ + +#include + +unsigned short do_csum(const void *addr, unsigned int count) +{ + unsigned int sum = 0; + + /* checksumming disabled, just skip */ + if (CONFIG(flags) & DONT_CHECKSUM) + return 0; + + while(count > 1) { + /* This is the inner loop */ + sum += *((unsigned short *) addr++); + count -= 2; + } + + /* Add left-over byte, if any */ + if(count > 0) + sum += *((unsigned char *) addr); + + /* Fold 32-bit sum to 16 bits */ + while (sum>>16) + sum = (sum & 0xffff) + (sum >> 16); + + return ~sum; +} diff --git a/daemon/src/hash.c b/daemon/src/hash.c new file mode 100644 index 0000000..274a140 --- /dev/null +++ b/daemon/src/hash.c @@ -0,0 +1,199 @@ +/* + * (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. + * + * Description: generic hash table implementation + */ + +#include +#include +#include +#include +#include +#include "slist.h" +#include "hash.h" + + +struct hashtable_node *hashtable_alloc_node(int datasize, void *data) +{ + struct hashtable_node *n; + int size = sizeof(struct hashtable_node) + datasize; + + n = malloc(size); + if (!n) + return NULL; + memset(n, 0, size); + 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, + u_int32_t (*hash)(const void *data, struct hashtable *table), + int (*compare)(const void *data1, const void *data2)) +{ + int i; + struct hashtable *h; + struct hashtype *t; + int size = sizeof(struct hashtable) + + hashsize * sizeof(struct slist_head); + + h = (struct hashtable *) malloc(size); + if (!h) { + errno = ENOMEM; + return NULL; + } + + memset(h, 0, size); + for (i=0; imembers[i]); + + h->hashsize = hashsize; + h->limit = limit; + h->datasize = datasize; + h->hash = hash; + h->compare = compare; + + return h; +} + +void hashtable_destroy(struct hashtable *h) +{ + hashtable_flush(h); + free(h); +} + +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) { + 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; +} + +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); + + slist_for_each(e, &table->members[id]) { + n = slist_entry(e, struct hashtable_node, head); + if (table->compare(n->data, data)) + return n->data; + } + + errno = ENOENT; + return NULL; +} + +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); + + 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; + } + } + errno = ENOENT; + return -1; +} + +int hashtable_flush(struct hashtable *table) +{ + int i; + struct slist_head *e, *next, *prev; + 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); + } + + table->count = 0; + + return 0; +} + +int hashtable_iterate(struct hashtable *table, void *data, + int (*iterate)(void *data1, void *data2)) +{ + int i; + struct slist_head *e, *next, *prev; + 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) + return -1; + } + } + return 0; +} + +unsigned int hashtable_counter(struct hashtable *table) +{ + return table->count; +} diff --git a/daemon/src/ignore_pool.c b/daemon/src/ignore_pool.c new file mode 100644 index 0000000..5946617 --- /dev/null +++ b/daemon/src/ignore_pool.c @@ -0,0 +1,136 @@ +/* + * (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 "jhash.h" +#include "hash.h" +#include "conntrackd.h" +#include "ignore.h" +#include "debug.h" +#include + +#define IGNORE_POOL_SIZE 32 +#define IGNORE_POOL_LIMIT 1024 + +static u_int32_t hash(const void *data, struct hashtable *table) +{ + const u_int32_t *ip = data; + + return jhash_1word(*ip, 0) % table->hashsize; +} + +static u_int32_t hash6(const void *data, struct hashtable *table) +{ + return jhash(data, sizeof(u_int32_t)*4, 0) % table->hashsize; +} + +static int compare(const void *data1, const void *data2) +{ + const u_int32_t *ip1 = data1; + const u_int32_t *ip2 = data2; + + return *ip1 == *ip2; +} + +static int compare6(const void *data1, const void *data2) +{ + return memcmp(data1, data2, sizeof(u_int32_t)*4) == 0; +} + +struct ignore_pool *ignore_pool_create(u_int8_t proto) +{ + int i, j = 0; + struct ignore_pool *ip; + + ip = malloc(sizeof(struct ignore_pool)); + if (!ip) + 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(u_int32_t), + hash, + compare); + break; + case AF_INET6: + ip->h = hashtable_create(IGNORE_POOL_SIZE, + IGNORE_POOL_LIMIT, + sizeof(u_int32_t)*4, + hash6, + compare6); + break; + } + + if (!ip->h) { + free(ip); + return NULL; + } + + return ip; +} + +void ignore_pool_destroy(struct ignore_pool *ip) +{ + hashtable_destroy(ip->h); + free(ip); +} + +int ignore_pool_add(struct ignore_pool *ip, void *data) +{ + if (!hashtable_add(ip->h, data)) + return 0; + + return 1; +} + +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)) || + hashtable_test(ip->h, nfct_get_attr(ct, ATTR_REPL_IPV4_SRC)) || + 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) +{ + 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))); +} + +int ignore_pool_test(struct ignore_pool *ip, struct nf_conntrack *ct) +{ + int ret; + + switch(nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO)) { + case AF_INET: + ret = __ignore_pool_test_ipv4(ip, ct); + break; + case AF_INET6: + ret = __ignore_pool_test_ipv6(ip, ct); + break; + default: + dlog(STATE(log), "unknown conntrack layer 3 protocol?"); + break; + } + + return ret; +} diff --git a/daemon/src/local.c b/daemon/src/local.c new file mode 100644 index 0000000..eef70ad --- /dev/null +++ b/daemon/src/local.c @@ -0,0 +1,159 @@ +/* + * (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. + * + * Description: UNIX sockets library + */ + +#include +#include +#include +#include +#include "debug.h" + +#include "local.h" + +int local_server_create(struct local_conf *conf) +{ + int fd; + int len; + struct sockaddr_un local; + + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + debug("local_server_create:socket"); + return -1; + } + + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &conf->reuseaddr, + sizeof(conf->reuseaddr)) == -1) { + debug("local_server_create:setsockopt"); + close(fd); + return -1; + } + + local.sun_family = AF_UNIX; + strcpy(local.sun_path, conf->path); + len = strlen(local.sun_path) + sizeof(local.sun_family); + 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; + } + + return fd; +} + +void local_server_destroy(int fd) +{ + close(fd); +} + +int do_local_server_step(int fd, void *data, + void (*process)(int fd, void *data)) +{ + int rfd; + 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"); + return -1; + } + + process(rfd, data); + close(rfd); + + return 0; +} + +int local_client_create(struct local_conf *conf) +{ + int len; + struct sockaddr_un local; + int fd; + + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) + return -1; + + local.sun_family = AF_UNIX; + strcpy(local.sun_path, conf->path); + len = strlen(local.sun_path) + sizeof(local.sun_family); + + if (connect(fd, (struct sockaddr *) &local, len) == -1) { + close(fd); + debug("local_client_create: connect: "); + return -1; + } + + return fd; +} + +void local_client_destroy(int fd) +{ + close(fd); +} + +int do_local_client_step(int fd, void (*process)(char *buf)) +{ + int numbytes; + char buf[1024]; + + memset(buf, 0, sizeof(buf)); + while ((numbytes = recv(fd, buf, sizeof(buf)-1, 0)) > 0) { + buf[sizeof(buf)-1] = '\0'; + if (process) + process(buf); + memset(buf, 0, sizeof(buf)); + } + + return 0; +} + +void local_step(char *buf) +{ + printf(buf); +} + +int do_local_request(int request, + struct local_conf *conf, + void (*step)(char *buf)) +{ + int fd, ret; + + fd = local_client_create(conf); + if (fd == -1) + return -1; + + ret = send(fd, &request, sizeof(int), 0); + if (ret == -1) { + debug("send:"); + return -1; + } + + do_local_client_step(fd, step); + + local_client_destroy(fd); + + return 0; +} diff --git a/daemon/src/lock.c b/daemon/src/lock.c new file mode 100644 index 0000000..cd68baf --- /dev/null +++ b/daemon/src/lock.c @@ -0,0 +1,32 @@ +/* + * (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/daemon/src/log.c b/daemon/src/log.c new file mode 100644 index 0000000..88cadea --- /dev/null +++ b/daemon/src/log.c @@ -0,0 +1,57 @@ +/* + * (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. + * + * Description: Logging support for the conntrack daemon + */ + +#include +#include +#include +#include + +FILE *init_log(char *filename) +{ + FILE *fd; + + fd = fopen(filename, "a+"); + if (fd == NULL) { + fprintf(stderr, "can't open log file `%s'\n", filename); + return NULL; + } + + 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 close_log(FILE *fd) +{ + fclose(fd); +} diff --git a/daemon/src/main.c b/daemon/src/main.c new file mode 100644 index 0000000..1c75970 --- /dev/null +++ b/daemon/src/main.c @@ -0,0 +1,302 @@ +/* + * (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 "conntrackd.h" +#include "log.h" +#include +#include +#include +#include +#include +#include +#include "hash.h" +#include "jhash.h" + +struct ct_general_state st; +union ct_state state; + +static const char usage_daemon_commands[] = + "Daemon mode commands:\n" + " -d [options]\t\tRun in daemon mode\n" + " -S [options]\t\tRun in statistics mode\n"; + +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, flush kernel conntrack table\n" + " -i, display content of the internal cache\n" + " -e, display the content of the external cache\n" + " -k, kill conntrack daemon\n" + " -s, dump statistics\n" + " -R, resync with kernel conntrack table\n" + " -n, request resync with other node (only NACK mode)\n" + " -x, dump cache in XML format (requires -i or -e)"; + +static const char usage_options[] = + "Options:\n" + " -C [configfile], configuration file path\n"; + +void show_usage(char *progname) +{ + fprintf(stdout, "Connection tracking userspace daemon v%s\n", VERSION); + fprintf(stdout, "Usage: %s [commands] [options]\n\n", progname); + fprintf(stdout, "%s\n", usage_daemon_commands); + fprintf(stdout, "%s\n", usage_client_commands); + fprintf(stdout, "%s\n", usage_options); +} + +/* These live in run.c */ +int init(int); +void run(void); + +void set_operation_mode(int *current, int want, char *argv[]) +{ + if (*current == NOT_SET) { + *current = want; + return; + } + if (*current != want) { + show_usage(argv[0]); + fprintf(stderr, "\nError: Invalid parameters\n"); + exit(EXIT_FAILURE); + } +} + +static int check_capabilities(void) +{ + int ret; + cap_user_header_t hcap; + cap_user_data_t dcap; + + hcap = malloc(sizeof(cap_user_header_t)); + if (!hcap) + return -1; + + hcap->version = _LINUX_CAPABILITY_VERSION; + hcap->pid = getpid(); + + dcap = malloc(sizeof(cap_user_data_t)); + if (!dcap) { + free(hcap); + return -1; + } + + if (capget(hcap, dcap) == -1) { + free(hcap); + free(dcap); + return -1; + } + + ret = dcap->permitted & (1 << CAP_NET_ADMIN); + + free(hcap); + free(dcap); + + return ret; +} + +int main(int argc, char *argv[]) +{ + int ret, i, config_set = 0, action; + char config_file[PATH_MAX]; + int type = 0, mode = 0; + struct utsname u; + int version, major, minor; + + /* Check kernel version: it must be >= 2.6.18 */ + if (uname(&u) == -1) { + fprintf(stderr, "Can't retrieve kernel version via uname()\n"); + exit(EXIT_FAILURE); + } + sscanf(u.release, "%d.%d.%d", &version, &major, &minor); + if (version < 2 && major < 6) { + fprintf(stderr, "Linux kernel version must be >= 2.6.18\n"); + exit(EXIT_FAILURE); + } + + if (major == 6 && minor < 18) { + fprintf(stderr, "Linux kernel version must be >= 2.6.18\n"); + exit(EXIT_FAILURE); + } + + ret = check_capabilities(); + switch (ret) { + case -1: + fprintf(stderr, "Can't get capabilities\n"); + exit(EXIT_FAILURE); + break; + case 0: + fprintf(stderr, "You require CAP_NET_ADMIN in order " + "to run conntrackd\n"); + exit(EXIT_FAILURE); + break; + default: + break; + } + + for (i=1; i= PATH_MAX){ + config_file[PATH_MAX-1]='\0'; + fprintf(stderr, "Path to config file " + "to long. Cutting it " + "down to %d characters", + PATH_MAX); + } + config_set = 1; + break; + } + show_usage(argv[0]); + fprintf(stderr, "Missing config filename\n"); + break; + case 'F': + set_operation_mode(&type, REQUEST, argv); + action = FLUSH_MASTER; + case 'f': + set_operation_mode(&type, REQUEST, argv); + action = FLUSH_CACHE; + break; + case 'R': + set_operation_mode(&type, REQUEST, argv); + action = RESYNC_MASTER; + break; + case 'B': + set_operation_mode(&type, REQUEST, argv); + action = SEND_BULK; + break; + case 'k': + set_operation_mode(&type, REQUEST, argv); + action = KILL; + break; + case 's': + set_operation_mode(&type, REQUEST, argv); + action = STATS; + break; + case 'S': + set_operation_mode(&mode, STATS_MODE, argv); + break; + case 'n': + set_operation_mode(&type, REQUEST, argv); + action = REQUEST_DUMP; + break; + case 'x': + if (action == DUMP_INTERNAL) + action = DUMP_INT_XML; + else if (action == DUMP_EXTERNAL) + action = DUMP_EXT_XML; + else { + show_usage(argv[0]); + fprintf(stderr, "Error: Invalid parameters\n"); + exit(EXIT_FAILURE); + + } + break; + default: + show_usage(argv[0]); + fprintf(stderr, "Unknown option: %s\n", argv[i]); + return 0; + break; + } + } + + if (config_set == 0) + strcpy(config_file, DEFAULT_CONFIGFILE); + + if ((ret = init_config(config_file)) == -1) { + fprintf(stderr, "can't open config file `%s'\n", config_file); + exit(EXIT_FAILURE); + } + + /* + * Setting up logfile + */ + STATE(log) = init_log(CONFIG(logfile)); + if (!STATE(log)) { + fprintf(stdout, "can't open logfile `%s\n'", CONFIG(logfile)); + exit(EXIT_FAILURE); + } + + if (type == REQUEST) { + if (do_local_request(action, &conf.local, local_step) == -1) + fprintf(stderr, "can't connect: is conntrackd " + "running? appropiate permissions?\n"); + exit(EXIT_SUCCESS); + } + + /* + * lock file + */ + if ((ret = open(CONFIG(lockfile), O_CREAT | O_EXCL | O_TRUNC)) == -1) { + fprintf(stderr, "lockfile `%s' exists, perhaps conntrackd " + "already running?\n", CONFIG(lockfile)); + exit(EXIT_FAILURE); + } + close(ret); + + /* Daemonize conntrackd */ + if (type == DAEMON) { + pid_t pid; + + if ((pid = fork()) == -1) { + dlog(STATE(log), "fork() failed: " + "%s", strerror(errno)); + exit(EXIT_FAILURE); + } else if (pid) + exit(EXIT_SUCCESS); + + dlog(STATE(log), "--- starting in daemon mode ---"); + } else + dlog(STATE(log), "--- starting in console mode ---"); + + /* + * initialization process + */ + + if (init(mode) == -1) { + close_log(STATE(log)); + fprintf(stderr, "ERROR: conntrackd cannot start, please " + "check the logfile for more info\n"); + unlink(CONFIG(lockfile)); + exit(EXIT_FAILURE); + } + + /* + * run main process + */ + run(); +} diff --git a/daemon/src/mcast.c b/daemon/src/mcast.c new file mode 100644 index 0000000..9904544 --- /dev/null +++ b/daemon/src/mcast.c @@ -0,0 +1,287 @@ +/* + * (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. + * + * Description: multicast socket library + */ +#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) +{ + int yes = 1; + union { + struct ip_mreq ipv4; + struct ipv6_mreq ipv6; + } mreq; + struct mcast_sock *m; + + m = (struct mcast_sock *) malloc(sizeof(struct mcast_sock)); + if (!m) + return NULL; + memset(m, 0, sizeof(struct mcast_sock)); + + switch(conf->ipproto) { + case AF_INET: + mreq.ipv4.imr_multiaddr.s_addr = conf->in.inet_addr.s_addr; + mreq.ipv4.imr_interface.s_addr =conf->ifa.interface_addr.s_addr; + + 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); + break; + + case AF_INET6: + memcpy(&mreq.ipv6.ipv6mr_multiaddr, &conf->in.inet_addr6, + sizeof(u_int32_t) * 4); + memcpy(&mreq.ipv6.ipv6mr_interface, &conf->ifa.interface_addr6, + sizeof(u_int32_t) * 4); + + m->addr.ipv6.sin6_family = AF_INET6; + m->addr.ipv6.sin6_port = htons(conf->port); + m->addr.ipv6.sin6_addr = in6addr_any; + break; + } + + if ((m->fd = socket(conf->ipproto, SOCK_DGRAM, 0)) == -1) { + debug("mcast_sock_server_create:socket"); + free(m); + return NULL; + } + + 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; + } + + if (bind(m->fd, (struct sockaddr *) &m->addr, + sizeof(struct sockaddr)) == -1) { + debug("mcast_sock_server_create:bind"); + close(m->fd); + free(m); + return NULL; + } + + + switch(conf->ipproto) { + 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; + } + break; + 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; + } + break; + } + + return m; +} + +void mcast_server_destroy(struct mcast_sock *m) +{ + close(m->fd); + free(m); +} + +static int +__mcast_client_create_ipv4(struct mcast_sock *m, struct mcast_conf *conf) +{ + int no = 0; + + m->addr.ipv4.sin_family = AF_INET; + m->addr.ipv4.sin_port = htons(conf->port); + m->addr.ipv4.sin_addr = conf->in.inet_addr; + + if (setsockopt(m->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &no, + sizeof(int)) < 0) { + debug("mcast_sock_client_create:setsockopt2"); + close(m->fd); + return -1; + } + + 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); + free(m); + return -1; + } + + return 0; +} + +static int +__mcast_client_create_ipv6(struct mcast_sock *m, struct mcast_conf *conf) +{ + int no = 0; + + m->addr.ipv6.sin6_family = AF_INET6; + m->addr.ipv6.sin6_port = htons(conf->port); + memcpy(&m->addr.ipv6.sin6_addr, + &conf->in.inet_addr6, + sizeof(struct in6_addr)); + + if (setsockopt(m->fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &no, + sizeof(int)) < 0) { + debug("mcast_sock_client_create:setsockopt2"); + close(m->fd); + return -1; + } + + if (setsockopt(m->fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, + &conf->ifa.interface_addr, + sizeof(struct in_addr)) == -1) { + debug("mcast_sock_client_create:setsockopt3"); + close(m->fd); + free(m); + return -1; + } + + return 0; +} + +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)); + if (!m) + return NULL; + memset(m, 0, sizeof(struct mcast_sock)); + + if ((m->fd = socket(conf->ipproto, SOCK_DGRAM, 0)) == -1) { + debug("mcast_sock_client_create:socket"); + return NULL; + } + + switch(conf->ipproto) { + case AF_INET: + ret = __mcast_client_create_ipv4(m, conf); + break; + case AF_INET6: + ret = __mcast_client_create_ipv6(m, conf); + break; + default: + break; + } + + if (ret == -1) { + free(m); + m = NULL; + } + + return m; +} + +void mcast_client_destroy(struct mcast_sock *m) +{ + close(m->fd); + free(m); +} + +int mcast_send(struct mcast_sock *m, void *data, int size) +{ + int ret; + + ret = sendto(m->fd, + data, + size, + 0, + (struct sockaddr *) &m->addr, + sizeof(struct sockaddr)); + if (ret == -1) { + debug("mcast_sock_send"); + m->stats.error++; + return ret; + } + + m->stats.bytes += ret; + m->stats.messages++; + + return ret; +} + +int mcast_recv(struct mcast_sock *m, void *data, int size) +{ + int ret; + socklen_t sin_size = sizeof(struct sockaddr_in); + + ret = recvfrom(m->fd, + data, + size, + 0, + (struct sockaddr *)&m->addr, + &sin_size); + if (ret == -1) { + debug("mcast_sock_recv"); + m->stats.error++; + return ret; + } + + m->stats.bytes += ret; + m->stats.messages++; + + return ret; +} + +struct mcast_stats *mcast_get_stats(struct mcast_sock *m) +{ + return &m->stats; +} + +void mcast_dump_stats(int fd, struct mcast_sock *s, struct mcast_sock *r) +{ + char buf[512]; + int size; + + size = sprintf(buf, "multicast traffic:\n" + "%20llu Bytes sent " + "%20llu Bytes recv\n" + "%20llu Pckts sent " + "%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); + + send(fd, buf, size, 0); +} diff --git a/daemon/src/netlink.c b/daemon/src/netlink.c new file mode 100644 index 0000000..0bde632 --- /dev/null +++ b/daemon/src/netlink.c @@ -0,0 +1,326 @@ +/* + * (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 "conntrackd.h" +#include +#include +#include +#include "us-conntrack.h" +#include +#include +#include "network.h" + +static int ignore_conntrack(struct nf_conntrack *ct) +{ + /* ignore a certain protocol */ + if (CONFIG(ignore_protocol)[nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)]) + 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)) { + 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)) { + debug_ct(ct, "SNAT"); + return 0; + } + + /* Ignore traffic */ + if (ignore_pool_test(STATE(ignore_pool), ct)) { + debug_ct(ct, "ignore traffic"); + return 1; + } + + return 0; +} + +static int nl_event_handler(struct nlmsghdr *nlh, + struct nfattr *nfa[], + 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. + */ + if (ignore_conntrack(ct)) + return NFCT_CB_STOP; + + switch(type) { + case NFCT_T_NEW: + STATE(mode)->event_new(ct, nlh); + break; + case NFCT_T_UPDATE: + STATE(mode)->event_upd(ct, nlh); + break; + case NFCT_T_DESTROY: + if (STATE(mode)->event_dst(ct, nlh)) + update_traffic_stats(ct); + break; + default: + dlog(STATE(log), "received unknown msg from ctnetlink\n"); + break; + } + + return NFCT_CB_STOP; +} + +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(); + if (!STATE(event)) + return -1; + + /* set up socket buffer size */ + if (CONFIG(netlink_buffer_size)) + nfnl_rcvbufsiz(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, + SO_RCVBUF, &read_size, &socklen); + + CONFIG(netlink_buffer_size) = read_size; + } + + /* ensure that maximum grown size is >= than maximum size */ + if (CONFIG(netlink_buffer_size_max_grown) < CONFIG(netlink_buffer_size)) + 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); + + return 0; +} + +static int nl_dump_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: + STATE(mode)->dump(ct, nlh); + break; + default: + dlog(STATE(log), "received unknown msg from ctnetlink"); + break; + } + return NFCT_CB_CONTINUE; +} + +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(); + 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); + + if (nl_dump_conntrack_table(STATE(dump), STATE(subsys_dump)) == -1) + return -1; + + 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) +{ + unsigned int s = CONFIG(netlink_buffer_size) * 2; + + /* already warned that we have reached the maximum buffer size */ + if (warned) + return; + + if (s > CONFIG(netlink_buffer_size_max_grown)) { + dlog(STATE(log), "maximum netlink socket buffer size reached"); + s = CONFIG(netlink_buffer_size_max_grown); + warned = 1; + } + + CONFIG(netlink_buffer_size) = nfnl_rcvbufsiz(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) +{ + 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_sync), + NFCT_Q_FLUSH, + &CONFIG(family), + &req, + sizeof(req)); + + if (nfnl_query(STATE(sync), &req.nlh) == -1) + return -1; + + return 0; +} diff --git a/daemon/src/network.c b/daemon/src/network.c new file mode 100644 index 0000000..b9be318 --- /dev/null +++ b/daemon/src/network.c @@ -0,0 +1,282 @@ +/* + * (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 "conntrackd.h" +#include "network.h" + +#if 0 +#define _TEST_DROP +#else +#undef _TEST_DROP +#endif + +static int drop = 0; /* debugging purposes */ +static unsigned int seq_set, cur_seq; + +static int send_netmsg(struct mcast_sock *m, void *data, unsigned int len) +{ + struct nlnetwork *net = data; + +#ifdef _TEST_DROP + if (++drop > 10) { + drop = 0; + printf("dropping resend (seq=%u)\n", ntohl(net->seq)); + return 0; + } +#endif + return mcast_send(m, net, 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; + + if (!seq_set) { + seq_set = 1; + cur_seq = time(NULL); + net->flags |= NET_HELLO; + } + + net->flags = htons(net->flags); + net->seq = htonl(cur_seq++); + + if (nlh_host2network(nlh) == -1) + return -1; + + net->checksum = 0; + net->checksum = ntohs(do_csum(data, len)); + + return send_netmsg(m, data, len); +} + +int mcast_resend_netmsg(struct mcast_sock *m, void *data) +{ + struct nlnetwork *net = data; + struct nlmsghdr *nlh = data + sizeof(struct nlnetwork); + unsigned int len = htonl(nlh->nlmsg_len) + sizeof(struct nlnetwork); + + net->flags = ntohs(net->flags); + + if (!seq_set) { + seq_set = 1; + cur_seq = time(NULL); + net->flags |= NET_HELLO; + } + + if (net->flags & NET_NACK || net->flags & NET_ACK) { + struct nlnetwork_ack *nack = (struct nlnetwork_ack *) net; + len = sizeof(struct nlnetwork_ack); + } + + net->flags = htons(net->flags); + net->seq = htonl(cur_seq++); + net->checksum = 0; + net->checksum = ntohs(do_csum(data, len)); + + 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); + + if (!seq_set) { + seq_set = 1; + cur_seq = time(NULL); + net->flags |= NET_HELLO; + } + + if (net->flags & NET_NACK || net->flags & NET_ACK) { + struct nlnetwork_ack *nack = (struct nlnetwork_ack *) net; + nack->from = htonl(nack->from); + nack->to = htonl(nack->to); + len = sizeof(struct nlnetwork_ack); + } + + net->flags = htons(net->flags); + net->seq = htonl(cur_seq++); + net->checksum = 0; + net->checksum = ntohs(do_csum(data, len)); + + return send_netmsg(m, data, len); +} + +static int valid_checksum(void *data, unsigned int len) +{ + struct nlnetwork *net = data; + unsigned short checksum, tmp; + + checksum = ntohs(net->checksum); + + /* no checksum, skip */ + if (!checksum) + return 1; + + net->checksum = 0; + tmp = do_csum(data, len); + + return tmp == checksum; +} + +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 nfgenmsg *nfhdr; + + ret = mcast_recv(m, net, len); + if (ret <= 0) + return ret; + + if (ret < sizeof(struct nlnetwork)) + return -1; + + if (!valid_checksum(data, ret)) + return -1; + + net->flags = ntohs(net->flags); + net->seq = ntohl(net->seq); + + if (net->flags & NET_HELLO) + STATE_SYNC(last_seq_recv) = net->seq-1; + + if (net->flags & NET_NACK || net->flags & NET_ACK) { + struct nlnetwork_ack *nack = (struct nlnetwork_ack *) net; + + if (ret < sizeof(struct nlnetwork_ack)) + return -1; + + nack->from = ntohl(nack->from); + nack->to = ntohl(nack->to); + + return ret; + } + + if (net->flags & NET_RESYNC) + return ret; + + /* 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) + sizeof(struct nlnetwork)) + return -1; + + /* this message does not come from ctnetlink */ + if (NFNL_SUBSYS_ID(ntohs(nlh->nlmsg_type)) != NFNL_SUBSYS_CTNETLINK) + 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; + + if (nlh_network2host(nlh) == -1) + return -1; + + return ret; +} + +int mcast_track_seq(u_int32_t seq, u_int32_t *exp_seq) +{ + static int seq_set = 0; + int ret = 1; + + /* netlink sequence tracking initialization */ + if (!seq_set) { + seq_set = 1; + goto out; + } + + /* fast path: we received the correct sequence */ + if (seq == STATE_SYNC(last_seq_recv)+1) + goto out; + + /* out of sequence: some messages got lost */ + if (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: + *exp_seq = STATE_SYNC(last_seq_recv)+1; + /* update expected sequence */ + STATE_SYNC(last_seq_recv) = seq; + + 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 += sizeof(struct nlnetwork); + 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/daemon/src/proxy.c b/daemon/src/proxy.c new file mode 100644 index 0000000..b9bb04e --- /dev/null +++ b/daemon/src/proxy.c @@ -0,0 +1,124 @@ +/* + * (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/daemon/src/read_config_lex.l b/daemon/src/read_config_lex.l new file mode 100644 index 0000000..dee90c9 --- /dev/null +++ b/daemon/src/read_config_lex.l @@ -0,0 +1,125 @@ +%{ +/* + * (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. + * + * Description: configuration file syntax + */ + +#include "read_config_yy.h" +#include "conntrackd.h" +%} + +%option yylineno +%option nounput + +ws [ \t]+ +comment #.*$ +nl [\n\r] + +is_on [o|O][n|N] +is_off [o|O][f|F][f|F] +integer [0-9]+ +path \/[^\"\n ]* +ip4_end [0-9]*[0-9]+ +ip4_part [0-2]*{ip4_end} +ip4 {ip4_part}\.{ip4_part}\.{ip4_part}\.{ip4_part} +hex_255 [0-9a-fA-F]{1,4} +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-Z]* +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] + +%% +"UNIX" { return T_UNIX; } +"IPv4_address" { return T_IPV4_ADDR; } +"IPv6_address" { return T_IPV6_ADDR; } +"IPv4_interface" { return T_IPV4_IFACE; } +"IPv6_interface" { return T_IPV6_IFACE; } +"Port" { return T_PORT; } +"Multicast" { return T_MULTICAST; } +"HashSize" { return T_HASHSIZE; } +"RefreshTime" { return T_REFRESH; } +"CacheTimeout" { return T_EXPIRE; } +"CommitTimeout" { return T_TIMEOUT; } +"DelayDestroyMessages" { return T_DELAY; } +"HashLimit" { return T_HASHLIMIT; } +"Path" { return T_PATH; } +"IgnoreProtocol" { return T_IGNORE_PROTOCOL; } +"UDP" { return T_UDP; } +"ICMP" { return T_ICMP; } +"VRRP" { return T_VRRP; } +"IGMP" { return T_IGMP; } +"TCP" { return T_TCP; } +"IgnoreTrafficFor" { return T_IGNORE_TRAFFIC; } +"StripNAT" { return T_STRIP_NAT; } +"Backlog" { return T_BACKLOG; } +"Group" { return T_GROUP; } +"LogFile" { return T_LOG; } +"LockFile" { return T_LOCK; } +"General" { return T_GENERAL; } +"Sync" { return T_SYNC; } +"Stats" { return T_STATS; } +"RelaxTransitions" { return T_RELAX_TRANSITIONS; } +"SocketBufferSize" { return T_BUFFER_SIZE; } +"SocketBufferSizeMaxGrown" { return T_BUFFER_SIZE_MAX_GROWN; } +"SocketBufferSizeMaxGrowth" { return T_BUFFER_SIZE_MAX_GROWN; } +"Mode" { return T_SYNC_MODE; } +"ListenTo" { return T_LISTEN_TO; } +"Family" { return T_FAMILY; } +"ResendBufferSize" { return T_RESEND_BUFFER_SIZE; } +"Checksum" { return T_CHECKSUM; } +"ACKWindowSize" { return T_WINDOWSIZE; } +"Replicate" { return T_REPLICATE; } +"for" { return T_FOR; } +"SYN_SENT" { return T_SYN_SENT; } +"SYN_RECV" { return T_SYN_RECV; } +"ESTABLISHED" { return T_ESTABLISHED; } +"FIN_WAIT" { return T_FIN_WAIT; } +"CLOSE_WAIT" { return T_CLOSE_WAIT; } +"LAST_ACK" { return T_LAST_ACK; } +"TIME_WAIT" { return T_TIME_WAIT; } +"CLOSE" { return T_CLOSE; } +"LISTEN" { return T_LISTEN; } + +{is_on} { return T_ON; } +{is_off} { return T_OFF; } +{integer} { yylval.val = atoi(yytext); return T_NUMBER; } +{ip4} { yylval.string = strdup(yytext); return T_IP; } +{ip6} { yylval.string = strdup(yytext); return T_IP; } +{path} { yylval.string = strdup(yytext); return T_PATH_VAL; } +{persistent} { return T_PERSISTENT; } +{nack} { return T_NACK; } +{string} { yylval.string = strdup(yytext); return T_STRING; } + +{comment} ; +{ws} ; +{nl} ; + +<> { yyterminate(); } + +. { return yytext[0]; } + +%% + +int +yywrap() +{ + return 1; +} diff --git a/daemon/src/read_config_yy.y b/daemon/src/read_config_yy.y new file mode 100644 index 0000000..1668919 --- /dev/null +++ b/daemon/src/read_config_yy.y @@ -0,0 +1,550 @@ +%{ +/* + * (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. + * + * Description: configuration file abstract grammar + */ + +#include +#include +#include +#include +#include "conntrackd.h" +#include "ignore.h" + +extern char *yytext; +extern int yylineno; + +struct ct_conf conf; +%} + +%union { + int val; + char *string; +} + +%token T_IPV4_ADDR T_IPV4_IFACE T_PORT T_HASHSIZE T_HASHLIMIT T_MULTICAST +%token T_PATH T_UNIX T_REFRESH T_IPV6_ADDR T_IPV6_IFACE +%token T_IGNORE_UDP T_IGNORE_ICMP T_IGNORE_TRAFFIC T_BACKLOG T_GROUP +%token T_LOG T_UDP T_ICMP T_IGMP T_VRRP T_TCP T_IGNORE_PROTOCOL +%token T_LOCK T_STRIP_NAT T_BUFFER_SIZE_MAX_GROWN T_EXPIRE T_TIMEOUT +%token T_GENERAL T_SYNC T_STATS T_RELAX_TRANSITIONS T_BUFFER_SIZE T_DELAY +%token T_SYNC_MODE T_LISTEN_TO T_FAMILY T_RESEND_BUFFER_SIZE +%token T_PERSISTENT T_NACK T_CHECKSUM T_WINDOWSIZE T_ON T_OFF +%token T_REPLICATE T_FOR +%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_IP T_PATH_VAL +%token T_NUMBER +%token T_STRING + +%% + +configfile : + | lines + ; + +lines : line + | lines line + ; + +line : ignore_protocol + | ignore_traffic + | strip_nat + | general + | sync + | stats + ; + +log : T_LOG T_PATH_VAL +{ + strncpy(conf.logfile, $2, FILENAME_MAXLEN); +}; + +lock : T_LOCK T_PATH_VAL +{ + strncpy(conf.lockfile, $2, FILENAME_MAXLEN); +}; + +strip_nat: T_STRIP_NAT +{ + conf.flags |= STRIP_NAT; +}; + +refreshtime : T_REFRESH T_NUMBER +{ + conf.refresh = $2; +}; + +expiretime: T_EXPIRE T_NUMBER +{ + conf.cache_timeout = $2; +}; + +timeout: T_TIMEOUT T_NUMBER +{ + conf.commit_timeout = $2; +}; + +checksum: T_CHECKSUM T_ON +{ +}; + +checksum: T_CHECKSUM T_OFF +{ + conf.flags |= DONT_CHECKSUM; +}; + +ignore_traffic : T_IGNORE_TRAFFIC '{' ignore_traffic_options '}'; + +ignore_traffic_options : + | ignore_traffic_options ignore_traffic_option; + +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 (!family) { + fprintf(stdout, "%s is not a valid IP, ignoring", $2); + return; + } + + if (!STATE(ignore_pool)) { + STATE(ignore_pool) = ignore_pool_create(family); + if (!STATE(ignore_pool)) { + fprintf(stdout, "Can't create ignore pool!\n"); + exit(EXIT_FAILURE); + } + } + + if (!ignore_pool_add(STATE(ignore_pool), &ip)) { + if (errno == EEXIST) + fprintf(stdout, "IP %s is repeated " + "in the ignore pool\n", $2); + if (errno == ENOSPC) + fprintf(stdout, "Too many IP in the ignore pool!\n"); + } +}; + +multicast_line : T_MULTICAST '{' multicast_options '}'; + +multicast_options : + | multicast_options multicast_option; + +multicast_option : T_IPV4_ADDR T_IP +{ + if (!inet_aton($2, &conf.mcast.in)) { + fprintf(stderr, "%s is not a valid IPv4 address\n"); + return; + } + + if (conf.mcast.ipproto == AF_INET6) { + fprintf(stderr, "Your multicast address is IPv4 but " + "is binded to an IPv6 interface? Surely " + "this is not what you want\n"); + return; + } + + conf.mcast.ipproto = AF_INET; +}; + +multicast_option : T_IPV6_ADDR T_IP +{ +#ifdef HAVE_INET_PTON_IPV6 + if (inet_pton(AF_INET6, $2, &conf.mcast.in) <= 0) + fprintf(stderr, "%s is not a valid IPv6 address\n", $2); +#endif + + if (conf.mcast.ipproto == AF_INET) { + fprintf(stderr, "Your multicast address is IPv6 but " + "is binded to an IPv4 interface? Surely " + "this is not what you want\n"); + return; + } + + conf.mcast.ipproto = AF_INET6; +}; + +multicast_option : T_IPV4_IFACE T_IP +{ + if (!inet_aton($2, &conf.mcast.ifa)) { + fprintf(stderr, "%s is not a valid IPv4 address\n"); + return; + } + + if (conf.mcast.ipproto == AF_INET6) { + fprintf(stderr, "Your multicast interface is IPv4 but " + "is binded to an IPv6 interface? Surely " + "this is not what you want\n"); + return; + } + + conf.mcast.ipproto = AF_INET; +}; + +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"); + return; + } + + conf.mcast.ipproto = AF_INET6; +}; + +multicast_option : T_BACKLOG T_NUMBER +{ + conf.mcast.backlog = $2; +}; + +multicast_option : T_GROUP T_NUMBER +{ + conf.mcast.port = $2; +}; + +hashsize : T_HASHSIZE T_NUMBER +{ + conf.hashsize = $2; +}; + +hashlimit: T_HASHLIMIT T_NUMBER +{ + conf.limit = $2; +}; + +unix_line: T_UNIX '{' unix_options '}'; + +unix_options: + | unix_options unix_option + ; + +unix_option : T_PATH T_PATH_VAL +{ + strcpy(conf.local.path, $2); +}; + +unix_option : T_BACKLOG T_NUMBER +{ + conf.local.backlog = $2; +}; + +ignore_protocol: T_IGNORE_PROTOCOL '{' ignore_proto_list '}'; + +ignore_proto_list: + | ignore_proto_list ignore_proto + ; + +ignore_proto: T_NUMBER +{ + if ($1 < IPPROTO_MAX) + conf.ignore_protocol[$1] = 1; + else + fprintf(stdout, "Protocol number `%d' is freak\n", $1); +}; + +ignore_proto: T_UDP +{ + conf.ignore_protocol[IPPROTO_UDP] = 1; +}; + +ignore_proto: T_ICMP +{ + conf.ignore_protocol[IPPROTO_ICMP] = 1; +}; + +ignore_proto: T_VRRP +{ + conf.ignore_protocol[IPPROTO_VRRP] = 1; +}; + +ignore_proto: T_IGMP +{ + conf.ignore_protocol[IPPROTO_IGMP] = 1; +}; + +sync: T_SYNC '{' sync_list '}'; + +sync_list: + | sync_list sync_line; + +sync_line: refreshtime + | expiretime + | timeout + | checksum + | multicast_line + | relax_transitions + | delay_destroy_msgs + | sync_mode_persistent + | sync_mode_nack + | listen_to + | state_replication + ; + +sync_mode_persistent: T_SYNC_MODE T_PERSISTENT '{' sync_mode_persistent_list '}' +{ + conf.flags |= SYNC_MODE_PERSISTENT; +}; + +sync_mode_nack: T_SYNC_MODE T_NACK '{' sync_mode_nack_list '}' +{ + conf.flags |= SYNC_MODE_NACK; +}; + +sync_mode_persistent_list: + | sync_mode_persistent_list sync_mode_persistent_line; + +sync_mode_persistent_line: refreshtime + | expiretime + | timeout + | relax_transitions + | delay_destroy_msgs + ; + +sync_mode_nack_list: + | sync_mode_nack_list sync_mode_nack_line; + +sync_mode_nack_line: resend_buffer_size + | timeout + | window_size + ; + +resend_buffer_size: T_RESEND_BUFFER_SIZE T_NUMBER +{ + conf.resend_buffer_size = $2; +}; + +window_size: T_WINDOWSIZE T_NUMBER +{ + conf.window_size = $2; +}; + +relax_transitions: T_RELAX_TRANSITIONS +{ + conf.flags |= RELAX_TRANSITIONS; +}; + +delay_destroy_msgs: T_DELAY +{ + conf.flags |= DELAY_DESTROY_MSG; +}; + +listen_to: T_LISTEN_TO T_IP +{ + union inet_address addr; + +#ifdef HAVE_INET_PTON_IPV6 + if (inet_pton(AF_INET6, $2, &addr.ipv6) <= 0) +#endif + if (inet_aton($2, &addr.ipv4) <= 0) { + fprintf(stderr, "%s is not a valid IP address\n", $2); + exit(EXIT_FAILURE); + } + + if (CONFIG(listen_to_len) == 0 || CONFIG(listen_to_len) % 16) { + CONFIG(listen_to) = realloc(CONFIG(listen_to), + sizeof(union inet_address) * + (CONFIG(listen_to_len) + 16)); + if (CONFIG(listen_to) == NULL) { + fprintf(stderr, "cannot init listen_to array\n"); + exit(EXIT_FAILURE); + } + + memset(CONFIG(listen_to) + + (CONFIG(listen_to_len) * sizeof(union inet_address)), + 0, sizeof(union inet_address) * 16); + + } +}; + +state_replication: T_REPLICATE states T_FOR state_proto; + +states: + | states state; + +state_proto: T_TCP; +state: tcp_state; + +tcp_state: T_SYN_SENT +{ + extern struct state_replication_helper tcp_state_helper; + state_helper_register(&tcp_state_helper, TCP_CONNTRACK_SYN_SENT); +}; +tcp_state: T_SYN_RECV +{ + extern struct state_replication_helper tcp_state_helper; + state_helper_register(&tcp_state_helper, TCP_CONNTRACK_SYN_RECV); +}; +tcp_state: T_ESTABLISHED +{ + extern struct state_replication_helper tcp_state_helper; + state_helper_register(&tcp_state_helper, TCP_CONNTRACK_ESTABLISHED); +}; +tcp_state: T_FIN_WAIT +{ + extern struct state_replication_helper tcp_state_helper; + state_helper_register(&tcp_state_helper, TCP_CONNTRACK_FIN_WAIT); +}; +tcp_state: T_CLOSE_WAIT +{ + extern struct state_replication_helper tcp_state_helper; + state_helper_register(&tcp_state_helper, TCP_CONNTRACK_CLOSE_WAIT); +}; +tcp_state: T_LAST_ACK +{ + extern struct state_replication_helper tcp_state_helper; + state_helper_register(&tcp_state_helper, TCP_CONNTRACK_LAST_ACK); +}; +tcp_state: T_TIME_WAIT +{ + extern struct state_replication_helper tcp_state_helper; + state_helper_register(&tcp_state_helper, TCP_CONNTRACK_TIME_WAIT); +}; +tcp_state: T_CLOSE +{ + extern struct state_replication_helper tcp_state_helper; + state_helper_register(&tcp_state_helper, TCP_CONNTRACK_CLOSE); +}; +tcp_state: T_LISTEN +{ + extern struct state_replication_helper tcp_state_helper; + state_helper_register(&tcp_state_helper, TCP_CONNTRACK_LISTEN); +}; + +general: T_GENERAL '{' general_list '}'; + +general_list: + | general_list general_line + ; + +general_line: hashsize + | hashlimit + | log + | lock + | unix_line + | netlink_buffer_size + | netlink_buffer_size_max_grown + | family + ; + +netlink_buffer_size: T_BUFFER_SIZE T_NUMBER +{ + conf.netlink_buffer_size = $2; +}; + +netlink_buffer_size_max_grown : T_BUFFER_SIZE_MAX_GROWN T_NUMBER +{ + conf.netlink_buffer_size_max_grown = $2; +}; + +family : T_FAMILY T_STRING +{ + if (strncmp($2, "IPv6", strlen("IPv6")) == 0) + conf.family = AF_INET6; + else + conf.family = AF_INET; +}; + +stats: T_SYNC '{' stats_list '}'; + +stats_list: + | stats_list stat_line + ; + +stat_line: + | + ; + +%% + +int +yyerror(char *msg) +{ + printf("Error parsing config file: "); + printf("line (%d), symbol '%s': %s\n", yylineno, yytext, msg); + exit(EXIT_FAILURE); +} + +int +init_config(char *filename) +{ + FILE *fp; + + fp = fopen(filename, "r"); + if (!fp) + return -1; + + yyrestart(fp); + yyparse(); + fclose(fp); + + /* default to IPv4 */ + if (CONFIG(family) == 0) + CONFIG(family) = AF_INET; + + /* set to default is not specified */ + if (strcmp(CONFIG(lockfile), "") == 0) + strncpy(CONFIG(lockfile), DEFAULT_LOCKFILE, FILENAME_MAXLEN); + + /* default to 180 seconds of expiration time: cache entries */ + if (CONFIG(cache_timeout) == 0) + CONFIG(cache_timeout) = 180; + + /* default to 180 seconds: committed entries */ + if (CONFIG(commit_timeout) == 0) + CONFIG(commit_timeout) = 180; + + /* default to 60 seconds of refresh time */ + if (CONFIG(refresh) == 0) + CONFIG(refresh) = 60; + + if (CONFIG(resend_buffer_size) == 0) + CONFIG(resend_buffer_size) = 262144; + + /* create empty pool */ + if (!STATE(ignore_pool)) { + STATE(ignore_pool) = ignore_pool_create(CONFIG(family)); + if (!STATE(ignore_pool)) { + fprintf(stdout, "Can't create ignore pool!\n"); + exit(EXIT_FAILURE); + } + } + + /* default to a window size of 20 packets */ + if (CONFIG(window_size) == 0) + CONFIG(window_size) = 20; + + return 0; +} diff --git a/daemon/src/run.c b/daemon/src/run.c new file mode 100644 index 0000000..67437d8 --- /dev/null +++ b/daemon/src/run.c @@ -0,0 +1,227 @@ +/* + * (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. + * + * Description: run and init functions + */ + +#include "conntrackd.h" +#include +#include +#include "us-conntrack.h" +#include +#include + +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_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)); + STATE(mode)->kill(); + unlink(CONFIG(lockfile)); + dlog(STATE(log), "------- shutdown received ----"); + close_log(STATE(log)); + + sigprocmask(SIG_UNBLOCK, &STATE(block), NULL); + + exit(0); +} + +void local_handler(int fd, void *data) +{ + int ret; + int type; + + ret = read(fd, &type, sizeof(type)); + if (ret == -1) { + dlog(STATE(log), "can't read from unix socket\n"); + return; + } + if (ret == 0) { + debug("nothing to process\n"); + return; + } + + switch(type) { + case FLUSH_MASTER: + dlog(STATE(log), "[REQ] flushing master table"); + nl_flush_master_conntrack_table(); + return; + case RESYNC_MASTER: + dlog(STATE(log), "[REQ] resync with master table"); + nl_dump_conntrack_table(STATE(dump), STATE(subsys_dump)); + return; + } + + if (!STATE(mode)->local(fd, type, data)) + dlog(STATE(log), "[FAIL] unknown local request %d", type); +} + +int init(int mode) +{ + switch(mode) { + case STATS_MODE: + STATE(mode) = &stats_mode; + break; + case SYNC_MODE: + STATE(mode) = &sync_mode; + break; + default: + fprintf(stderr, "Unknown running mode! default " + "to synchronization mode\n"); + STATE(mode) = &sync_mode; + break; + } + + /* Initialization */ + if (STATE(mode)->init() == -1) { + dlog(STATE(log), "[FAIL] initialization failed"); + return -1; + } + + /* local UNIX socket */ + STATE(local) = local_server_create(&CONFIG(local)); + if (!STATE(local)) { + dlog(STATE(log), "[FAIL] 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?"); + return -1; + } + + if (nl_init_dump_handler() == -1) { + dlog(STATE(log), "[FAIL] can't open netlink handler! " + "no ctnetlink kernel support?"); + 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); + sigaddset(&STATE(block), SIGINT); + + if (signal(SIGINT, killer) == SIG_ERR) + return -1; + + if (signal(SIGTERM, killer) == SIG_ERR) + return -1; + + /* ignore connection reset by peer */ + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) + return -1; + + dlog(STATE(log), "[OK] initialization completed"); + + return 0; +} + +#define POLL_NSECS 1 + +static void __run(void) +{ + int max, ret; + fd_set readfds; + struct timeval tv = { + .tv_sec = POLL_NSECS, + .tv_usec = 0 + }; + + FD_ZERO(&readfds); + FD_SET(STATE(local), &readfds); + FD_SET(nfnl_fd(STATE(event)), &readfds); + + max = MAX(STATE(local), nfnl_fd(STATE(event))); + + if (STATE(mode)->add_fds_to_set) + max = MAX(max, STATE(mode)->add_fds_to_set(&readfds)); + + ret = select(max+1, &readfds, NULL, NULL, &tv); + if (ret == -1) { + /* interrupted syscall, retry */ + if (errno == EINTR) + return; + + dlog(STATE(log), "select() failed: %s", strerror(errno)); + return; + } + + /* signals are racy */ + sigprocmask(SIG_BLOCK, &STATE(block), NULL); + + /* order received via UNIX socket */ + if (FD_ISSET(STATE(local), &readfds)) + 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 (ret == -1) { + switch(errno) { + case ENOBUFS: + /* + * It seems that ctnetlink can't back off, + * it's likely that we're losing events. + * Solution: duplicate the socket buffer + * size and resync with master conntrack table. + */ + nl_resize_socket_buffer(STATE(event)); + nl_dump_conntrack_table(STATE(sync), + STATE(subsys_sync)); + break; + case ENOENT: + /* + * We received a message from another + * netfilter subsystem that we are not + * interested in. Just ignore it. + */ + break; + default: + dlog(STATE(log), "event catch says: %s", + strerror(errno)); + break; + } + } + } + + if (STATE(mode)->step) + STATE(mode)->step(&readfds); + + sigprocmask(SIG_UNBLOCK, &STATE(block), NULL); +} + +void run(void) +{ + while(1) + __run(); +} diff --git a/daemon/src/state_helper.c b/daemon/src/state_helper.c new file mode 100644 index 0000000..81b0d09 --- /dev/null +++ b/daemon/src/state_helper.c @@ -0,0 +1,44 @@ +/* + * (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 "conntrackd.h" +#include "state_helper.h" + +static struct state_replication_helper *helper[IPPROTO_MAX]; + +int state_helper_verdict(int type, struct nf_conntrack *ct) +{ + u_int8_t l4proto; + + if (type == NFCT_T_DESTROY) + return ST_H_REPLICATE; + + l4proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO); + if (helper[l4proto]) + return helper[l4proto]->verdict(helper[l4proto], ct); + + return ST_H_REPLICATE; +} + +void state_helper_register(struct state_replication_helper *h, int state) +{ + if (helper[h->proto] == NULL) + helper[h->proto] = h; + + helper[h->proto]->state |= (1 << state); +} diff --git a/daemon/src/state_helper_tcp.c b/daemon/src/state_helper_tcp.c new file mode 100644 index 0000000..af714dc --- /dev/null +++ b/daemon/src/state_helper_tcp.c @@ -0,0 +1,35 @@ +/* + * (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 "conntrackd.h" +#include "state_helper.h" + +static int tcp_verdict(const struct state_replication_helper *h, + const struct nf_conntrack *ct) +{ + u_int8_t state = nfct_get_attr_u8(ct, ATTR_TCP_STATE); + if (h->state & (1 << state)) + return ST_H_REPLICATE; + + return ST_H_SKIP; +} + +struct state_replication_helper tcp_state_helper = { + .proto = IPPROTO_TCP, + .verdict = tcp_verdict, +}; diff --git a/daemon/src/stats-mode.c b/daemon/src/stats-mode.c new file mode 100644 index 0000000..9647bbf --- /dev/null +++ b/daemon/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 +}; diff --git a/daemon/src/sync-mode.c b/daemon/src/sync-mode.c new file mode 100644 index 0000000..b32bef7 --- /dev/null +++ b/daemon/src/sync-mode.c @@ -0,0 +1,416 @@ +/* + * (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 +#include "sync.h" +#include "network.h" + +/* handler for multicast messages received */ +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; + struct us_conntrack *u = NULL; + + memset(tmp, 0, sizeof(tmp)); + + ret = mcast_recv_netmsg(m, buf, sizeof(buf)); + if (ret <= 0) { + STATE(malformed)++; + return; + } + + if (STATE_SYNC(mcast_sync)->pre_recv(net)) + return; + + if ((type = parse_network_msg(ct, nlh)) == NFCT_T_ERROR) { + STATE(malformed)++; + return; + } + + 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: +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; + } + debug_ct(ct, "can't add"); + } + break; + case NFCT_T_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: + if (cache_del(STATE_SYNC(external), ct)) + debug_ct(ct, "external destroy"); + else + debug_ct(ct, "can't destroy"); + break; + default: + debug("unknown type %d\n", type); + break; + } +} + +static int init_sync(void) +{ + int ret; + + state.sync = malloc(sizeof(struct ct_sync_state)); + if (!state.sync) { + dlog(STATE(log), "[FAIL] can't allocate memory for state sync"); + return -1; + } + memset(state.sync, 0, sizeof(struct ct_sync_state)); + + if (CONFIG(flags) & SYNC_MODE_NACK) + STATE_SYNC(mcast_sync) = &nack; + else + /* default to persistent mode */ + STATE_SYNC(mcast_sync) = ¬rack; + + if (STATE_SYNC(mcast_sync)->init) + STATE_SYNC(mcast_sync)->init(); + + STATE_SYNC(internal) = + cache_create("internal", + STATE_SYNC(mcast_sync)->internal_cache_flags, + CONFIG(family), + STATE_SYNC(mcast_sync)->internal_cache_extra); + + if (!STATE_SYNC(internal)) { + dlog(STATE(log), "[FAIL] can't allocate memory for " + "the internal cache"); + return -1; + } + + STATE_SYNC(external) = + cache_create("external", + STATE_SYNC(mcast_sync)->external_cache_flags, + CONFIG(family), + NULL); + + if (!STATE_SYNC(external)) { + dlog(STATE(log), "[FAIL] 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!"); + 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!"); + return -1; + } + + /* 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; +} + +static int add_fds_to_set_sync(fd_set *readfds) +{ + FD_SET(STATE_SYNC(mcast_server->fd), readfds); + + return STATE_SYNC(mcast_server->fd); +} + +static void step_sync(fd_set *readfds) +{ + /* multicast packet has been received */ + if (FD_ISSET(STATE_SYNC(mcast_server->fd), readfds)) + mcast_handler(); +} + +static void kill_sync() +{ + cache_destroy(STATE_SYNC(internal)); + cache_destroy(STATE_SYNC(external)); + + mcast_server_destroy(STATE_SYNC(mcast_server)); + mcast_client_destroy(STATE_SYNC(mcast_client)); + + destroy_alarm_thread(); + + if (STATE_SYNC(mcast_sync)->kill) + STATE_SYNC(mcast_sync)->kill(); +} + +static dump_stats_sync(int fd) +{ + char buf[512]; + int size; + + size = sprintf(buf, "multicast sequence tracking:\n" + "%20llu Pckts mfrm " + "%20llu Pckts lost\n\n", + STATE(malformed), + STATE_SYNC(packets_lost)); + + send(fd, buf, size, 0); +} + +/* handler for requests coming via UNIX socket */ +static int local_handler_sync(int fd, int type, void *data) +{ + int ret = 1; + + switch(type) { + case DUMP_INTERNAL: + cache_dump(STATE_SYNC(internal), fd, NFCT_O_PLAIN); + break; + case DUMP_EXTERNAL: + cache_dump(STATE_SYNC(external), fd, NFCT_O_PLAIN); + break; + case DUMP_INT_XML: + cache_dump(STATE_SYNC(internal), fd, NFCT_O_XML); + break; + case DUMP_EXT_XML: + cache_dump(STATE_SYNC(external), fd, NFCT_O_XML); + break; + case COMMIT: + dlog(STATE(log), "[REQ] commit external cache to master table"); + cache_commit(STATE_SYNC(external)); + break; + case FLUSH_CACHE: + dlog(STATE(log), "[REQ] flushing caches"); + cache_flush(STATE_SYNC(internal)); + cache_flush(STATE_SYNC(external)); + break; + case KILL: + killer(); + break; + case STATS: + cache_stats(STATE_SYNC(internal), fd); + cache_stats(STATE_SYNC(external), fd); + dump_traffic_stats(fd); + mcast_dump_stats(fd, STATE_SYNC(mcast_client), + 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(mcast_sync)->local) + ret = STATE_SYNC(mcast_sync)->local(fd, type, data); + break; + } + + return ret; +} + +static void dump_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) +{ + /* 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_update_force(STATE_SYNC(internal), ct)) + debug_ct(ct, "resync"); +} + +static void mcast_send_sync(struct nlmsghdr *nlh, + struct us_conntrack *u, + struct nf_conntrack *ct, + int type) +{ + char buf[4096]; + struct nlnetwork *net = (struct nlnetwork *) buf; + int mangled = 0; + + memset(buf, 0, sizeof(buf)); + + if (!state_helper_verdict(type, ct)) + return; + + if (!mangled) + memcpy(buf + sizeof(struct nlnetwork), nlh, nlh->nlmsg_len); + + mcast_send_netmsg(STATE_SYNC(mcast_client), net); + STATE_SYNC(mcast_sync)->post_send(net, u); +} + +static void overrun_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) +{ + struct us_conntrack *u; + + /* 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_SYNC(internal), ct)) { + if ((u = cache_update_force(STATE_SYNC(internal), ct))) { + debug_ct(ct, "overrun resync"); + mcast_send_sync(nlh, u, ct, NFCT_T_UPDATE); + } + } +} + +static void event_new_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) +{ + struct us_conntrack *u; + + /* 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); + nfct_attr_unset(ct, ATTR_TIMEOUT); +retry: + if ((u = cache_add(STATE_SYNC(internal), ct))) { + mcast_send_sync(nlh, u, ct, NFCT_T_NEW); + debug_ct(u->ct, "internal new"); + } else { + if (errno == EEXIST) { + char buf[4096]; + struct nlmsghdr *nlh = (struct nlmsghdr *) buf; + + 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_NEW); + goto retry; + } + dlog(STATE(log), "can't add to internal cache: " + "%s\n", strerror(errno)); + debug_ct(ct, "can't add"); + } +} + +static void event_update_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) +{ + struct us_conntrack *u; + + nfct_attr_unset(ct, ATTR_TIMEOUT); + + if ((u = cache_update(STATE_SYNC(internal), ct)) == NULL) { + /* + * 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) + && (u = cache_add(STATE_SYNC(internal), ct))) { + debug_ct(u->ct, "forcing internal update"); + } else { + debug_ct(ct, "can't update"); + return; + } + } + debug_ct(u->ct, "internal update"); + mcast_send_sync(nlh, u, ct, NFCT_T_UPDATE); +} + +static int event_destroy_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) +{ + nfct_attr_unset(ct, ATTR_TIMEOUT); + + if (CONFIG(flags) & DELAY_DESTROY_MSG) { + + nfct_set_attr_u32(ct, ATTR_STATUS, IPS_DYING); + + if (cache_update(STATE_SYNC(internal), ct)) { + debug_ct(ct, "delay internal destroy"); + return 1; + } else { + debug_ct(ct, "can't delay destroy!"); + return 0; + } + } else { + if (cache_del(STATE_SYNC(internal), ct)) { + mcast_send_sync(nlh, NULL, ct, NFCT_T_DESTROY); + debug_ct(ct, "internal destroy"); + } else + debug_ct(ct, "can't destroy"); + } +} + +struct ct_mode sync_mode = { + .init = init_sync, + .add_fds_to_set = add_fds_to_set_sync, + .step = step_sync, + .local = local_handler_sync, + .kill = kill_sync, + .dump = dump_sync, + .overrun = overrun_sync, + .event_new = event_new_sync, + .event_upd = event_update_sync, + .event_dst = event_destroy_sync +}; diff --git a/daemon/src/sync-nack.c b/daemon/src/sync-nack.c new file mode 100644 index 0000000..288dba4 --- /dev/null +++ b/daemon/src/sync-nack.c @@ -0,0 +1,309 @@ +/* + * (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 "conntrackd.h" +#include "sync.h" +#include "linux_list.h" +#include "us-conntrack.h" +#include "buffer.h" +#include "debug.h" +#include "network.h" +#include +#include + +#if 0 +#define dp printf +#else +#define dp +#endif + +static LIST_HEAD(queue); + +struct cache_nack { + struct list_head head; + 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); + list_add(&cn->head, &queue); +} + +static void cache_nack_update(struct us_conntrack *u, void *data) +{ + struct cache_nack *cn = data; + + if (cn->head.next != LIST_POISON1 && + cn->head.prev != LIST_POISON2) + list_del(&cn->head); + + INIT_LIST_HEAD(&cn->head); + list_add(&cn->head, &queue); +} + +static void cache_nack_destroy(struct us_conntrack *u, void *data) +{ + struct cache_nack *cn = data; + + if (cn->head.next != LIST_POISON1 && + cn->head.prev != LIST_POISON2) + list_del(&cn->head); +} + +static struct cache_extra cache_nack_extra = { + .size = sizeof(struct cache_nack), + .add = cache_nack_add, + .update = cache_nack_update, + .destroy = cache_nack_destroy +}; + +static int nack_init() +{ + STATE_SYNC(buffer) = buffer_create(CONFIG(resend_buffer_size)); + if (STATE_SYNC(buffer) == NULL) + return -1; + + return 0; +} + +static void nack_kill() +{ + buffer_destroy(STATE_SYNC(buffer)); +} + +static void mcast_send_nack(u_int32_t expt_seq, u_int32_t recv_seq) +{ + struct nlnetwork_ack nack = { + .flags = NET_NACK, + .from = expt_seq, + .to = recv_seq, + }; + + mcast_send_error(STATE_SYNC(mcast_client), &nack); + buffer_add(STATE_SYNC(buffer), &nack, sizeof(struct nlnetwork_ack)); +} + +static void mcast_send_ack(u_int32_t from, u_int32_t to) +{ + struct nlnetwork_ack ack = { + .flags = NET_ACK, + .from = from, + .to = to, + }; + + mcast_send_error(STATE_SYNC(mcast_client), &ack); + buffer_add(STATE_SYNC(buffer), &ack, sizeof(struct nlnetwork_ack)); +} + +static void mcast_send_resync() +{ + struct nlnetwork net = { + .flags = NET_RESYNC, + }; + + mcast_send_error(STATE_SYNC(mcast_client), &net); + buffer_add(STATE_SYNC(buffer), &net, sizeof(struct nlnetwork)); +} + +int nack_local(int fd, int type, void *data) +{ + int ret = 1; + + switch(type) { + case REQUEST_DUMP: + mcast_send_resync(); + dlog(STATE(log), "[REQ] request resync"); + break; + default: + ret = 0; + break; + } + + return ret; +} + +static int buffer_compare(void *data1, void *data2) +{ + struct nlnetwork *net = data1; + struct nlnetwork_ack *nack = data2; + struct nlmsghdr *nlh = data1 + sizeof(struct nlnetwork); + + unsigned old_seq = ntohl(net->seq); + + if (ntohl(net->seq) >= nack->from && ntohl(net->seq) <= 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)); + } + return 0; +} + +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) { + dp("remove from buffer (seq=%u)\n", ntohl(net->seq)); + __buffer_del(STATE_SYNC(buffer), data1); + } + return 0; +} + +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; + + u = cache_get_conntrack(STATE_SYNC(internal), cn); + + if (cn->seq >= from && cn->seq <= 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); + STATE_SYNC(mcast_sync)->post_send(net, u); + dp("(newseq=%u)\n", *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; + + u = cache_get_conntrack(STATE_SYNC(internal), cn); + if (cn->seq >= from && cn->seq <= 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); + } + } + unlock(); +} + +static int nack_pre_recv(const struct nlnetwork *net) +{ + static unsigned int window = 0; + unsigned int exp_seq; + + if (window == 0) + window = CONFIG(window_size); + + if (!mcast_track_seq(net->seq, &exp_seq)) { + dp("OOS: sending nack (seq=%u)\n", exp_seq); + mcast_send_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_ack(net->seq-CONFIG(window_size), net->seq); + } + } + + if (net->flags & NET_NACK) { + struct nlnetwork_ack *nack = (struct nlnetwork_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) { + 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; + + 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); + return 1; + } + + return 0; +} + +static void nack_post_send(const struct nlnetwork *net, struct us_conntrack *u) +{ + unsigned int size = sizeof(struct nlnetwork); + struct nlmsghdr *nlh = (struct nlmsghdr *) ((void *) net + size); + + if (NFNL_MSG_TYPE(ntohs(nlh->nlmsg_type)) == IPCTNL_MSG_CT_DELETE) { + buffer_add(STATE_SYNC(buffer), net, + ntohl(nlh->nlmsg_len) + size); + } else if (u != NULL) { + unsigned int *seq; + struct list_head *n; + struct cache_nack *cn; + + cn = (struct cache_nack *) + cache_get_extra(STATE_SYNC(internal), u); + cn->seq = ntohl(net->seq); + if (cn->head.next != LIST_POISON1 && + cn->head.prev != LIST_POISON2) + list_del(&cn->head); + + INIT_LIST_HEAD(&cn->head); + list_add(&cn->head, &queue); + } +} + +struct sync_mode nack = { + .internal_cache_flags = LIFETIME, + .external_cache_flags = LIFETIME, + .internal_cache_extra = &cache_nack_extra, + .init = nack_init, + .kill = nack_kill, + .local = nack_local, + .pre_recv = nack_pre_recv, + .post_send = nack_post_send, +}; diff --git a/daemon/src/sync-notrack.c b/daemon/src/sync-notrack.c new file mode 100644 index 0000000..2b5ae38 --- /dev/null +++ b/daemon/src/sync-notrack.c @@ -0,0 +1,127 @@ +/* + * (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 "conntrackd.h" +#include "sync.h" +#include "network.h" +#include "us-conntrack.h" +#include "alarm.h" + +static void refresher(struct alarm_list *a, void *data) +{ + struct us_conntrack *u = data; + char buf[8192]; + int size; + + if (nfct_get_attr_u32(u->ct, ATTR_STATUS) & IPS_DYING) { + + debug_ct(u->ct, "persistence destroy"); + + 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); + } +} + +static void cache_notrack_add(struct us_conntrack *u, void *data) +{ + struct alarm_list *alarm = data; + + init_alarm(alarm); + set_alarm_expiration(alarm, (random() % conf.refresh) + 1); + set_alarm_data(alarm, u); + set_alarm_function(alarm, refresher); + add_alarm(alarm); +} + +static void cache_notrack_update(struct us_conntrack *u, void *data) +{ + struct alarm_list *alarm = data; + mod_alarm(alarm, (random() % conf.refresh) + 1); +} + +static void cache_notrack_destroy(struct us_conntrack *u, void *data) +{ + struct alarm_list *alarm = data; + del_alarm(alarm); +} + +static struct cache_extra cache_notrack_extra = { + .size = sizeof(struct alarm_list), + .add = cache_notrack_add, + .update = cache_notrack_update, + .destroy = cache_notrack_destroy +}; + +static int notrack_pre_recv(const struct nlnetwork *net) +{ + unsigned int exp_seq; + + /* + * Ignore error messages: Although this message type is not ever + * 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)) + return 1; + + /* + * Multicast sequence tracking: we keep track of multicast messages + * although we don't do any explicit message recovery. So, why do + * we do sequence tracking? Just to let know the sysadmin. + * + * Let t be 1 < t < RefreshTime. To ensure consistency, conntrackd + * retransmit every t seconds a message with the state of a certain + * entry even if such entry did not change. This mechanism also + * provides passive resynchronization, in other words, there is + * no facility to request a full synchronization from new nodes that + * just joined the cluster, instead they just get resynchronized in + * RefreshTime seconds at worst case. + */ + mcast_track_seq(net->seq, &exp_seq); + + return 0; +} + +static void notrack_post_send(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, +}; diff --git a/daemon/src/traffic_stats.c b/daemon/src/traffic_stats.c new file mode 100644 index 0000000..b510b77 --- /dev/null +++ b/daemon/src/traffic_stats.c @@ -0,0 +1,54 @@ +/* + * (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 "cache.h" +#include "hash.h" +#include "conntrackd.h" +#include +#include +#include +#include "us-conntrack.h" +#include + +void update_traffic_stats(struct nf_conntrack *ct) +{ + STATE(bytes)[NFCT_DIR_ORIGINAL] += + nfct_get_attr_u32(ct, ATTR_ORIG_COUNTER_BYTES); + STATE(bytes)[NFCT_DIR_REPLY] += + nfct_get_attr_u32(ct, ATTR_REPL_COUNTER_BYTES); + STATE(packets)[NFCT_DIR_ORIGINAL] += + nfct_get_attr_u32(ct, ATTR_ORIG_COUNTER_PACKETS); + STATE(packets)[NFCT_DIR_REPLY] += + nfct_get_attr_u32(ct, ATTR_REPL_COUNTER_PACKETS); +} + +void dump_traffic_stats(int fd) +{ + char buf[512]; + int size; + u_int64_t bytes = STATE(bytes)[NFCT_DIR_ORIGINAL] + + STATE(bytes)[NFCT_DIR_REPLY]; + u_int64_t packets = STATE(packets)[NFCT_DIR_ORIGINAL] + + 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); + + send(fd, buf, size, 0); +} diff --git a/extensions/Makefile.am b/extensions/Makefile.am deleted file mode 100644 index 5366ee3..0000000 --- a/extensions/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ -include $(top_srcdir)/Make_global.am - -AM_CFLAGS=-fPIC -Wall -LIBS= - -pkglib_LTLIBRARIES = ct_proto_tcp.la ct_proto_udp.la \ - ct_proto_icmp.la ct_proto_sctp.la - -ct_proto_tcp_la_SOURCES = libct_proto_tcp.c -ct_proto_tcp_la_LDFLAGS = -module -avoid-version -ct_proto_udp_la_SOURCES = libct_proto_udp.c -ct_proto_udp_la_LDFLAGS = -module -avoid-version -ct_proto_icmp_la_SOURCES = libct_proto_icmp.c -ct_proto_icmp_la_LDFLAGS = -module -avoid-version -ct_proto_sctp_la_SOURCES = libct_proto_sctp.c -ct_proto_sctp_la_LDFLAGS = -module -avoid-version diff --git a/extensions/libct_proto_icmp.c b/extensions/libct_proto_icmp.c deleted file mode 100644 index e7cb04d..0000000 --- a/extensions/libct_proto_icmp.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * (C) 2005 by Pablo Neira Ayuso - * Harald Welte - * - * 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 -#include -#include -#include /* For htons */ -#include -#include -#include -#include "conntrack.h" - -static struct option opts[] = { - {"icmp-type", 1, 0, '1'}, - {"icmp-code", 1, 0, '2'}, - {"icmp-id", 1, 0, '3'}, - {0, 0, 0, 0} -}; - -static void help() -{ - fprintf(stdout, "--icmp-type icmp type\n"); - fprintf(stdout, "--icmp-code icmp code\n"); - fprintf(stdout, "--icmp-id icmp id\n"); -} - -/* Add 1; spaces filled with 0. */ -static u_int8_t invmap[] - = { [ICMP_ECHO] = ICMP_ECHOREPLY + 1, - [ICMP_ECHOREPLY] = ICMP_ECHO + 1, - [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1, - [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1, - [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1, - [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1, - [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1, - [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1}; - -static int parse(char c, char *argv[], - struct nfct_tuple *orig, - struct nfct_tuple *reply, - struct nfct_tuple *exptuple, - struct nfct_tuple *mask, - union nfct_protoinfo *proto, - unsigned int *flags) -{ - switch(c) { - case '1': - if (optarg) { - orig->l4dst.icmp.type = atoi(optarg); - reply->l4dst.icmp.type = - invmap[orig->l4dst.icmp.type] - 1; - *flags |= ICMP_TYPE; - } - break; - case '2': - if (optarg) { - orig->l4dst.icmp.code = atoi(optarg); - reply->l4dst.icmp.code = 0; - *flags |= ICMP_CODE; - } - break; - case '3': - if (optarg) { - orig->l4src.icmp.id = htons(atoi(optarg)); - reply->l4dst.icmp.id = 0; - *flags |= ICMP_ID; - } - break; - } - return 1; -} - -static int final_check(unsigned int flags, - unsigned int command, - struct nfct_tuple *orig, - struct nfct_tuple *reply) -{ - if (!(flags & ICMP_TYPE)) - return 0; - else if (!(flags & ICMP_CODE)) - return 0; - - return 1; -} - -static struct ctproto_handler icmp = { - .name = "icmp", - .protonum = IPPROTO_ICMP, - .parse_opts = parse, - .final_check = final_check, - .help = help, - .opts = opts, - .version = VERSION, -}; - -static void __attribute__ ((constructor)) init(void); - -static void init(void) -{ - register_proto(&icmp); -} diff --git a/extensions/libct_proto_icmp.man b/extensions/libct_proto_icmp.man deleted file mode 100644 index 3b860d0..0000000 --- a/extensions/libct_proto_icmp.man +++ /dev/null @@ -1,10 +0,0 @@ -This module matches on ICMP-specific fields. -.TP -.BI "--icmp-type " "TYPE" -ICMP Type. Has to be specified numerically. -.TP -.BI "--icmp-code " "CODE" -ICMP Code. Has to be specified numerically. -.TP -.BI "--icmp-id " "ID" -ICMP Id. Has to be specified numerically. diff --git a/extensions/libct_proto_sctp.c b/extensions/libct_proto_sctp.c deleted file mode 100644 index 1c8f0d1..0000000 --- a/extensions/libct_proto_sctp.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * (C) 2005 by Harald Welte - * 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. - * - */ -#include -#include -#include -#include -#include /* For htons */ -#include "conntrack.h" -#include -#include - -static struct option opts[] = { - {"orig-port-src", 1, 0, '1'}, - {"orig-port-dst", 1, 0, '2'}, - {"reply-port-src", 1, 0, '3'}, - {"reply-port-dst", 1, 0, '4'}, - {"state", 1, 0, '5'}, - {"tuple-port-src", 1, 0, '6'}, - {"tuple-port-dst", 1, 0, '7'}, - {0, 0, 0, 0} -}; - -static const char *states[] = { - "NONE", - "CLOSED", - "COOKIE_WAIT", - "COOKIE_ECHOED", - "ESTABLISHED", - "SHUTDOWN_SENT", - "SHUTDOWN_RECV", - "SHUTDOWN_ACK_SENT", -}; - -static void help() -{ - fprintf(stdout, "--orig-port-src original source port\n"); - fprintf(stdout, "--orig-port-dst original destination port\n"); - fprintf(stdout, "--reply-port-src reply source port\n"); - fprintf(stdout, "--reply-port-dst reply destination port\n"); - fprintf(stdout, "--state SCTP state, fe. ESTABLISHED\n"); - fprintf(stdout, "--tuple-port-src expectation tuple src port\n"); - fprintf(stdout, "--tuple-port-src expectation tuple dst port\n"); -} - -static int parse_options(char c, char *argv[], - struct nfct_tuple *orig, - struct nfct_tuple *reply, - struct nfct_tuple *exptuple, - struct nfct_tuple *mask, - union nfct_protoinfo *proto, - unsigned int *flags) -{ - switch(c) { - case '1': - if (optarg) { - orig->l4src.sctp.port = htons(atoi(optarg)); - *flags |= SCTP_ORIG_SPORT; - } - break; - case '2': - if (optarg) { - orig->l4dst.sctp.port = htons(atoi(optarg)); - *flags |= SCTP_ORIG_DPORT; - } - break; - case '3': - if (optarg) { - reply->l4src.sctp.port = htons(atoi(optarg)); - *flags |= SCTP_REPL_SPORT; - } - break; - case '4': - if (optarg) { - reply->l4dst.sctp.port = htons(atoi(optarg)); - *flags |= SCTP_REPL_DPORT; - } - break; - case '5': - if (optarg) { - int i; - for (i=0; i<10; i++) { - if (strcmp(optarg, states[i]) == 0) { - /* FIXME: Add state to - * nfct_protoinfo - proto->sctp.state = i; */ - break; - } - } - if (i == 10) { - printf("doh?\n"); - return 0; - } - *flags |= SCTP_STATE; - } - break; - case '6': - if (optarg) { - exptuple->l4src.sctp.port = htons(atoi(optarg)); - *flags |= SCTP_EXPTUPLE_SPORT; - } - break; - case '7': - if (optarg) { - exptuple->l4dst.sctp.port = htons(atoi(optarg)); - *flags |= SCTP_EXPTUPLE_DPORT; - } - - } - return 1; -} - -static int final_check(unsigned int flags, - unsigned int command, - struct nfct_tuple *orig, - struct nfct_tuple *reply) -{ - int ret = 0; - - if ((flags & (SCTP_ORIG_SPORT|SCTP_ORIG_DPORT)) - && !(flags & (SCTP_REPL_SPORT|SCTP_REPL_DPORT))) { - reply->l4src.sctp.port = orig->l4dst.sctp.port; - reply->l4dst.sctp.port = orig->l4src.sctp.port; - ret = 1; - } else if (!(flags & (SCTP_ORIG_SPORT|SCTP_ORIG_DPORT)) - && (flags & (SCTP_REPL_SPORT|SCTP_REPL_DPORT))) { - orig->l4src.sctp.port = reply->l4dst.sctp.port; - orig->l4dst.sctp.port = reply->l4src.sctp.port; - ret = 1; - } - if ((flags & (SCTP_ORIG_SPORT|SCTP_ORIG_DPORT)) - && ((flags & (SCTP_REPL_SPORT|SCTP_REPL_DPORT)))) - ret = 1; - - /* --state is missing and we are trying to create a conntrack */ - if (ret && (command & CT_CREATE) && (!(flags & SCTP_STATE))) - ret = 0; - - return ret; -} - -static struct ctproto_handler sctp = { - .name = "sctp", - .protonum = IPPROTO_SCTP, - .parse_opts = parse_options, - .final_check = final_check, - .help = help, - .opts = opts, - .version = VERSION, -}; - -static void __attribute__ ((constructor)) init(void); - -static void init(void) -{ - register_proto(&sctp); -} diff --git a/extensions/libct_proto_tcp.c b/extensions/libct_proto_tcp.c deleted file mode 100644 index ee24206..0000000 --- a/extensions/libct_proto_tcp.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * (C) 2005 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 -#include -#include -#include -#include /* For htons */ -#include -#include - -#include "conntrack.h" - -static struct option opts[] = { - {"orig-port-src", 1, 0, '1'}, - {"orig-port-dst", 1, 0, '2'}, - {"reply-port-src", 1, 0, '3'}, - {"reply-port-dst", 1, 0, '4'}, - {"mask-port-src", 1, 0, '5'}, - {"mask-port-dst", 1, 0, '6'}, - {"state", 1, 0, '7'}, - {"tuple-port-src", 1, 0, '8'}, - {"tuple-port-dst", 1, 0, '9'}, - {0, 0, 0, 0} -}; - -static const char *states[] = { - "NONE", - "SYN_SENT", - "SYN_RECV", - "ESTABLISHED", - "FIN_WAIT", - "CLOSE_WAIT", - "LAST_ACK", - "TIME_WAIT", - "CLOSE", - "LISTEN" -}; - -static void help() -{ - fprintf(stdout, "--orig-port-src original source port\n"); - fprintf(stdout, "--orig-port-dst original destination port\n"); - fprintf(stdout, "--reply-port-src reply source port\n"); - fprintf(stdout, "--reply-port-dst reply destination port\n"); - fprintf(stdout, "--mask-port-src mask source port\n"); - fprintf(stdout, "--mask-port-dst mask destination port\n"); - fprintf(stdout, "--tuple-port-src expectation tuple src port\n"); - fprintf(stdout, "--tuple-port-src expectation tuple dst port\n"); - fprintf(stdout, "--state TCP state, fe. ESTABLISHED\n"); -} - -static int parse_options(char c, char *argv[], - struct nfct_tuple *orig, - struct nfct_tuple *reply, - struct nfct_tuple *exptuple, - struct nfct_tuple *mask, - union nfct_protoinfo *proto, - unsigned int *flags) -{ - switch(c) { - case '1': - if (optarg) { - orig->l4src.tcp.port = htons(atoi(optarg)); - *flags |= TCP_ORIG_SPORT; - } - break; - case '2': - if (optarg) { - orig->l4dst.tcp.port = htons(atoi(optarg)); - *flags |= TCP_ORIG_DPORT; - } - break; - case '3': - if (optarg) { - reply->l4src.tcp.port = htons(atoi(optarg)); - *flags |= TCP_REPL_SPORT; - } - break; - case '4': - if (optarg) { - reply->l4dst.tcp.port = htons(atoi(optarg)); - *flags |= TCP_REPL_DPORT; - } - break; - case '5': - if (optarg) { - mask->l4src.tcp.port = htons(atoi(optarg)); - *flags |= TCP_MASK_SPORT; - } - break; - case '6': - if (optarg) { - mask->l4dst.tcp.port = htons(atoi(optarg)); - *flags |= TCP_MASK_DPORT; - } - break; - case '7': - if (optarg) { - int i; - for (i=0; i<10; i++) { - if (strcmp(optarg, states[i]) == 0) { - proto->tcp.state = i; - break; - } - } - if (i == 10) { - printf("doh?\n"); - return 0; - } - *flags |= TCP_STATE; - } - break; - case '8': - if (optarg) { - exptuple->l4src.tcp.port = htons(atoi(optarg)); - *flags |= TCP_EXPTUPLE_SPORT; - } - break; - case '9': - if (optarg) { - exptuple->l4dst.tcp.port = htons(atoi(optarg)); - *flags |= TCP_EXPTUPLE_DPORT; - } - break; - } - return 1; -} - -static int final_check(unsigned int flags, - unsigned int command, - struct nfct_tuple *orig, - struct nfct_tuple *reply) -{ - int ret = 0; - - if ((flags & (TCP_ORIG_SPORT|TCP_ORIG_DPORT)) - && !(flags & (TCP_REPL_SPORT|TCP_REPL_DPORT))) { - reply->l4src.tcp.port = orig->l4dst.tcp.port; - reply->l4dst.tcp.port = orig->l4src.tcp.port; - ret = 1; - } else if (!(flags & (TCP_ORIG_SPORT|TCP_ORIG_DPORT)) - && (flags & (TCP_REPL_SPORT|TCP_REPL_DPORT))) { - orig->l4src.tcp.port = reply->l4dst.tcp.port; - orig->l4dst.tcp.port = reply->l4src.tcp.port; - ret = 1; - } - if ((flags & (TCP_ORIG_SPORT|TCP_ORIG_DPORT)) - && ((flags & (TCP_REPL_SPORT|TCP_REPL_DPORT)))) - ret = 1; - - /* --state is missing and we are trying to create a conntrack */ - if (ret && (command & CT_CREATE) && (!(flags & TCP_STATE))) - ret = 0; - - return ret; -} - -static struct ctproto_handler tcp = { - .name = "tcp", - .protonum = IPPROTO_TCP, - .parse_opts = parse_options, - .final_check = final_check, - .help = help, - .opts = opts, - .version = VERSION, -}; - -static void __attribute__ ((constructor)) init(void); - -static void init(void) -{ - register_proto(&tcp); -} diff --git a/extensions/libct_proto_tcp.man b/extensions/libct_proto_tcp.man deleted file mode 100644 index 41783f8..0000000 --- a/extensions/libct_proto_tcp.man +++ /dev/null @@ -1,16 +0,0 @@ -This module matches on TCP-specific fields. -.TP -.BI "--orig-port-src " "PORT" -Source port in original direction -.TP -.BI "--orig-port-dst " "PORT" -Destination port in original direction -.TP -.BI "--reply-port-src " "PORT" -Source port in reply direction -.TP -.BI "--reply-port-dst " "PORT" -Destination port in reply direction -.TP -.BI "--state " "[NONE|SYN_SENT|SYN_RECV|ESTABLISHED|FIN_WAIT|CLOSE_WAIT|LAST_ACK|TIME_WAIT|CLOSE|LISTEN]" -TCP state diff --git a/extensions/libct_proto_udp.c b/extensions/libct_proto_udp.c deleted file mode 100644 index 48079e0..0000000 --- a/extensions/libct_proto_udp.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * (C) 2005 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 -#include -#include -#include /* For htons */ -#include "conntrack.h" -#include -#include - -static struct option opts[] = { - {"orig-port-src", 1, 0, '1'}, - {"orig-port-dst", 1, 0, '2'}, - {"reply-port-src", 1, 0, '3'}, - {"reply-port-dst", 1, 0, '4'}, - {"mask-port-src", 1, 0, '5'}, - {"mask-port-dst", 1, 0, '6'}, - {"tuple-port-src", 1, 0, '7'}, - {"tuple-port-dst", 1, 0, '8'}, - {0, 0, 0, 0} -}; - -static void help() -{ - fprintf(stdout, "--orig-port-src original source port\n"); - fprintf(stdout, "--orig-port-dst original destination port\n"); - fprintf(stdout, "--reply-port-src reply source port\n"); - fprintf(stdout, "--reply-port-dst reply destination port\n"); - fprintf(stdout, "--mask-port-src mask source port\n"); - fprintf(stdout, "--mask-port-dst mask destination port\n"); - fprintf(stdout, "--tuple-port-src expectation tuple src port\n"); - fprintf(stdout, "--tuple-port-src expectation tuple dst port\n"); -} - -static int parse_options(char c, char *argv[], - struct nfct_tuple *orig, - struct nfct_tuple *reply, - struct nfct_tuple *exptuple, - struct nfct_tuple *mask, - union nfct_protoinfo *proto, - unsigned int *flags) -{ - switch(c) { - case '1': - if (optarg) { - orig->l4src.udp.port = htons(atoi(optarg)); - *flags |= UDP_ORIG_SPORT; - } - break; - case '2': - if (optarg) { - orig->l4dst.udp.port = htons(atoi(optarg)); - *flags |= UDP_ORIG_DPORT; - } - break; - case '3': - if (optarg) { - reply->l4src.udp.port = htons(atoi(optarg)); - *flags |= UDP_REPL_SPORT; - } - break; - case '4': - if (optarg) { - reply->l4dst.udp.port = htons(atoi(optarg)); - *flags |= UDP_REPL_DPORT; - } - break; - case '5': - if (optarg) { - mask->l4src.udp.port = htons(atoi(optarg)); - *flags |= UDP_MASK_SPORT; - } - break; - case '6': - if (optarg) { - mask->l4dst.udp.port = htons(atoi(optarg)); - *flags |= UDP_MASK_DPORT; - } - break; - case '7': - if (optarg) { - exptuple->l4src.udp.port = htons(atoi(optarg)); - *flags |= UDP_EXPTUPLE_SPORT; - } - break; - case '8': - if (optarg) { - exptuple->l4dst.udp.port = htons(atoi(optarg)); - *flags |= UDP_EXPTUPLE_DPORT; - } - - } - return 1; -} - -static int final_check(unsigned int flags, - unsigned int command, - struct nfct_tuple *orig, - struct nfct_tuple *reply) -{ - if ((flags & (UDP_ORIG_SPORT|UDP_ORIG_DPORT)) - && !(flags & (UDP_REPL_SPORT|UDP_REPL_DPORT))) { - reply->l4src.udp.port = orig->l4dst.udp.port; - reply->l4dst.udp.port = orig->l4src.udp.port; - return 1; - } else if (!(flags & (UDP_ORIG_SPORT|UDP_ORIG_DPORT)) - && (flags & (UDP_REPL_SPORT|UDP_REPL_DPORT))) { - orig->l4src.udp.port = reply->l4dst.udp.port; - orig->l4dst.udp.port = reply->l4src.udp.port; - return 1; - } - if ((flags & (UDP_ORIG_SPORT|UDP_ORIG_DPORT)) - && ((flags & (UDP_REPL_SPORT|UDP_REPL_DPORT)))) - return 1; - - return 0; -} - -static struct ctproto_handler udp = { - .name = "udp", - .protonum = IPPROTO_UDP, - .parse_opts = parse_options, - .final_check = final_check, - .help = help, - .opts = opts, - .version = VERSION, -}; - -static void __attribute__ ((constructor)) init(void); - -static void init(void) -{ - register_proto(&udp); -} diff --git a/extensions/libct_proto_udp.man b/extensions/libct_proto_udp.man deleted file mode 100644 index c67fedf..0000000 --- a/extensions/libct_proto_udp.man +++ /dev/null @@ -1,13 +0,0 @@ -This module matches on UDP-specific fields. -.TP -.BI "--orig-port-src " "PORT" -Source port in original direction -.TP -.BI "--orig-port-dst " "PORT" -Destination port in original direction -.TP -.BI "--reply-port-src " "PORT" -Source port in reply direction -.TP -.BI "--reply-port-dst " "PORT" -Destination port in reply direction diff --git a/include/Makefile.am b/include/Makefile.am deleted file mode 100644 index ef7ce45..0000000 --- a/include/Makefile.am +++ /dev/null @@ -1,2 +0,0 @@ - -noinst_HEADERS = conntrack.h linux_list.h diff --git a/include/conntrack.h b/include/conntrack.h deleted file mode 100644 index fb3b9b6..0000000 --- a/include/conntrack.h +++ /dev/null @@ -1,160 +0,0 @@ -#ifndef _CONNTRACK_H -#define _CONNTRACK_H - -#ifdef HAVE_CONFIG_H -#include "../config.h" -#endif - -#include "linux_list.h" -#include -#include - -#define PROGNAME "conntrack" - -#include -#ifndef IPPROTO_SCTP -#define IPPROTO_SCTP 132 -#endif - -enum action { - CT_NONE = 0, - - CT_LIST_BIT = 0, - CT_LIST = (1 << CT_LIST_BIT), - - CT_CREATE_BIT = 1, - CT_CREATE = (1 << CT_CREATE_BIT), - - CT_UPDATE_BIT = 2, - CT_UPDATE = (1 << CT_UPDATE_BIT), - - CT_DELETE_BIT = 3, - CT_DELETE = (1 << CT_DELETE_BIT), - - CT_GET_BIT = 4, - CT_GET = (1 << CT_GET_BIT), - - CT_FLUSH_BIT = 5, - CT_FLUSH = (1 << CT_FLUSH_BIT), - - CT_EVENT_BIT = 6, - CT_EVENT = (1 << CT_EVENT_BIT), - - CT_VERSION_BIT = 7, - CT_VERSION = (1 << CT_VERSION_BIT), - - CT_HELP_BIT = 8, - CT_HELP = (1 << CT_HELP_BIT), - - EXP_LIST_BIT = 9, - EXP_LIST = (1 << EXP_LIST_BIT), - - EXP_CREATE_BIT = 10, - EXP_CREATE = (1 << EXP_CREATE_BIT), - - EXP_DELETE_BIT = 11, - EXP_DELETE = (1 << EXP_DELETE_BIT), - - EXP_GET_BIT = 12, - EXP_GET = (1 << EXP_GET_BIT), - - EXP_FLUSH_BIT = 13, - EXP_FLUSH = (1 << EXP_FLUSH_BIT), - - EXP_EVENT_BIT = 14, - EXP_EVENT = (1 << EXP_EVENT_BIT), -}; -#define NUMBER_OF_CMD 15 - -enum options { - CT_OPT_ORIG_SRC_BIT = 0, - CT_OPT_ORIG_SRC = (1 << CT_OPT_ORIG_SRC_BIT), - - CT_OPT_ORIG_DST_BIT = 1, - CT_OPT_ORIG_DST = (1 << CT_OPT_ORIG_DST_BIT), - - CT_OPT_ORIG = (CT_OPT_ORIG_SRC | CT_OPT_ORIG_DST), - - CT_OPT_REPL_SRC_BIT = 2, - CT_OPT_REPL_SRC = (1 << CT_OPT_REPL_SRC_BIT), - - CT_OPT_REPL_DST_BIT = 3, - CT_OPT_REPL_DST = (1 << CT_OPT_REPL_DST_BIT), - - CT_OPT_REPL = (CT_OPT_REPL_SRC | CT_OPT_REPL_DST), - - CT_OPT_PROTO_BIT = 4, - CT_OPT_PROTO = (1 << CT_OPT_PROTO_BIT), - - CT_OPT_TIMEOUT_BIT = 5, - CT_OPT_TIMEOUT = (1 << CT_OPT_TIMEOUT_BIT), - - CT_OPT_STATUS_BIT = 6, - CT_OPT_STATUS = (1 << CT_OPT_STATUS_BIT), - - CT_OPT_ZERO_BIT = 7, - CT_OPT_ZERO = (1 << CT_OPT_ZERO_BIT), - - CT_OPT_EVENT_MASK_BIT = 8, - CT_OPT_EVENT_MASK = (1 << CT_OPT_EVENT_MASK_BIT), - - CT_OPT_EXP_SRC_BIT = 9, - CT_OPT_EXP_SRC = (1 << CT_OPT_EXP_SRC_BIT), - - CT_OPT_EXP_DST_BIT = 10, - CT_OPT_EXP_DST = (1 << CT_OPT_EXP_DST_BIT), - - CT_OPT_MASK_SRC_BIT = 11, - CT_OPT_MASK_SRC = (1 << CT_OPT_MASK_SRC_BIT), - - CT_OPT_MASK_DST_BIT = 12, - CT_OPT_MASK_DST = (1 << CT_OPT_MASK_DST_BIT), - - CT_OPT_NATRANGE_BIT = 13, - CT_OPT_NATRANGE = (1 << CT_OPT_NATRANGE_BIT), - - CT_OPT_MARK_BIT = 14, - CT_OPT_MARK = (1 << CT_OPT_MARK_BIT), - - CT_OPT_ID_BIT = 15, - CT_OPT_ID = (1 << CT_OPT_ID_BIT), - - CT_OPT_FAMILY_BIT = 16, - CT_OPT_FAMILY = (1 << CT_OPT_FAMILY_BIT), - - CT_OPT_MAX_BIT = CT_OPT_FAMILY_BIT -}; -#define NUMBER_OF_OPT CT_OPT_MAX_BIT+1 - -struct ctproto_handler { - struct list_head head; - - char *name; - u_int16_t protonum; - char *version; - - enum ctattr_protoinfo protoinfo_attr; - - int (*parse_opts)(char c, char *argv[], - struct nfct_tuple *orig, - struct nfct_tuple *reply, - struct nfct_tuple *exptuple, - struct nfct_tuple *mask, - union nfct_protoinfo *proto, - unsigned int *flags); - - int (*final_check)(unsigned int flags, - unsigned int command, - struct nfct_tuple *orig, - struct nfct_tuple *reply); - - void (*help)(); - - struct option *opts; - - unsigned int option_offset; -}; - -extern void register_proto(struct ctproto_handler *h); - -#endif diff --git a/include/linux_list.h b/include/linux_list.h deleted file mode 100644 index 57b56d7..0000000 --- a/include/linux_list.h +++ /dev/null @@ -1,725 +0,0 @@ -#ifndef _LINUX_LIST_H -#define _LINUX_LIST_H - -#undef offsetof -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) - -/** - * container_of - cast a member of a structure out to the containing structure - * - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -/* - * Check at compile time that something is of a particular type. - * Always evaluates to 1 so you may use it easily in comparisons. - */ -#define typecheck(type,x) \ -({ type __dummy; \ - typeof(x) __dummy2; \ - (void)(&__dummy == &__dummy2); \ - 1; \ -}) - -#define prefetch(x) 1 - -/* empty define to make this work in userspace -HW */ -#ifndef smp_wmb -#define smp_wmb() -#endif - -/* - * These are non-NULL pointers that will result in page faults - * under normal circumstances, used to verify that nobody uses - * non-initialized list entries. - */ -#define LIST_POISON1 ((void *) 0x00100100) -#define LIST_POISON2 ((void *) 0x00200200) - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add_rcu(struct list_head * new, - struct list_head * prev, struct list_head * next) -{ - new->next = next; - new->prev = prev; - smp_wmb(); - next->prev = new; - prev->next = new; -} - -/** - * list_add_rcu - add a new entry to rcu-protected list - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - * - * The caller must take whatever precautions are necessary - * (such as holding appropriate locks) to avoid racing - * with another list-mutation primitive, such as list_add_rcu() - * or list_del_rcu(), running on this same list. - * However, it is perfectly legal to run concurrently with - * the _rcu list-traversal primitives, such as - * list_for_each_entry_rcu(). - */ -static inline void list_add_rcu(struct list_head *new, struct list_head *head) -{ - __list_add_rcu(new, head, head->next); -} - -/** - * list_add_tail_rcu - add a new entry to rcu-protected list - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - * - * The caller must take whatever precautions are necessary - * (such as holding appropriate locks) to avoid racing - * with another list-mutation primitive, such as list_add_tail_rcu() - * or list_del_rcu(), running on this same list. - * However, it is perfectly legal to run concurrently with - * the _rcu list-traversal primitives, such as - * list_for_each_entry_rcu(). - */ -static inline void list_add_tail_rcu(struct list_head *new, - struct list_head *head) -{ - __list_add_rcu(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_del(struct list_head * prev, struct list_head * next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is - * in an undefined state. - */ -static inline void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->next = LIST_POISON1; - entry->prev = LIST_POISON2; -} - -/** - * list_del_rcu - deletes entry from list without re-initialization - * @entry: the element to delete from the list. - * - * Note: list_empty on entry does not return true after this, - * the entry is in an undefined state. It is useful for RCU based - * lockfree traversal. - * - * In particular, it means that we can not poison the forward - * pointers that may still be used for walking the list. - * - * The caller must take whatever precautions are necessary - * (such as holding appropriate locks) to avoid racing - * with another list-mutation primitive, such as list_del_rcu() - * or list_add_rcu(), running on this same list. - * However, it is perfectly legal to run concurrently with - * the _rcu list-traversal primitives, such as - * list_for_each_entry_rcu(). - * - * Note that the caller is not permitted to immediately free - * the newly deleted entry. Instead, either synchronize_kernel() - * or call_rcu() must be used to defer freeing until an RCU - * grace period has elapsed. - */ -static inline void list_del_rcu(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->prev = LIST_POISON2; -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static inline void list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/** - * list_move - delete from one list and add as another's head - * @list: the entry to move - * @head: the head that will precede our entry - */ -static inline void list_move(struct list_head *list, struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add(list, head); -} - -/** - * list_move_tail - delete from one list and add as another's tail - * @list: the entry to move - * @head: the head that will follow our entry - */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add_tail(list, head); -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static inline int list_empty(const struct list_head *head) -{ - return head->next == head; -} - -/** - * list_empty_careful - tests whether a list is - * empty _and_ checks that no other CPU might be - * in the process of still modifying either member - * - * NOTE: using list_empty_careful() without synchronization - * can only be safe if the only activity that can happen - * to the list entry is list_del_init(). Eg. it cannot be used - * if another CPU could re-list_add() it. - * - * @head: the list to test. - */ -static inline int list_empty_careful(const struct list_head *head) -{ - struct list_head *next = head->next; - return (next == head) && (next == head->prev); -} - -static inline void __list_splice(struct list_head *list, - struct list_head *head) -{ - struct list_head *first = list->next; - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static inline void list_splice(struct list_head *list, struct list_head *head) -{ - if (!list_empty(list)) - __list_splice(list, head); -} - -/** - * list_splice_init - join two lists and reinitialise the emptied list. - * @list: the new list to add. - * @head: the place to add it in the first list. - * - * The list at @list is reinitialised - */ -static inline void list_splice_init(struct list_head *list, - struct list_head *head) -{ - if (!list_empty(list)) { - __list_splice(list, head); - INIT_LIST_HEAD(list); - } -} - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - container_of(ptr, type, member) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next, prefetch(pos->next); pos != (head); \ - pos = pos->next, prefetch(pos->next)) - -/** - * __list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - * - * This variant differs from list_for_each() in that it's the - * simplest possible list iteration code, no prefetching is done. - * Use this for code that knows the list to be very short (empty - * or 1 entry) most of the time. - */ -#define __list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -/** - * list_for_each_prev - iterate over a list backwards - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ - pos = pos->prev, prefetch(pos->prev)) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/** - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next)) - -/** - * list_for_each_entry_reverse - iterate backwards over list of given type. - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_reverse(pos, head, member) \ - for (pos = list_entry((head)->prev, typeof(*pos), member), \ - prefetch(pos->member.prev); \ - &pos->member != (head); \ - pos = list_entry(pos->member.prev, typeof(*pos), member), \ - prefetch(pos->member.prev)) - -/** - * list_prepare_entry - prepare a pos entry for use as a start point in - * list_for_each_entry_continue - * @pos: the type * to use as a start point - * @head: the head of the list - * @member: the name of the list_struct within the struct. - */ -#define list_prepare_entry(pos, head, member) \ - ((pos) ? : list_entry(head, typeof(*pos), member)) - -/** - * list_for_each_entry_continue - iterate over list of given type - * continuing after existing point - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_continue(pos, head, member) \ - for (pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next)) - -/** - * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @pos: the type * to use as a loop counter. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/** - * list_for_each_rcu - iterate over an rcu-protected list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - * - * This list-traversal primitive may safely run concurrently with - * the _rcu list-mutation primitives such as list_add_rcu() - * as long as the traversal is guarded by rcu_read_lock(). - */ -#define list_for_each_rcu(pos, head) \ - for (pos = (head)->next, prefetch(pos->next); pos != (head); \ - pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next)) - -#define __list_for_each_rcu(pos, head) \ - for (pos = (head)->next; pos != (head); \ - pos = pos->next, ({ smp_read_barrier_depends(); 0;})) - -/** - * list_for_each_safe_rcu - iterate over an rcu-protected list safe - * against removal of list entry - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - * - * This list-traversal primitive may safely run concurrently with - * the _rcu list-mutation primitives such as list_add_rcu() - * as long as the traversal is guarded by rcu_read_lock(). - */ -#define list_for_each_safe_rcu(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next) - -/** - * list_for_each_entry_rcu - iterate over rcu list of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * This list-traversal primitive may safely run concurrently with - * the _rcu list-mutation primitives such as list_add_rcu() - * as long as the traversal is guarded by rcu_read_lock(). - */ -#define list_for_each_entry_rcu(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member), \ - ({ smp_read_barrier_depends(); 0;}), \ - prefetch(pos->member.next)) - - -/** - * list_for_each_continue_rcu - iterate over an rcu-protected list - * continuing after existing point. - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - * - * This list-traversal primitive may safely run concurrently with - * the _rcu list-mutation primitives such as list_add_rcu() - * as long as the traversal is guarded by rcu_read_lock(). - */ -#define list_for_each_continue_rcu(pos, head) \ - for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \ - (pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next)) - -/* - * Double linked lists with a single pointer list head. - * Mostly useful for hash tables where the two pointer list head is - * too wasteful. - * You lose the ability to access the tail in O(1). - */ - -struct hlist_head { - struct hlist_node *first; -}; - -struct hlist_node { - struct hlist_node *next, **pprev; -}; - -#define HLIST_HEAD_INIT { .first = NULL } -#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } -#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) -#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL) - -static inline int hlist_unhashed(const struct hlist_node *h) -{ - return !h->pprev; -} - -static inline int hlist_empty(const struct hlist_head *h) -{ - return !h->first; -} - -static inline void __hlist_del(struct hlist_node *n) -{ - struct hlist_node *next = n->next; - struct hlist_node **pprev = n->pprev; - *pprev = next; - if (next) - next->pprev = pprev; -} - -static inline void hlist_del(struct hlist_node *n) -{ - __hlist_del(n); - n->next = LIST_POISON1; - n->pprev = LIST_POISON2; -} - -/** - * hlist_del_rcu - deletes entry from hash list without re-initialization - * @n: the element to delete from the hash list. - * - * Note: list_unhashed() on entry does not return true after this, - * the entry is in an undefined state. It is useful for RCU based - * lockfree traversal. - * - * In particular, it means that we can not poison the forward - * pointers that may still be used for walking the hash list. - * - * The caller must take whatever precautions are necessary - * (such as holding appropriate locks) to avoid racing - * with another list-mutation primitive, such as hlist_add_head_rcu() - * or hlist_del_rcu(), running on this same list. - * However, it is perfectly legal to run concurrently with - * the _rcu list-traversal primitives, such as - * hlist_for_each_entry(). - */ -static inline void hlist_del_rcu(struct hlist_node *n) -{ - __hlist_del(n); - n->pprev = LIST_POISON2; -} - -static inline void hlist_del_init(struct hlist_node *n) -{ - if (n->pprev) { - __hlist_del(n); - INIT_HLIST_NODE(n); - } -} - -#define hlist_del_rcu_init hlist_del_init - -static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) -{ - struct hlist_node *first = h->first; - n->next = first; - if (first) - first->pprev = &n->next; - h->first = n; - n->pprev = &h->first; -} - - -/** - * hlist_add_head_rcu - adds the specified element to the specified hlist, - * while permitting racing traversals. - * @n: the element to add to the hash list. - * @h: the list to add to. - * - * The caller must take whatever precautions are necessary - * (such as holding appropriate locks) to avoid racing - * with another list-mutation primitive, such as hlist_add_head_rcu() - * or hlist_del_rcu(), running on this same list. - * However, it is perfectly legal to run concurrently with - * the _rcu list-traversal primitives, such as - * hlist_for_each_entry(), but only if smp_read_barrier_depends() - * is used to prevent memory-consistency problems on Alpha CPUs. - * Regardless of the type of CPU, the list-traversal primitive - * must be guarded by rcu_read_lock(). - * - * OK, so why don't we have an hlist_for_each_entry_rcu()??? - */ -static inline void hlist_add_head_rcu(struct hlist_node *n, - struct hlist_head *h) -{ - struct hlist_node *first = h->first; - n->next = first; - n->pprev = &h->first; - smp_wmb(); - if (first) - first->pprev = &n->next; - h->first = n; -} - -/* next must be != NULL */ -static inline void hlist_add_before(struct hlist_node *n, - struct hlist_node *next) -{ - n->pprev = next->pprev; - n->next = next; - next->pprev = &n->next; - *(n->pprev) = n; -} - -static inline void hlist_add_after(struct hlist_node *n, - struct hlist_node *next) -{ - next->next = n->next; - n->next = next; - next->pprev = &n->next; - - if(next->next) - next->next->pprev = &next->next; -} - -#define hlist_entry(ptr, type, member) container_of(ptr,type,member) - -#define hlist_for_each(pos, head) \ - for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \ - pos = pos->next) - -#define hlist_for_each_safe(pos, n, head) \ - for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ - pos = n) - -/** - * hlist_for_each_entry - iterate over list of given type - * @tpos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @head: the head for your list. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry(tpos, pos, head, member) \ - for (pos = (head)->first; \ - pos && ({ prefetch(pos->next); 1;}) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_continue - iterate over a hlist continuing after existing point - * @tpos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_continue(tpos, pos, member) \ - for (pos = (pos)->next; \ - pos && ({ prefetch(pos->next); 1;}) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_from - iterate over a hlist continuing from existing point - * @tpos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_from(tpos, pos, member) \ - for (; pos && ({ prefetch(pos->next); 1;}) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @tpos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @n: another &struct hlist_node to use as temporary storage - * @head: the head for your list. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ - for (pos = (head)->first; \ - pos && ({ n = pos->next; 1; }) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = n) - -/** - * hlist_for_each_entry_rcu - iterate over rcu list of given type - * @pos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @head: the head for your list. - * @member: the name of the hlist_node within the struct. - * - * This list-traversal primitive may safely run concurrently with - * the _rcu list-mutation primitives such as hlist_add_rcu() - * as long as the traversal is guarded by rcu_read_lock(). - */ -#define hlist_for_each_entry_rcu(tpos, pos, head, member) \ - for (pos = (head)->first; \ - pos && ({ prefetch(pos->next); 1;}) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next, ({ smp_read_barrier_depends(); 0; }) ) - -#endif diff --git a/src/Makefile.am b/src/Makefile.am deleted file mode 100644 index 83cad99..0000000 --- a/src/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -include $(top_srcdir)/Make_global.am -LIBS = @CONNTRACK_LIBS@ - -sbin_PROGRAMS = conntrack -conntrack_SOURCES = conntrack.c -conntrack_LDFLAGS = -rdynamic - diff --git a/src/conntrack.c b/src/conntrack.c deleted file mode 100644 index 30fbf69..0000000 --- a/src/conntrack.c +++ /dev/null @@ -1,1131 +0,0 @@ -/* - * (C) 2005 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. - * - * Note: - * Yes, portions of this code has been stolen from iptables ;) - * Special thanks to the the Netfilter Core Team. - * Thanks to Javier de Miguel Rodriguez - * for introducing me to advanced firewalling stuff. - * - * --pablo 13/04/2005 - * - * 2005-04-16 Harald Welte : - * Add support for conntrack accounting and conntrack mark - * 2005-06-23 Harald Welte : - * Add support for expect creation - * 2005-09-24 Harald Welte : - * Remove remaints of "-A" - * - */ -#include -#include -#include -#include -#include -#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'}; - -static const char cmd_need_param[NUMBER_OF_CMD] -= { 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2 }; - -static const char optflags[NUMBER_OF_OPT] -= {'s','d','r','q','p','t','u','z','e','[',']','{','}','a','m','i','f'}; - -static struct option original_opts[] = { - {"dump", 2, 0, 'L'}, - {"create", 1, 0, 'I'}, - {"delete", 1, 0, 'D'}, - {"update", 1, 0, 'U'}, - {"get", 1, 0, 'G'}, - {"flush", 1, 0, 'F'}, - {"event", 1, 0, 'E'}, - {"version", 0, 0, 'V'}, - {"help", 0, 0, 'h'}, - {"orig-src", 1, 0, 's'}, - {"orig-dst", 1, 0, 'd'}, - {"reply-src", 1, 0, 'r'}, - {"reply-dst", 1, 0, 'q'}, - {"protonum", 1, 0, 'p'}, - {"timeout", 1, 0, 't'}, - {"status", 1, 0, 'u'}, - {"zero", 0, 0, 'z'}, - {"event-mask", 1, 0, 'e'}, - {"tuple-src", 1, 0, '['}, - {"tuple-dst", 1, 0, ']'}, - {"mask-src", 1, 0, '{'}, - {"mask-dst", 1, 0, '}'}, - {"nat-range", 1, 0, 'a'}, - {"mark", 1, 0, 'm'}, - {"id", 2, 0, 'i'}, - {"family", 1, 0, 'f'}, - {0, 0, 0, 0} -}; - -#define OPTION_OFFSET 256 - -static struct nfct_handle *cth; -static struct option *opts = original_opts; -static unsigned int global_option_offset = 0; - -/* Table of legal combinations of commands and options. If any of the - * given commands make an option legal, that option is legal (applies to - * CMD_LIST and CMD_ZERO only). - * Key: - * 0 illegal - * 1 compulsory - * 2 optional - */ - -static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = -/* Well, it's better than "Re: Linux vs FreeBSD" */ -{ - /* s d r q p t u z e x y k l a m i f*/ -/*CT_LIST*/ {2,2,2,2,2,0,0,2,0,0,0,0,0,0,2,2,2}, -/*CT_CREATE*/ {2,2,2,2,1,1,1,0,0,0,0,0,0,2,2,0,0}, -/*CT_UPDATE*/ {2,2,2,2,1,2,2,0,0,0,0,0,0,0,2,2,0}, -/*CT_DELETE*/ {2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,0}, -/*CT_GET*/ {2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,2,0}, -/*CT_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*CT_EVENT*/ {2,2,2,2,2,0,0,0,2,0,0,0,0,0,2,0,0}, -/*VERSION*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*HELP*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_LIST*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2}, -/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0}, -/*EXP_DELETE*/{1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_GET*/ {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -}; - -static char *lib_dir = CONNTRACK_LIB_DIR; - -static LIST_HEAD(proto_list); - -void register_proto(struct ctproto_handler *h) -{ - if (strcmp(h->version, VERSION) != 0) { - fprintf(stderr, "plugin `%s': version %s (I'm %s)\n", - h->name, h->version, VERSION); - exit(1); - } - list_add(&h->head, &proto_list); -} - -static struct ctproto_handler *findproto(char *name) -{ - struct list_head *i; - struct ctproto_handler *cur = NULL, *handler = NULL; - - if (!name) - return handler; - - lib_dir = getenv("CONNTRACK_LIB_DIR"); - if (!lib_dir) - lib_dir = CONNTRACK_LIB_DIR; - - list_for_each(i, &proto_list) { - cur = (struct ctproto_handler *) i; - if (strcmp(cur->name, name) == 0) { - handler = cur; - break; - } - } - - if (!handler) { - char path[sizeof("ct_proto_.so") - + strlen(name) + strlen(lib_dir)]; - sprintf(path, "%s/ct_proto_%s.so", lib_dir, name); - if (dlopen(path, RTLD_NOW)) - handler = findproto(name); - else - fprintf(stderr, "%s\n", dlerror()); - } - - return handler; -} - -enum exittype { - OTHER_PROBLEM = 1, - PARAMETER_PROBLEM, - VERSION_PROBLEM -}; - -void extension_help(struct ctproto_handler *h) -{ - fprintf(stdout, "\n"); - fprintf(stdout, "Proto `%s' help:\n", h->name); - h->help(); -} - -void -exit_tryhelp(int status) -{ - fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n", - PROGNAME, PROGNAME); - exit(status); -} - -static void -exit_error(enum exittype status, char *msg, ...) -{ - va_list args; - - /* On error paths, make sure that we don't leak the memory - * reserved during options merging */ - if (opts != original_opts) { - free(opts); - opts = original_opts; - global_option_offset = 0; - } - va_start(args, msg); - fprintf(stderr,"%s v%s: ", PROGNAME, VERSION); - vfprintf(stderr, msg, args); - va_end(args); - fprintf(stderr, "\n"); - if (status == PARAMETER_PROBLEM) - exit_tryhelp(status); - exit(status); -} - -static void -generic_cmd_check(int command, int options) -{ - int i; - - for (i = 0; i < NUMBER_OF_CMD; i++) { - if (!(command & (1< illegal, 1 => legal, 0 => undecided. */ - - for (j = 0; j < NUMBER_OF_CMD; j++) { - if (!(command & (1<size; i++) - if (strncasecmp(str, p->parameter[i], strlen) == 0) { - *value |= p->value[i]; - ret = 1; - break; - } - - return ret; -} - -static void -parse_parameter(const char *arg, unsigned int *status, int parse_type) -{ - const char *comma; - - while ((comma = strchr(arg, ',')) != NULL) { - if (comma == arg - || !do_parse_parameter(arg, comma-arg, status, parse_type)) - exit_error(PARAMETER_PROBLEM,"Bad parameter `%s'", arg); - arg = comma+1; - } - - if (strlen(arg) == 0 - || !do_parse_parameter(arg, strlen(arg), status, parse_type)) - exit_error(PARAMETER_PROBLEM, "Bad parameter `%s'", arg); -} - -static void -add_command(unsigned int *cmd, const int newcmd, const int othercmds) -{ - if (*cmd & (~othercmds)) - exit_error(PARAMETER_PROBLEM, "Invalid commands combination\n"); - *cmd |= newcmd; -} - -unsigned int check_type(int argc, char *argv[]) -{ - char *table = NULL; - - /* Nasty bug or feature in getopt_long ? - * It seems that it behaves badly with optional arguments. - * Fortunately, I just stole the fix from iptables ;) */ - if (optarg) - return 0; - else if (optind < argc && argv[optind][0] != '-' - && argv[optind][0] != '!') - table = argv[optind++]; - - if (!table) - return 0; - - if (strncmp("expect", table, 6) == 0) - return 1; - else if (strncmp("conntrack", table, 9) == 0) - return 0; - else - exit_error(PARAMETER_PROBLEM, "unknown type `%s'\n", table); - - return 0; -} - -static void set_family(int *family, int new) -{ - if (*family == AF_UNSPEC) - *family = new; - else if (*family != new) - exit_error(PARAMETER_PROBLEM, "mismatched address family\n"); -} - -struct addr_parse { - struct in_addr addr; - struct in6_addr addr6; - unsigned int family; -}; - -int __parse_inetaddr(const char *cp, struct addr_parse *parse) -{ - if (inet_aton(cp, &parse->addr)) - return AF_INET; -#ifdef HAVE_INET_PTON_IPV6 - else if (inet_pton(AF_INET6, cp, &parse->addr6) > 0) - return AF_INET6; -#endif - - exit_error(PARAMETER_PROBLEM, "Invalid IP address `%s'.", cp); -} - -int parse_inetaddr(const char *cp, union nfct_address *address) -{ - struct addr_parse parse; - int ret; - - if ((ret = __parse_inetaddr(cp, &parse)) == AF_INET) - address->v4 = parse.addr.s_addr; - else if (ret == AF_INET6) - memcpy(address->v6, &parse.addr6, sizeof(parse.addr6)); - - return ret; -} - -/* Shamelessly stolen from libipt_DNAT ;). Ranges expected in network order. */ -static void -nat_parse(char *arg, int portok, struct nfct_nat *range) -{ - char *colon, *dash, *error; - struct addr_parse parse; - - memset(range, 0, sizeof(range)); - colon = strchr(arg, ':'); - - if (colon) { - int port; - - if (!portok) - exit_error(PARAMETER_PROBLEM, - "Need TCP or UDP with port specification"); - - port = atoi(colon+1); - if (port == 0 || port > 65535) - exit_error(PARAMETER_PROBLEM, - "Port `%s' not valid\n", colon+1); - - error = strchr(colon+1, ':'); - if (error) - exit_error(PARAMETER_PROBLEM, - "Invalid port:port syntax - use dash\n"); - - dash = strchr(colon, '-'); - if (!dash) { - range->l4min.tcp.port - = range->l4max.tcp.port - = htons(port); - } else { - int maxport; - - maxport = atoi(dash + 1); - if (maxport == 0 || maxport > 65535) - exit_error(PARAMETER_PROBLEM, - "Port `%s' not valid\n", dash+1); - if (maxport < port) - /* People are stupid. */ - exit_error(PARAMETER_PROBLEM, - "Port range `%s' funky\n", colon+1); - range->l4min.tcp.port = htons(port); - range->l4max.tcp.port = htons(maxport); - } - /* Starts with a colon? No IP info... */ - if (colon == arg) - return; - *colon = '\0'; - } - - dash = strchr(arg, '-'); - if (colon && dash && dash > colon) - dash = NULL; - - if (dash) - *dash = '\0'; - - if (__parse_inetaddr(arg, &parse) != AF_INET) - return; - - range->min_ip = parse.addr.s_addr; - if (dash) { - if (__parse_inetaddr(dash+1, &parse) != AF_INET) - return; - range->max_ip = parse.addr.s_addr; - } else - range->max_ip = parse.addr.s_addr; -} - -static void event_sighandler(int s) -{ - fprintf(stdout, "Now closing conntrack event dumping...\n"); - nfct_close(cth); - exit(0); -} - -static const char usage_commands[] = - "Commands:\n" - " -L [table] [options]\t\tList conntrack or expectation table\n" - " -G [table] parameters\t\tGet conntrack or expectation\n" - " -D [table] parameters\t\tDelete conntrack or expectation\n" - " -I [table] parameters\t\tCreate a conntrack or expectation\n" - " -U [table] parameters\t\tUpdate a conntrack\n" - " -E [table] [options]\t\tShow events\n" - " -F [table]\t\t\tFlush table\n"; - -static const char usage_tables[] = - "Tables: conntrack, expect\n"; - -static const char usage_conntrack_parameters[] = - "Conntrack parameters and options:\n" - " -a, --nat-range min_ip[-max_ip]\tNAT ip range\n" - " -m, --mark mark\t\t\tSet mark\n" - " -e, --event-mask eventmask\t\tEvent mask, eg. NEW,DESTROY\n" - " -z, --zero \t\t\t\tZero counters while listing\n" - ; - -static const char usage_expectation_parameters[] = - "Expectation parameters and options:\n" - " --tuple-src ip\tSource address in expect tuple\n" - " --tuple-dst ip\tDestination address in expect tuple\n" - " --mask-src ip\t\tSource mask address\n" - " --mask-dst ip\t\tDestination mask address\n"; - -static const char usage_parameters[] = - "Common parameters and options:\n" - " -s, --orig-src ip\t\tSource address from original direction\n" - " -d, --orig-dst ip\t\tDestination address from original direction\n" - " -r, --reply-src ip\t\tSource addres from reply direction\n" - " -q, --reply-dst ip\t\tDestination address from reply direction\n" - " -p, --protonum proto\t\tLayer 4 Protocol, eg. 'tcp'\n" - " -f, --family proto\t\tLayer 3 Protocol, eg. 'ipv6'\n" - " -t, --timeout timeout\t\tSet timeout\n" - " -u, --status status\t\tSet status, eg. ASSURED\n" - " -i, --id [id]\t\t\tShow or set conntrack ID\n" - ; - - -void usage(char *prog) { - fprintf(stdout, "Tool to manipulate conntrack and expectations. Version %s\n", VERSION); - fprintf(stdout, "Usage: %s [commands] [options]\n", prog); - - fprintf(stdout, "\n%s", usage_commands); - fprintf(stdout, "\n%s", usage_tables); - fprintf(stdout, "\n%s", usage_conntrack_parameters); - fprintf(stdout, "\n%s", usage_expectation_parameters); - fprintf(stdout, "\n%s", usage_parameters); -} - -#define CT_COMPARISON (CT_OPT_PROTO | CT_OPT_ORIG | CT_OPT_REPL | CT_OPT_MARK) - -static struct nfct_tuple orig, reply, mask; -static struct nfct_tuple exptuple; -static struct ctproto_handler *h; -static union nfct_protoinfo proto; -static struct nfct_nat range; -static struct nfct_conntrack *ct; -static struct nfct_expect *exp; -static unsigned long timeout; -static unsigned int status; -static unsigned int mark; -static unsigned int id = NFCT_ANY_ID; -static struct nfct_conntrack_compare cmp; - -int main(int argc, char *argv[]) -{ - int c; - unsigned int command = 0, options = 0; - unsigned int type = 0, event_mask = 0; - unsigned int l3flags = 0, l4flags = 0, metaflags = 0; - int res = 0; - int family = AF_UNSPEC; - struct nfct_conntrack_compare *pcmp; - - while ((c = getopt_long(argc, argv, - "L::I::U::D::G::E::F::hVs:d:r:q:p:t:u:e:a:z[:]:{:}:m:i::f:", - opts, NULL)) != -1) { - switch(c) { - case 'L': - type = check_type(argc, argv); - if (type == 0) - add_command(&command, CT_LIST, CT_NONE); - else if (type == 1) - add_command(&command, EXP_LIST, CT_NONE); - break; - case 'I': - type = check_type(argc, argv); - if (type == 0) - add_command(&command, CT_CREATE, CT_NONE); - else if (type == 1) - add_command(&command, EXP_CREATE, CT_NONE); - break; - case 'U': - type = check_type(argc, argv); - if (type == 0) - add_command(&command, CT_UPDATE, CT_NONE); - else - exit_error(PARAMETER_PROBLEM, "Can't update " - "expectations"); - break; - case 'D': - type = check_type(argc, argv); - if (type == 0) - add_command(&command, CT_DELETE, CT_NONE); - else if (type == 1) - add_command(&command, EXP_DELETE, CT_NONE); - break; - case 'G': - type = check_type(argc, argv); - if (type == 0) - add_command(&command, CT_GET, CT_NONE); - else if (type == 1) - add_command(&command, EXP_GET, CT_NONE); - break; - case 'F': - type = check_type(argc, argv); - if (type == 0) - add_command(&command, CT_FLUSH, CT_NONE); - else if (type == 1) - add_command(&command, EXP_FLUSH, CT_NONE); - break; - case 'E': - type = check_type(argc, argv); - if (type == 0) - add_command(&command, CT_EVENT, CT_NONE); - else if (type == 1) - add_command(&command, EXP_EVENT, CT_NONE); - break; - case 'V': - add_command(&command, CT_VERSION, CT_NONE); - break; - case 'h': - add_command(&command, CT_HELP, CT_NONE); - break; - case 's': - options |= CT_OPT_ORIG_SRC; - if (optarg) { - orig.l3protonum = - parse_inetaddr(optarg, &orig.src); - set_family(&family, orig.l3protonum); - if (orig.l3protonum == AF_INET) - l3flags |= IPV4_ORIG_SRC; - else if (orig.l3protonum == AF_INET6) - l3flags |= IPV6_ORIG_SRC; - } - break; - case 'd': - options |= CT_OPT_ORIG_DST; - if (optarg) { - orig.l3protonum = - parse_inetaddr(optarg, &orig.dst); - set_family(&family, orig.l3protonum); - if (orig.l3protonum == AF_INET) - l3flags |= IPV4_ORIG_DST; - else if (orig.l3protonum == AF_INET6) - l3flags |= IPV6_ORIG_DST; - } - break; - case 'r': - options |= CT_OPT_REPL_SRC; - if (optarg) { - reply.l3protonum = - parse_inetaddr(optarg, &reply.src); - set_family(&family, reply.l3protonum); - if (orig.l3protonum == AF_INET) - l3flags |= IPV4_REPL_SRC; - else if (orig.l3protonum == AF_INET6) - l3flags |= IPV6_REPL_SRC; - } - break; - case 'q': - options |= CT_OPT_REPL_DST; - if (optarg) { - reply.l3protonum = - parse_inetaddr(optarg, &reply.dst); - set_family(&family, reply.l3protonum); - if (orig.l3protonum == AF_INET) - l3flags |= IPV4_REPL_DST; - else if (orig.l3protonum == AF_INET6) - l3flags |= IPV6_REPL_DST; - } - break; - case 'p': - options |= CT_OPT_PROTO; - h = findproto(optarg); - if (!h) - exit_error(PARAMETER_PROBLEM, "proto needed\n"); - orig.protonum = h->protonum; - reply.protonum = h->protonum; - exptuple.protonum = h->protonum; - mask.protonum = h->protonum; - opts = merge_options(opts, h->opts, - &h->option_offset); - break; - case 't': - options |= CT_OPT_TIMEOUT; - if (optarg) - timeout = atol(optarg); - break; - case 'u': { - if (!optarg) - continue; - - options |= CT_OPT_STATUS; - parse_parameter(optarg, &status, PARSE_STATUS); - break; - } - case 'e': - options |= CT_OPT_EVENT_MASK; - parse_parameter(optarg, &event_mask, PARSE_EVENT); - break; - case 'z': - options |= CT_OPT_ZERO; - break; - case '{': - options |= CT_OPT_MASK_SRC; - if (optarg) { - mask.l3protonum = - parse_inetaddr(optarg, &mask.src); - set_family(&family, mask.l3protonum); - } - break; - case '}': - options |= CT_OPT_MASK_DST; - if (optarg) { - mask.l3protonum = - parse_inetaddr(optarg, &mask.dst); - set_family(&family, mask.l3protonum); - } - break; - case '[': - options |= CT_OPT_EXP_SRC; - if (optarg) { - exptuple.l3protonum = - parse_inetaddr(optarg, &exptuple.src); - set_family(&family, exptuple.l3protonum); - } - break; - case ']': - options |= CT_OPT_EXP_DST; - if (optarg) { - exptuple.l3protonum = - parse_inetaddr(optarg, &exptuple.dst); - set_family(&family, exptuple.l3protonum); - } - break; - case 'a': - options |= CT_OPT_NATRANGE; - set_family(&family, AF_INET); - nat_parse(optarg, 1, &range); - break; - case 'm': - options |= CT_OPT_MARK; - mark = atol(optarg); - metaflags |= NFCT_MARK; - break; - case 'i': { - char *s = NULL; - options |= CT_OPT_ID; - if (optarg) - break; - else if (optind < argc && argv[optind][0] != '-' - && argv[optind][0] != '!') - s = argv[optind++]; - - if (s) - id = atol(s); - break; - } - case 'f': - options |= CT_OPT_FAMILY; - if (strncmp(optarg, "ipv4", strlen("ipv4")) == 0) - set_family(&family, AF_INET); - else if (strncmp(optarg, "ipv6", strlen("ipv6")) == 0) - set_family(&family, AF_INET6); - else - exit_error(PARAMETER_PROBLEM, "Unknown " - "protocol family\n"); - break; - default: - if (h && h->parse_opts - &&!h->parse_opts(c - h->option_offset, argv, &orig, - &reply, &exptuple, &mask, &proto, - &l4flags)) - exit_error(PARAMETER_PROBLEM, "parse error\n"); - - /* Unknown argument... */ - if (!h) { - usage(argv[0]); - exit_error(PARAMETER_PROBLEM, "Missing " - "arguments...\n"); - } - break; - } - } - - /* default family */ - if (family == AF_UNSPEC) - family = AF_INET; - - generic_cmd_check(command, options); - generic_opt_check(command, options); - - if (!(command & CT_HELP) - && h && h->final_check - && !h->final_check(l4flags, command, &orig, &reply)) { - usage(argv[0]); - extension_help(h); - exit_error(PARAMETER_PROBLEM, "Missing protocol arguments!\n"); - } - - switch(command) { - - case CT_LIST: - cth = nfct_open(CONNTRACK, 0); - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - - if (options & CT_COMPARISON) { - - if (options & CT_OPT_ZERO) - exit_error(PARAMETER_PROBLEM, "Can't use -z " - "with filtering parameters"); - - ct = nfct_conntrack_alloc(&orig, &reply, timeout, - &proto, status, mark, id, - NULL); - if (!ct) - exit_error(OTHER_PROBLEM, "Not enough memory"); - - cmp.ct = ct; - cmp.flags = metaflags; - cmp.l3flags = l3flags; - cmp.l4flags = l4flags; - pcmp = &cmp; - } - - if (options & CT_OPT_ID) - nfct_register_callback(cth, - nfct_default_conntrack_display_id, - (void *) pcmp); - else - nfct_register_callback(cth, - nfct_default_conntrack_display, - (void *) pcmp); - - if (options & CT_OPT_ZERO) - res = - nfct_dump_conntrack_table_reset_counters(cth, family); - else - res = nfct_dump_conntrack_table(cth, family); - nfct_close(cth); - break; - - case EXP_LIST: - cth = nfct_open(EXPECT, 0); - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - if (options & CT_OPT_ID) - nfct_register_callback(cth, - nfct_default_expect_display_id, - NULL); - else - nfct_register_callback(cth, - nfct_default_expect_display, - NULL); - res = nfct_dump_expect_list(cth, family); - nfct_close(cth); - break; - - case CT_CREATE: - if ((options & CT_OPT_ORIG) - && !(options & CT_OPT_REPL)) { - reply.l3protonum = orig.l3protonum; - memcpy(&reply.src, &orig.dst, sizeof(reply.src)); - memcpy(&reply.dst, &orig.src, sizeof(reply.dst)); - } else if (!(options & CT_OPT_ORIG) - && (options & CT_OPT_REPL)) { - orig.l3protonum = reply.l3protonum; - memcpy(&orig.src, &reply.dst, sizeof(orig.src)); - memcpy(&orig.dst, &reply.src, sizeof(orig.dst)); - } - if (options & CT_OPT_NATRANGE) - ct = nfct_conntrack_alloc(&orig, &reply, timeout, - &proto, status, mark, id, - &range); - else - ct = nfct_conntrack_alloc(&orig, &reply, timeout, - &proto, status, mark, id, - NULL); - if (!ct) - exit_error(OTHER_PROBLEM, "Not Enough memory"); - - cth = nfct_open(CONNTRACK, 0); - if (!cth) { - nfct_conntrack_free(ct); - exit_error(OTHER_PROBLEM, "Can't open handler"); - } - res = nfct_create_conntrack(cth, ct); - nfct_close(cth); - nfct_conntrack_free(ct); - break; - - case EXP_CREATE: - if (options & CT_OPT_ORIG) - exp = nfct_expect_alloc(&orig, &exptuple, - &mask, timeout, id); - else if (options & CT_OPT_REPL) - exp = nfct_expect_alloc(&reply, &exptuple, - &mask, timeout, id); - if (!exp) - exit_error(OTHER_PROBLEM, "Not enough memory"); - - cth = nfct_open(EXPECT, 0); - if (!cth) { - nfct_expect_free(exp); - exit_error(OTHER_PROBLEM, "Can't open handler"); - } - res = nfct_create_expectation(cth, exp); - nfct_expect_free(exp); - nfct_close(cth); - break; - - case CT_UPDATE: - if ((options & CT_OPT_ORIG) - && !(options & CT_OPT_REPL)) { - reply.l3protonum = orig.l3protonum; - memcpy(&reply.src, &orig.dst, sizeof(reply.src)); - memcpy(&reply.dst, &orig.src, sizeof(reply.dst)); - } else if (!(options & CT_OPT_ORIG) - && (options & CT_OPT_REPL)) { - orig.l3protonum = reply.l3protonum; - memcpy(&orig.src, &reply.dst, sizeof(orig.src)); - memcpy(&orig.dst, &reply.src, sizeof(orig.dst)); - } - ct = nfct_conntrack_alloc(&orig, &reply, timeout, - &proto, status, mark, id, - NULL); - if (!ct) - exit_error(OTHER_PROBLEM, "Not enough memory"); - - cth = nfct_open(CONNTRACK, 0); - if (!cth) { - nfct_conntrack_free(ct); - exit_error(OTHER_PROBLEM, "Can't open handler"); - } - res = nfct_update_conntrack(cth, ct); - nfct_conntrack_free(ct); - nfct_close(cth); - break; - - case CT_DELETE: - if (!(options & CT_OPT_ORIG) && !(options & CT_OPT_REPL)) - exit_error(PARAMETER_PROBLEM, "Can't kill conntracks " - "just by its ID"); - cth = nfct_open(CONNTRACK, 0); - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - if (options & CT_OPT_ORIG) - res = nfct_delete_conntrack(cth, &orig, - NFCT_DIR_ORIGINAL, - id); - else if (options & CT_OPT_REPL) - res = nfct_delete_conntrack(cth, &reply, - NFCT_DIR_REPLY, - id); - nfct_close(cth); - break; - - case EXP_DELETE: - cth = nfct_open(EXPECT, 0); - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - if (options & CT_OPT_ORIG) - res = nfct_delete_expectation(cth, &orig, id); - else if (options & CT_OPT_REPL) - res = nfct_delete_expectation(cth, &reply, id); - nfct_close(cth); - break; - - case CT_GET: - cth = nfct_open(CONNTRACK, 0); - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - nfct_register_callback(cth, nfct_default_conntrack_display, - NULL); - if (options & CT_OPT_ORIG) - res = nfct_get_conntrack(cth, &orig, - NFCT_DIR_ORIGINAL, id); - else if (options & CT_OPT_REPL) - res = nfct_get_conntrack(cth, &reply, - NFCT_DIR_REPLY, id); - nfct_close(cth); - break; - - case EXP_GET: - cth = nfct_open(EXPECT, 0); - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - nfct_register_callback(cth, nfct_default_expect_display, - NULL); - if (options & CT_OPT_ORIG) - res = nfct_get_expectation(cth, &orig, id); - else if (options & CT_OPT_REPL) - res = nfct_get_expectation(cth, &reply, id); - nfct_close(cth); - break; - - case CT_FLUSH: - cth = nfct_open(CONNTRACK, 0); - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - res = nfct_flush_conntrack_table(cth, AF_INET); - nfct_close(cth); - break; - - case EXP_FLUSH: - cth = nfct_open(EXPECT, 0); - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - res = nfct_flush_expectation_table(cth, AF_INET); - nfct_close(cth); - break; - - case CT_EVENT: - if (options & CT_OPT_EVENT_MASK) - cth = nfct_open(CONNTRACK, event_mask); - else - cth = nfct_open(CONNTRACK, NFCT_ALL_CT_GROUPS); - - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - signal(SIGINT, event_sighandler); - - if (options & CT_COMPARISON) { - ct = nfct_conntrack_alloc(&orig, &reply, timeout, - &proto, status, mark, id, - NULL); - if (!ct) - exit_error(OTHER_PROBLEM, "Not enough memory"); - - cmp.ct = ct; - cmp.flags = metaflags; - cmp.l3flags = l3flags; - cmp.l4flags = l4flags; - pcmp = &cmp; - } - - nfct_register_callback(cth, - nfct_default_conntrack_event_display, - (void *) pcmp); - res = nfct_event_conntrack(cth); - nfct_close(cth); - break; - - case EXP_EVENT: - cth = nfct_open(EXPECT, NF_NETLINK_CONNTRACK_EXP_NEW); - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - signal(SIGINT, event_sighandler); - nfct_register_callback(cth, nfct_default_expect_display, - NULL); - res = nfct_event_expectation(cth); - nfct_close(cth); - break; - - case CT_VERSION: - fprintf(stdout, "%s v%s\n", PROGNAME, VERSION); - break; - case CT_HELP: - usage(argv[0]); - if (options & CT_OPT_PROTO) - extension_help(h); - break; - default: - usage(argv[0]); - break; - } - - if (opts != original_opts) { - free(opts); - opts = original_opts; - global_option_offset = 0; - } - - if (res < 0) { - fprintf(stderr, "Operation failed: %s\n", err2str(res, command)); - exit(OTHER_PROBLEM); - } - - return 0; -} diff --git a/test.sh b/test.sh deleted file mode 100644 index 4694236..0000000 --- a/test.sh +++ /dev/null @@ -1,110 +0,0 @@ -CONNTRACK=conntrack - -SRC=1.1.1.1 -DST=2.2.2.2 -SPORT=2005 -DPORT=21 - -case $1 in - dump) - echo "Dumping conntrack table" - $CONNTRACK -L - ;; - flush) - echo "Flushing conntrack table" - $CONNTRACK -F - ;; - new) - echo "creating a new conntrack" - $CONNTRACK -I --orig-src $SRC --orig-dst $DST \ - --reply-src $DST --reply-dst $SRC -p tcp \ - --orig-port-src $SPORT --orig-port-dst $DPORT \ - --reply-port-src $DPORT --reply-port-dst $SPORT \ - --state LISTEN -u SEEN_REPLY -t 50 - ;; - new-simple) - echo "creating a new conntrack (simplified)" - $CONNTRACK -I --orig-src $SRC --orig-dst $DST \ - -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \ - --state LISTEN -u SEEN_REPLY -t 50 - ;; - new-nat) - echo "creating a new conntrack (NAT)" - $CONNTRACK -I --orig-src $SRC --orig-dst $DST \ - -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \ - --state LISTEN -u SEEN_REPLY,SRC_NAT -t 50 -a 8.8.8.8 - ;; - get) - echo "getting a conntrack" - $CONNTRACK -G --orig-src $SRC --orig-dst $DST \ - -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \ - --reply-port-src $DPORT --reply-port-dst $SPORT - ;; - change) - echo "change a conntrack" - $CONNTRACK -U --orig-src $SRC --orig-dst $DST \ - --reply-src $DST --reply-dst $SRC -p tcp \ - --orig-port-src $SPORT --orig-port-dst $DPORT \ - --reply-port-src $DPORT --reply-port-dst $SPORT \ - --state TIME_WAIT -u ASSURED,SEEN_REPLY -t 500 - ;; - delete) - $CONNTRACK -D --orig-src $SRC --orig-dst $DST \ - -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT - ;; - output) - proc=$(cat /proc/net/ip_conntrack | wc -l) - netl=$($CONNTRACK -L | wc -l) - count=$(cat /proc/sys/net/ipv4/netfilter/ip_conntrack_count) - if [ $proc -ne $netl ]; then - echo "proc is $proc and netl is $netl and count is $count" - else - if [ $proc -ne $count ]; then - echo "proc is $proc and netl is $netl and count is $count" - else - echo "now $proc" - fi - fi - ;; - dump-expect) - $CONNTRACK -L expect - ;; - flush-expect) - $CONNTRACK -F expect - ;; - create-expect) - # requires modprobe ip_conntrack_ftp - $CONNTRACK -I expect --orig-src $SRC --orig-dst $DST \ - --tuple-src 4.4.4.4 --tuple-dst 5.5.5.5 \ - --mask-src 255.255.255.0 --mask-dst 255.255.255.255 \ - -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \ - -t 200 --tuple-port-src 10 --tuple-port-dst 300 \ - --mask-port-src 10 --mask-port-dst 300 - ;; - get-expect) - $CONNTRACK -G expect --orig-src 4.4.4.4 --orig-dst 5.5.5.5 \ - --p tcp --orig-port-src 0 --orig-port-dst 0 \ - --mask-port-src 10 --mask-port-dst 11 - ;; - delete-expect) - $CONNTRACK -D expect --orig-src 4.4.4.4 \ - --orig-dst 5.5.5.5 -p tcp --orig-port-src 0 \ - --orig-port-dst 0 --mask-port-src 10 --mask-port-dst 11 - ;; - *) - echo "Usage: $0 [dump" - echo " |new" - echo " |new-simple" - echo " |new-nat" - echo " |get" - echo " |change" - echo " |delete" - echo " |output" - echo " |flush" - echo " |dump-expect" - echo " |flush-expect" - echo " |create-expect" - echo " |get-expect" - echo " |delete-expect]" - ;; -esac -- cgit v1.2.3 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 --- AUTHORS | 1 + CHANGELOG | 184 ++++ CONTRIBUTORS | 3 + ChangeLog | 243 +++++ INSTALL | 199 ++++ Make_global.am | 1 + Makefile.am | 21 + TODO | 18 + autogen.sh | 18 + cli/ChangeLog | 243 ----- cli/conntrack.8 | 142 --- cli/extensions/Makefile.am | 16 - cli/extensions/libct_proto_icmp.c | 108 -- cli/extensions/libct_proto_icmp.man | 10 - cli/extensions/libct_proto_sctp.c | 164 --- cli/extensions/libct_proto_tcp.c | 180 ---- cli/extensions/libct_proto_tcp.man | 16 - cli/extensions/libct_proto_udp.c | 141 --- cli/extensions/libct_proto_udp.man | 13 - cli/include/conntrack.h | 160 --- cli/src/conntrack.c | 1131 -------------------- cli/test.sh | 110 -- configure.in | 106 ++ conntrack.8 | 142 +++ daemon/AUTHORS | 1 - daemon/CHANGELOG | 184 ---- daemon/CONTRIBUTORS | 3 - daemon/INSTALL | 199 ---- daemon/Make_global.am | 1 - daemon/Makefile.am | 21 - daemon/TODO | 18 - daemon/autogen.sh | 18 - daemon/configure.in | 106 -- daemon/examples/Makefile.am | 1 - daemon/examples/debian.conntrackd.init.d | 48 - daemon/examples/stats/Makefile.am | 1 - daemon/examples/stats/conntrackd.conf | 69 -- daemon/examples/sync/Makefile.am | 1 - daemon/examples/sync/nack/Makefile.am | 2 - daemon/examples/sync/nack/README | 1 - daemon/examples/sync/nack/node1/Makefile.am | 1 - daemon/examples/sync/nack/node1/conntrackd.conf | 125 --- daemon/examples/sync/nack/node1/keepalived.conf | 38 - daemon/examples/sync/nack/node2/Makefile.am | 1 - daemon/examples/sync/nack/node2/conntrackd.conf | 124 --- daemon/examples/sync/nack/node2/keepalived.conf | 38 - daemon/examples/sync/nack/script_backup.sh | 3 - daemon/examples/sync/nack/script_master.sh | 5 - daemon/examples/sync/persistent/Makefile.am | 2 - daemon/examples/sync/persistent/README | 1 - daemon/examples/sync/persistent/node1/Makefile.am | 1 - .../examples/sync/persistent/node1/conntrackd.conf | 130 --- .../examples/sync/persistent/node1/keepalived.conf | 38 - daemon/examples/sync/persistent/node2/Makefile.am | 1 - .../examples/sync/persistent/node2/conntrackd.conf | 130 --- .../examples/sync/persistent/node2/keepalived.conf | 38 - daemon/examples/sync/persistent/script_backup.sh | 3 - daemon/examples/sync/persistent/script_master.sh | 4 - daemon/include/Makefile.am | 5 - daemon/include/alarm.h | 13 - daemon/include/buffer.h | 32 - daemon/include/cache.h | 92 -- daemon/include/conntrackd.h | 174 --- daemon/include/debug.h | 53 - daemon/include/hash.h | 47 - daemon/include/ignore.h | 12 - daemon/include/jhash.h | 146 --- daemon/include/linux_list.h | 725 ------------- daemon/include/local.h | 29 - daemon/include/log.h | 10 - daemon/include/mcast.h | 48 - daemon/include/network.h | 34 - daemon/include/slist.h | 41 - daemon/include/state_helper.h | 20 - daemon/include/sync.h | 23 - daemon/include/us-conntrack.h | 13 - daemon/src/Makefile.am | 22 - daemon/src/alarm.c | 141 --- daemon/src/buffer.c | 136 --- daemon/src/cache.c | 446 -------- daemon/src/cache_iterators.c | 229 ---- daemon/src/cache_lifetime.c | 65 -- daemon/src/cache_timer.c | 72 -- daemon/src/checksum.c | 32 - daemon/src/hash.c | 199 ---- daemon/src/ignore_pool.c | 136 --- daemon/src/local.c | 159 --- daemon/src/lock.c | 32 - daemon/src/log.c | 57 - daemon/src/main.c | 302 ------ daemon/src/mcast.c | 287 ----- daemon/src/netlink.c | 326 ------ daemon/src/network.c | 282 ----- daemon/src/proxy.c | 124 --- daemon/src/read_config_lex.l | 125 --- daemon/src/read_config_yy.y | 550 ---------- daemon/src/run.c | 227 ---- daemon/src/state_helper.c | 44 - daemon/src/state_helper_tcp.c | 35 - daemon/src/stats-mode.c | 151 --- daemon/src/sync-mode.c | 416 ------- daemon/src/sync-nack.c | 309 ------ daemon/src/sync-notrack.c | 127 --- daemon/src/traffic_stats.c | 54 - examples/Makefile.am | 1 + examples/debian.conntrackd.init.d | 48 + examples/stats/Makefile.am | 1 + examples/stats/conntrackd.conf | 69 ++ examples/sync/Makefile.am | 1 + examples/sync/nack/Makefile.am | 2 + examples/sync/nack/README | 1 + examples/sync/nack/node1/Makefile.am | 1 + examples/sync/nack/node1/conntrackd.conf | 125 +++ examples/sync/nack/node1/keepalived.conf | 38 + examples/sync/nack/node2/Makefile.am | 1 + examples/sync/nack/node2/conntrackd.conf | 124 +++ examples/sync/nack/node2/keepalived.conf | 38 + examples/sync/nack/script_backup.sh | 3 + examples/sync/nack/script_master.sh | 5 + examples/sync/persistent/Makefile.am | 2 + examples/sync/persistent/README | 1 + examples/sync/persistent/node1/Makefile.am | 1 + examples/sync/persistent/node1/conntrackd.conf | 130 +++ examples/sync/persistent/node1/keepalived.conf | 38 + examples/sync/persistent/node2/Makefile.am | 1 + examples/sync/persistent/node2/conntrackd.conf | 130 +++ examples/sync/persistent/node2/keepalived.conf | 38 + examples/sync/persistent/script_backup.sh | 3 + examples/sync/persistent/script_master.sh | 4 + extensions/Makefile.am | 16 + extensions/libct_proto_icmp.c | 108 ++ extensions/libct_proto_icmp.man | 10 + extensions/libct_proto_sctp.c | 164 +++ extensions/libct_proto_tcp.c | 180 ++++ extensions/libct_proto_tcp.man | 16 + extensions/libct_proto_udp.c | 141 +++ extensions/libct_proto_udp.man | 13 + include/Makefile.am | 5 + include/alarm.h | 13 + include/buffer.h | 32 + include/cache.h | 92 ++ include/conntrack.h | 160 +++ include/conntrackd.h | 174 +++ include/debug.h | 53 + include/hash.h | 47 + include/ignore.h | 12 + include/jhash.h | 146 +++ include/linux_list.h | 725 +++++++++++++ include/local.h | 29 + include/log.h | 10 + include/mcast.h | 48 + include/network.h | 34 + include/slist.h | 41 + include/state_helper.h | 20 + include/sync.h | 23 + include/us-conntrack.h | 13 + src/Makefile.am | 26 + src/alarm.c | 141 +++ src/buffer.c | 136 +++ src/cache.c | 446 ++++++++ src/cache_iterators.c | 229 ++++ src/cache_lifetime.c | 65 ++ src/cache_timer.c | 72 ++ src/checksum.c | 32 + src/conntrack.c | 1131 ++++++++++++++++++++ src/hash.c | 199 ++++ src/ignore_pool.c | 136 +++ src/local.c | 159 +++ src/lock.c | 32 + src/log.c | 57 + src/main.c | 302 ++++++ src/mcast.c | 287 +++++ src/netlink.c | 326 ++++++ src/network.c | 282 +++++ src/proxy.c | 124 +++ src/read_config_lex.l | 125 +++ src/read_config_yy.y | 550 ++++++++++ src/run.c | 227 ++++ src/state_helper.c | 44 + src/state_helper_tcp.c | 35 + src/stats-mode.c | 151 +++ src/sync-mode.c | 416 +++++++ src/sync-nack.c | 309 ++++++ src/sync-notrack.c | 127 +++ src/traffic_stats.c | 54 + test.sh | 110 ++ 186 files changed, 10397 insertions(+), 10393 deletions(-) create mode 100644 AUTHORS create mode 100644 CHANGELOG create mode 100644 CONTRIBUTORS create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Make_global.am create mode 100644 Makefile.am create mode 100644 TODO create mode 100755 autogen.sh delete mode 100644 cli/ChangeLog delete mode 100644 cli/conntrack.8 delete mode 100644 cli/extensions/Makefile.am delete mode 100644 cli/extensions/libct_proto_icmp.c delete mode 100644 cli/extensions/libct_proto_icmp.man delete mode 100644 cli/extensions/libct_proto_sctp.c delete mode 100644 cli/extensions/libct_proto_tcp.c delete mode 100644 cli/extensions/libct_proto_tcp.man delete mode 100644 cli/extensions/libct_proto_udp.c delete mode 100644 cli/extensions/libct_proto_udp.man delete mode 100644 cli/include/conntrack.h delete mode 100644 cli/src/conntrack.c delete mode 100644 cli/test.sh create mode 100644 configure.in create mode 100644 conntrack.8 delete mode 100644 daemon/AUTHORS delete mode 100644 daemon/CHANGELOG delete mode 100644 daemon/CONTRIBUTORS delete mode 100644 daemon/INSTALL delete mode 100644 daemon/Make_global.am delete mode 100644 daemon/Makefile.am delete mode 100644 daemon/TODO delete mode 100755 daemon/autogen.sh delete mode 100644 daemon/configure.in delete mode 100644 daemon/examples/Makefile.am delete mode 100644 daemon/examples/debian.conntrackd.init.d delete mode 100644 daemon/examples/stats/Makefile.am delete mode 100644 daemon/examples/stats/conntrackd.conf delete mode 100644 daemon/examples/sync/Makefile.am delete mode 100644 daemon/examples/sync/nack/Makefile.am delete mode 100644 daemon/examples/sync/nack/README delete mode 100644 daemon/examples/sync/nack/node1/Makefile.am delete mode 100644 daemon/examples/sync/nack/node1/conntrackd.conf delete mode 100644 daemon/examples/sync/nack/node1/keepalived.conf delete mode 100644 daemon/examples/sync/nack/node2/Makefile.am delete mode 100644 daemon/examples/sync/nack/node2/conntrackd.conf delete mode 100644 daemon/examples/sync/nack/node2/keepalived.conf delete mode 100755 daemon/examples/sync/nack/script_backup.sh delete mode 100755 daemon/examples/sync/nack/script_master.sh delete mode 100644 daemon/examples/sync/persistent/Makefile.am delete mode 100644 daemon/examples/sync/persistent/README delete mode 100644 daemon/examples/sync/persistent/node1/Makefile.am delete mode 100644 daemon/examples/sync/persistent/node1/conntrackd.conf delete mode 100644 daemon/examples/sync/persistent/node1/keepalived.conf delete mode 100644 daemon/examples/sync/persistent/node2/Makefile.am delete mode 100644 daemon/examples/sync/persistent/node2/conntrackd.conf delete mode 100644 daemon/examples/sync/persistent/node2/keepalived.conf delete mode 100755 daemon/examples/sync/persistent/script_backup.sh delete mode 100755 daemon/examples/sync/persistent/script_master.sh delete mode 100644 daemon/include/Makefile.am delete mode 100644 daemon/include/alarm.h delete mode 100644 daemon/include/buffer.h delete mode 100644 daemon/include/cache.h delete mode 100644 daemon/include/conntrackd.h delete mode 100644 daemon/include/debug.h delete mode 100644 daemon/include/hash.h delete mode 100644 daemon/include/ignore.h delete mode 100644 daemon/include/jhash.h delete mode 100644 daemon/include/linux_list.h delete mode 100644 daemon/include/local.h delete mode 100644 daemon/include/log.h delete mode 100644 daemon/include/mcast.h delete mode 100644 daemon/include/network.h delete mode 100644 daemon/include/slist.h delete mode 100644 daemon/include/state_helper.h delete mode 100644 daemon/include/sync.h delete mode 100644 daemon/include/us-conntrack.h delete mode 100644 daemon/src/Makefile.am delete mode 100644 daemon/src/alarm.c delete mode 100644 daemon/src/buffer.c delete mode 100644 daemon/src/cache.c delete mode 100644 daemon/src/cache_iterators.c delete mode 100644 daemon/src/cache_lifetime.c delete mode 100644 daemon/src/cache_timer.c delete mode 100644 daemon/src/checksum.c delete mode 100644 daemon/src/hash.c delete mode 100644 daemon/src/ignore_pool.c delete mode 100644 daemon/src/local.c delete mode 100644 daemon/src/lock.c delete mode 100644 daemon/src/log.c delete mode 100644 daemon/src/main.c delete mode 100644 daemon/src/mcast.c delete mode 100644 daemon/src/netlink.c delete mode 100644 daemon/src/network.c delete mode 100644 daemon/src/proxy.c delete mode 100644 daemon/src/read_config_lex.l delete mode 100644 daemon/src/read_config_yy.y delete mode 100644 daemon/src/run.c delete mode 100644 daemon/src/state_helper.c delete mode 100644 daemon/src/state_helper_tcp.c delete mode 100644 daemon/src/stats-mode.c delete mode 100644 daemon/src/sync-mode.c delete mode 100644 daemon/src/sync-nack.c delete mode 100644 daemon/src/sync-notrack.c delete mode 100644 daemon/src/traffic_stats.c create mode 100644 examples/Makefile.am create mode 100644 examples/debian.conntrackd.init.d create mode 100644 examples/stats/Makefile.am create mode 100644 examples/stats/conntrackd.conf create mode 100644 examples/sync/Makefile.am create mode 100644 examples/sync/nack/Makefile.am create mode 100644 examples/sync/nack/README create mode 100644 examples/sync/nack/node1/Makefile.am create mode 100644 examples/sync/nack/node1/conntrackd.conf create mode 100644 examples/sync/nack/node1/keepalived.conf create mode 100644 examples/sync/nack/node2/Makefile.am create mode 100644 examples/sync/nack/node2/conntrackd.conf create mode 100644 examples/sync/nack/node2/keepalived.conf create mode 100755 examples/sync/nack/script_backup.sh create mode 100755 examples/sync/nack/script_master.sh create mode 100644 examples/sync/persistent/Makefile.am create mode 100644 examples/sync/persistent/README create mode 100644 examples/sync/persistent/node1/Makefile.am create mode 100644 examples/sync/persistent/node1/conntrackd.conf create mode 100644 examples/sync/persistent/node1/keepalived.conf create mode 100644 examples/sync/persistent/node2/Makefile.am create mode 100644 examples/sync/persistent/node2/conntrackd.conf create mode 100644 examples/sync/persistent/node2/keepalived.conf create mode 100755 examples/sync/persistent/script_backup.sh create mode 100755 examples/sync/persistent/script_master.sh create mode 100644 extensions/Makefile.am create mode 100644 extensions/libct_proto_icmp.c create mode 100644 extensions/libct_proto_icmp.man create mode 100644 extensions/libct_proto_sctp.c create mode 100644 extensions/libct_proto_tcp.c create mode 100644 extensions/libct_proto_tcp.man create mode 100644 extensions/libct_proto_udp.c create mode 100644 extensions/libct_proto_udp.man create mode 100644 include/Makefile.am create mode 100644 include/alarm.h create mode 100644 include/buffer.h create mode 100644 include/cache.h create mode 100644 include/conntrack.h create mode 100644 include/conntrackd.h create mode 100644 include/debug.h create mode 100644 include/hash.h create mode 100644 include/ignore.h create mode 100644 include/jhash.h create mode 100644 include/linux_list.h create mode 100644 include/local.h create mode 100644 include/log.h create mode 100644 include/mcast.h create mode 100644 include/network.h create mode 100644 include/slist.h create mode 100644 include/state_helper.h create mode 100644 include/sync.h create mode 100644 include/us-conntrack.h create mode 100644 src/Makefile.am create mode 100644 src/alarm.c create mode 100644 src/buffer.c create mode 100644 src/cache.c create mode 100644 src/cache_iterators.c create mode 100644 src/cache_lifetime.c create mode 100644 src/cache_timer.c create mode 100644 src/checksum.c create mode 100644 src/conntrack.c create mode 100644 src/hash.c create mode 100644 src/ignore_pool.c create mode 100644 src/local.c create mode 100644 src/lock.c create mode 100644 src/log.c create mode 100644 src/main.c create mode 100644 src/mcast.c create mode 100644 src/netlink.c create mode 100644 src/network.c create mode 100644 src/proxy.c create mode 100644 src/read_config_lex.l create mode 100644 src/read_config_yy.y create mode 100644 src/run.c create mode 100644 src/state_helper.c create mode 100644 src/state_helper_tcp.c create mode 100644 src/stats-mode.c create mode 100644 src/sync-mode.c create mode 100644 src/sync-nack.c create mode 100644 src/sync-notrack.c create mode 100644 src/traffic_stats.c create mode 100644 test.sh (limited to 'Makefile.am') diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..e6c2f6b --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Pablo Neira Ayuso diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..afab61d --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,184 @@ +version 0.9.3 (yet unreleased) +------------------------------ +o fix commit of confirmed expectations (reported by Nishit Shah) +o fix double increment of counters in cache_update_force() (Niko Tyni) +o nl_dump_handler must return NFCT_CB_CONTINUE (Niko Tyni) +o initialize buffer in nl_event_handler() and nl_dump_handler() (Niko Tyni) +o CacheCommit value can be set via conntrackd.conf for the NACK approach +o fix leaks in the hashtable/cache flush path (Niko Tyni) +o fix leak if a connection already exists in the cache (Niko Tyni) +o introduce a new header that encapsulates netlink messages +o remove all '_entry' tail from all functions in cache.c +o split cache.c: move cache iterators to file cache_iterators.c +o fix inconsistencies in the cache API related to counters +o cleanup 'usage' message +o fix typo in examples/sync/nack/node1/conntrackd.conf +o introduce message checksumming as described in RFC1071 (enabled by default) +o major cleanups in the synchronization code +o just warn once that the maximum netlink socket buffer has been reached +o fix ignore conntrack entries by IP and introduce ignore pool abstraction layer +o introduce netlink socket buffer overrun handler +o constification of hash, compare and hashtable_test functions in hash.c +o introduce ACKnowledgement mechanisms to reduce the size of the resend queue +o remove OK messages at startup since provide useless data +o fix compilation warning in mcast.c: recvfrom takes socklen_t not size_t +o add a lock per buffer: makes buffer code thread safe +o introduce 'Replicate' clause to explicitely set states to be replicated +o kill cache feature abuse: introduce nicer cache hooks for sync algorithms +o fix oversized buffer allocated in the stack in the cache functions +o add support to dump internal/external cache in XML format '-x' + +version 0.9.2 (2006/01/17) +-------------------------- +o remove spamming packet lost messages +o generalize network netlink sequence tracking +o fix bogus error message on resync `-R' +o fix endianess issues in the network netlink message +o introduce generic netlink multicast primitives to send and receive +o fix bogus replayed multicast message due to sequence numbering wraparound +o introduce counter for malformed netlink messages received +o introduce a new syntax for the `Sync' section in the configuration file +o several cleanups and remove unused variables +o add autostuff to include examples in the tarball (reported by Victor Lozano) +o use the new API available in libnetfilter_conntrack-0.0.50 +o implement a NACK based protocol for replication + +version 0.9.1 (2006/11/06) +-------------------------- +o conntrackd requires kernel >= 2.6.18 +o remove bogus TIMERS_MODE constant +o implement bulk mode '-B': first works to address the preemption issue +o fix minor reduction conflicts in the configfile grammar +o check for CAP_NET_ADMIN instead of requiring root privileges +o check that linux/capability.h exists +o fix formatting at dump statistics '-s' +o move dump traffic stats before multicast traffic stats +o move event and dump handler to a generic infrastructure: kill events.c file +o kill unused function inc_ct_stats +o kill file resync.h +o cleanup broadcast_sync: renamed to mcast_send_sync +o sed 's/perror/debug/g' local.c +o fix bogus increment of update_fail stats at dump stage +o display descriptive error if we can't connect to conntrackd via UNIX socket +o remove debugging message from alarm.c +o move dump_mcast_stats to mcast.c where it really belongs +o rename stats.c to traffic_stats.c +o check for replayed/lost multicast message: simple seq tracking w/o recovery +o reissue nfnl_catch on ENOENT error: a message for other subsystem +o remove test/ directory in tree +o improve cache commit stats +o kill last_commit and last_flush from cache statistics: use the logfile +o recover cache naming for dump stats `-s' +o display multicast sequence tracking statistics: packets lost and replayed +o zero ct_sync_state and ct_stats_state structures after allocation +o improve keepalived scripts: + - resync with conntrack table on transition to master + - send bulk on transition to backup +o implement alarm cascade of ten levels +o implement timer cache flavour: limited life of entries in the external cache +o implement a global lock that protects operation with conntrack entries +o remove debug checking in cache_del_entry +o set a reduced timeout for committed entries: 180 seconds by default +o update comments on the sync-mode code +o introduce delay destroy messages facility +o increase timer for external states from 60 to 180 seconds +o remove unused replicate/dont_replicated constants +o fix cache entry clashing issue (reported by Maik Hentsche) +o fix bogus increment of error stats in the external cache +o remove pollution generated by `[REQ] cache dump' message from logfile + +version 0.9.0 (2006/09/17) +-------------------------- +o implement initial for IPv6 (untested) +o implement generic extensible cache: kill the internal and external caches +o implement persistence cache feature +o implement lifetime cache feature +o modify UNIX facilities identification numbers: + separate master conntrack facilities and internal plugin facilities +o break backward compatibility of configuration file: + remove IgnoreLoopback, use IgnoreTrafficFor instead + remove IgnoreMulticastTraffic, use IgnoreTrafficFor instead +o merge event/event_subsys and sync/sync_subsys initialization to run.c +o improve control of the iteration process in the hashtables +o fix wrong locking in the alarm thread +o supersede AcceptNAT by StripNAT clause +o replace ignore traffic array by a hashtable +o move lockfile checking before daemonization +o on initialization error give a descriptive error +o introduce netlink socket size grown limitator +o introduce force resync with master conntrack table facility '-R' +o ignore SIGPIPE signal +o kill post_step since it is not used anymore + +version 0.8.3 (2006/09/03) +-------------------------- +Author: Maik Hentsche + +o Fix typo in conntrackd -h +o Disable debugging messages by default +o No signals while signals handlings +o Add extra checkings at forking +o Check maximum size for file passed via -C + +Author: Pablo Neira Ayuso + +o retry select() if EINTR is returned (Reported by Maik Hentsche) +o Fix bug in slist_for_each_entry (Reported by Maik Hetsche) +o Signal handler registration done after intialization +o Implement alarm thread (based on Maik Hentsche's patch) +o Fix segfault on conntrackd -k (Reported by Maik Hentsche) +o Fix bug on alarm removal (Reported by Maik Hentsche) +o configure stops if bison, flex or yacc are not installed + +version 0.8.2 (2006/07/05) +-------------------------- +o RelaxTransitions clause introduced in Sync mode +o multicast messages sequence tracking +o SocketBufferSize clause to set up the netlink socket buffer +o use new libnfnetlink API to solve limitations of nfnl_listen +o extra sanity checkings for netlink multicast messages +o improve statistics +o tons of cleanups 8) + +version 0.8.1 (2006/06/13) +-------------------------- +o -f now just flushes the internal and external caches +o -F flushes the master conntrack table +o fix segfault under heavy load and signal received +o added -S mode for statistics: still needs more thinking + +version 0.8.0 (2006/06/11) +-------------------------- +o more work to generalize the daemon: now it's ready to implement +modular support for adaptive timers and conntrack statistics, time +to implement them ;). This is *still* a work in progress. + +version 0.7.2 (2006/06/05) +-------------------------- +o stupid bug in normal and alarm caches initialization: flush unset +o fix racy signal handling + +version 0.7.1 (2006/06/05) +-------------------------- +o Bugfix for multicast sockets communication + +version 0.7 (2006/06/01) +------------------------ +o Major code re-structuration: internal and external cache abstraction +o sequence tracking for event messages +o expect more changes, I still dislike some stuff in its current status ;) + +version 0.6 (2006/05/31) +------------------------ +o Lock file support +o use new API nfct_conntrack_event_raw +o major code clean ups + +version 0.5 (2006/05/30) +------------------------- +o Fix multicast server binds to wrong interface +o Include clause `IgnoreProtocol', deprecates IgnoreUDP and IgnoreICMP + +version 0.4 (2006/05/29) +------------------------ +o Initial release diff --git a/CONTRIBUTORS b/CONTRIBUTORS new file mode 100644 index 0000000..c5e40b4 --- /dev/null +++ b/CONTRIBUTORS @@ -0,0 +1,3 @@ +Maik Hentsche : + - Feedback & Brainstorming + - Bug hunting diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..1524ef6 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,243 @@ +2006-03-20 + + o fix ICMP protocol extension parse callback + +2006-01-15 + + o Added missing parameters to set the ports of an expectation tuple + o Add support to filter dumped entries. + ie: conntrack -L -p tcp --orig-port-dst 993 + display all the connections to IMAPS servers + conntrack -L -m 2 + display all the connection marked with 2 + o Bumped version to 1.00beta2 + +2005-12-26 + + o add IPv6 support: main change + o removed dead code: iptables_insmod and get_modprobe + o compact the commands vs. options table + o move working vars from the stack to the BSS section + o update manpage + o Bumped version to 1.0beta1 + + o check address family mismatch + o fix incomplete copying IPv6 addresses + +2005-12-19 + + o We only support ipv4 at the moment: set l3protonum to AF_INET + o Minor changes to prepare upcoming ipv6 support + +2005-12-03 + + o Add support to filter events. ie: -p tcp --orig-port-dst 80 in + conjuction with -E to get all the requests to HTTP servers + o Update manpage + o Missing static function declaration in the protocol handlers + o Use protocol flags defined in libnetfilter_conntrack + o Bumped version to 0.991 + +2005-11-22 + + o Fix oversized number of options + +2005-11-11 + + o don't check for kernel header path in configure, since we don't use + kernel headers + o don't check for libnfnetlink, we don't use it directly + o move plugins into pkglibdir + o remove 'lib' prefix of plugins, they're not really libraries + o remove version information from plugin filenames + o Bumped version to 0.99 +2005-11-09 + + o set status to zero, libnetfilter_conntrack now activate + IPS_CONFIRMED since all conntrack in hash must be confirmed. + o Bumped version to 0.98 + +2005-11-08 + + o Fix warnings generated by gcc -Wall + o Fix conntrack exit value at error + o Replace obsolete inet_addr by inet_aton + +2005-11-05 + + o Improved conntrack -h output + o add htons for icmp id. + + o -t and -u are optional at update. + o Fixed versioning :( + o Bumped version to 0.97 + +2005-11-03 + + o Use extra 'data' argument of nfct_register_callback() function that + I've introduced in libetfilter_conntrack. + + o moves conntrack tool from bin to sbin directory since this + application is an administration utility and it requires uid==0 or + CAP_NET_ADMIN + + o check if --state missing when -p is passed + o command type is passed to final_check: checkings based on the + command can be done now. + o kill duplicated definition of IPS_* bits: Already present in + libnetfilter_conntrack. + o Move action and command enum to conntrack.h + o kill NIPQUAD macro + o make conntrack handler cth static. + o Bumped version to 0.96 + +2005-11-01 + + o Fix error message describing illegal option -E -i + o -D -i ID requires tuple information: Display an error message + o Use NFCT_ALL_CT_GROUPS flag instead of NFCT_ALL_GROUPS + o Event mask doesn't make sense for expectations, kill dead code + o Bumped version to 0.95 + + o Fix wrong formating in conntrack -h + +2005-10-30 + + Special thanks to Deti Fiegl from the Leibniz Supercomputing Centre in + Munich, Germany for providing the "fast" hardware to reproduce + spurious bugs ;) + + o Replace misleading message "Not enough memory" by "Can't open handler" + o New option -i for expectation dumping: conntrack -L expect [-i] + o sed 's/VERSION/CONNTRACK_VERSION/g' + o Fix nfct_open flags, now uses NFCT_ALL_GROUPS when needed + o Bumped version to 0.94 + +2005-10-28 + + o New option -i for dumping: conntrack -L [-i] + o Fixed warning in findproto due to a stupid wrong type definition + o sed 's/nfct_set_callback/nfct_register_callback/g' + o killed the 'retry' logic, *sigh* it is broken in some cases + o killed broken and unneeded protocol handler destructors (fini) + o killed unregister_proto + o Fixed code indentation in the command selector + o Bumped version to 0.93 + +2005-10-27 + + o Use conntrack VERSION instead of the old LIBCT_VERSION + o proto_list and lib_dir are now static + o kill dead code: function dump_tuple + o Bumped version to 0.92 + +2005-10-25 + + o Add missing autogen.sh file + +2005-10-24 + + o use NFCT_ANY_GROUP flag in nfct_open() + +2005-10-21 + + o Bumped version to 0.90 + o Add support for id and marks + +2005-10-20 + + o Kill some more files that generated by the autocrap + o Resync with the lastest libnetfilter_conntrack API changes + +2005-10-16 + + o Rename libct_proto.h to conntrack.h + o Remove config.h.in from svn, it's autogenerated by the autocrap :) + o Remove dead functions in the SCTP protocol helper + +2005-10-14 + + o Kill config.h.in, it's generated by the autocrap + o The conntrack tool now uses libnetfilter_conntrack :) + o libct.c has been killed, now it's in libnetfilter_conntrack + o Check if you're root or CAP_NET_ADMIN + o Bumped version number to 0.86 + +2005-10-07 + + o Fixed ICMP options + + o Multiple fixes for the ICMP protocol handler + o Fix ICMP output: wrong output. type and code were set to zero. + +2005-10-05 + + o Fix up counters + o Fix up compilation (IPS_* stuff missing), still need a proper fix + o Bumped version number to 0.82 + +2005-09-24 + + o Get rid of C++ style comments + o Remove remaining bits of "-A --action", group-mask and dump-mask + o Clean up #include's + o Fix double-free when exiting via signal handler (Ctrl+C) + o Add "version" member to plugins + o Fix some Endianness issues when printing CTA_STATUS + +2005-08-31 + + o Fix packet and bytes counters (use __be64_to_cpu) + o Fix ip_conntrack_netlink load-on-demand + +2005-07-12 + + o Use conntrack netlink attributes: Major change + o Kill action setting: Mask based dumping + o Fix ChangeLog + +2005-05-23 + + o Fixed syntax error (tab/space issue) in help message + o Fixed getopt handling on big endian machines + o Fixed possible future read-over-end-of-array in TCP extension + o Add manpage + o Add missing space at output of libct_proto_icmp.c + o Add status bits that were introduced in 2.6.11 + o Add SCTP extension + o Add support for expect creation + o Bump version number to 0.63 + +2005-05-17 + + o Added descriptive error messages. + o Fix wrong flags check in [tcp|udp] proto helpers. + +2005-05-16 + + o Implemented ICMP proto helper + o Added help() and final_check() functions for proto helpers. + +2005-05-01 + + o Created changelog file + o Deleted libctnetlink.h and libnfnetlink.h from the include/ dir. + o Added support for version (-V) and help (-h) + o Added event mask based support + o Added GPLv2 headers + o Use fprintf instead of printf + o Defined print_tuple and print_proto output interfaces + o ctnl_[get|del]_conntrack handles return value from kernel via msgerr + o Added support for conntrack table flushing + o Added test case file (test.sh) + o Improve dump output + + + o Autoconf stuff for conntrack + some pablo's modifications. + o Fixed packet counters formatting (use %llu instead of %lu) + +2005-04-25 + + o Added support for mask based event dumping + o Added support for mask based event notification + o On-demand autoload of ip_conntrack_netlink diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..0de8dc0 --- /dev/null +++ b/INSTALL @@ -0,0 +1,199 @@ +Copyright (C) 2006-2007 Pablo Neira Ayuso + +1.Basic Installation +==================== + + To compile and install 'conntrackd' just follow the classical steps: + + $ ./configure + $ make + # make install + # mkdir /etc/conntrackd/ + +2.1. Synchronization Mode +========================= + + Conntrackd can replicate the status of the connections that are currently + being processed by your stateful firewall based on Linux. This section + describes how to setup the daemon in synchronization mode: + +2.1.1. Requirements + + You have to install the following software in order to get conntrackd working, + make sure that you have installed them correctly before going forward: + + o linux kernel version >= 2.6.18 (http://www.kernel.org) with support for: + - connection tracking system (quite obvious ;) + - nfnetlink + - ctnetlink (ip_conntrack_netlink) + - connection tracking event notification API + + o libnfnetlink: the netfilter netlink library + + Since conntrackd version 0.9.2 you can used the official release availble at + http://www.netfilter.org/projects/libnfnetlink/files/ + + Up to conntrackd version 0.9.1 use the unofficial release available at the + download section + + o libnetfilter_conntrack: the netfilter conntrack library + + Since conntrackd version 0.9.2 you can used the official release availble at + http://www.netfilter.org/projects/libnetfilter_conntrack/files/ + + Up to conntrackd version 0.9.1 use the unnoficial release available at the + download section + + o Keepalived version 1.x (http://www.keepalived.org) + check if your distribution comes with a recent version + +2.1.2. Configuration + + 1) Setting up keepalived + + There is an example file available inside the conntrackd tarball: + + For node 1: conntrackd-x.x.x/examples/sync/node1/keepalived.conf + For node 2: conntrackd-x.x.x/examples/sync/node2/keepalived.conf + + These files can be used to set up a simple VRRP cluster composed of + two machines that hold the virtual IPs 192.168.0.100 on eth0 and + 192.168.1.100 on eth1. + + If you are not familiar with keepalived, please read the official + docs available at http://www.keepalived.org + + Please, make sure that keepalived is correctly working before passing + to step 2) + + 2) Setting up conntrackd + + To setup 'conntrackd' in synchronization mode, you have to put the + configuration file in the directory /etc/conntrackd. + + On node 1: + # cp examples/sync/_type_/node1/conntrackd.conf /etc/conntrackd.conf + + On node 2: + # cp examples/sync/_type_/node1/conntrackd.conf /etc/conntrackd.conf + + Where _type_ is the synchronization type selected, currently there are + two: the persistent mode and the NACK mode. The persistent mode consumes + more resources than the NACK mode, however the NACK mode is still + experimental + + Do not forget to edit the files in order to adapt them to the + setting that you are deploying. + + Note: If you don't want to put the config file under /etc/conntrackd, + just tell conntrackd where to find it passing the option -C + + 3) Running conntrackd + + Conntrackd can run in console mode, in that case just type 'conntrackd', + otherwise, if you want to run it in daemon mode the type 'conntrackd -d'. + + 4) Checking that conntrackd is working fine + + Conntrackd comes with several facilities to check its status: + + - Dump the cache of connections that are currently being processed by + this node (aka. internal cache): + + # conntrackd -i + + - Dump the cache of connections that has been transfered from + others active nodes in the network (aka. external cache) + + # conntrackd -e + + - Dump statistics collected by the replication daemon: + + # conntrackd -s + + 5) Setting up interaction with keepalived + + If keepalived detects the failure of the active node, then it designates + a candidate node that will replace the failing active. On such event, + the external cache, eg. the cache that contains the connections processed + by other nodes, must be commited. To commit the external cache, just type: + + # conntrackd -c + + See that keepalived provides a shell script interface to interact with + other programs, so we can automate the process of commiting the external + cache by introducing the following line in the keepalived file: + + notify_master /etc/conntrackd/script_master.sh + + The script 'script_master.sh' just the following: + + #!/bin/sh + /usr/sbin/conntrackd -c + + Therefore, on failure event, the candidate node takes over the virtual + IPs and the connections that the failing active was processing. Observe + that this file differs for the NACK mode. + + 6) Disable TCP window tracking + + Until the appropiate patches don't go into kernel mainline, you will have + to disable TCP window tracking, consider this as a temporary solution: + + # echo 1 > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_be_liberal + +2.2. Statistics mode +==================== + + Conntrackd can also run as statistics daemon, if you are not interested in + this mode, just skip it. It is not required in order to get the + synchronization mode working. This section details how to setup the daemon + in statistics mode: + +2.2.1. Requirements + + You have to install the following software in order to get conntrackd working, + make sure that you have them installed correctly before going forward: + + o linux kernel version >= 2.6.18 (http://www.kernel.org) with support for: + - connection tracking system + - nfnetlink + - ctnetlink (ip_conntrack_netlink) + - connection tracking event notification API + + o libnfnetlink: the netfilter netlink library + + Since conntrackd version 0.9.2 you can used the official release availble at + http://www.netfilter.org/projects/libnfnetlink/files/ + + Up to conntrackd version 0.9.1 use the unofficial release available at the + download section + + o libnetfilter_conntrack: the netfilter conntrack library + + Since conntrackd version 0.9.2 you can used the official release availble at + http://www.netfilter.org/projects/libnetfilter_conntrack/files/ + + Up to conntrackd version 0.9.1 use the unnoficial release available at the + download section + +2.2.2. Configuration + + Setting up conntrackd in statistics mode is rather easy. Just copy the + configuration file + + # cp examples/stats/conntrackd.conf /etc/conntrackd.conf + +2.2.3. Running conntrackd in statistics mode + + To run conntrackd in statistics mode: + + # conntrackd -S + + Alternatively, you can run conntrackd in daemon mode: + + # conntrackd -S -d + + In order to dump the statistics, just type: + + # conntrackd -s diff --git a/Make_global.am b/Make_global.am new file mode 100644 index 0000000..685add7 --- /dev/null +++ b/Make_global.am @@ -0,0 +1 @@ +INCLUDES=$(all_includes) -I$(top_srcdir)/include diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..8a4ce7c --- /dev/null +++ b/Makefile.am @@ -0,0 +1,21 @@ +include Make_global.am + +# not a GNU package. You can remove this line, if +# have all needed files, that a GNU package needs +AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 + +# man_MANS = "" +# EXTRA_DIST = $(man_MANS) Make_global.am debian +EXTRA_DIST = Make_global.am CHANGELOG TODO + +SUBDIRS = src extensions +DIST_SUBDIRS = include src extensions examples +LINKOPTS = -lnfnetlink -lnetfilter_conntrack -lpthread +AM_CFLAGS = -g + +$(OBJECTS): libtool +libtool: $(LIBTOOL_DEPS) + $(SHELL) ./config.status --recheck + +dist-hook: + rm -rf `find $(distdir)/debian -name .svn` diff --git a/TODO b/TODO new file mode 100644 index 0000000..130b1f8 --- /dev/null +++ b/TODO @@ -0,0 +1,18 @@ +There are several tasks that are pending to be done, I have classified them +by dificulty levels: + +Relatively easy +=============== + +- test ipv6 support +- improve shell scripts +- test NACK based protocol +- manpage for conntrackd + +Requires some work +================== + +- study better keepalived transitions +- implement support for TCP window tracking (patches are on the table) + - at the moment you have to disable it: + echo 1 > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_be_liberal diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..e76d3ef --- /dev/null +++ b/autogen.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +run () +{ + echo "running: $*" + eval $* + + if test $? != 0 ; then + echo "error: while running '$*'" + exit 1 + fi +} + +run aclocal +run libtoolize -f +#run autoheader +run automake -a +run autoconf diff --git a/cli/ChangeLog b/cli/ChangeLog deleted file mode 100644 index 1524ef6..0000000 --- a/cli/ChangeLog +++ /dev/null @@ -1,243 +0,0 @@ -2006-03-20 - - o fix ICMP protocol extension parse callback - -2006-01-15 - - o Added missing parameters to set the ports of an expectation tuple - o Add support to filter dumped entries. - ie: conntrack -L -p tcp --orig-port-dst 993 - display all the connections to IMAPS servers - conntrack -L -m 2 - display all the connection marked with 2 - o Bumped version to 1.00beta2 - -2005-12-26 - - o add IPv6 support: main change - o removed dead code: iptables_insmod and get_modprobe - o compact the commands vs. options table - o move working vars from the stack to the BSS section - o update manpage - o Bumped version to 1.0beta1 - - o check address family mismatch - o fix incomplete copying IPv6 addresses - -2005-12-19 - - o We only support ipv4 at the moment: set l3protonum to AF_INET - o Minor changes to prepare upcoming ipv6 support - -2005-12-03 - - o Add support to filter events. ie: -p tcp --orig-port-dst 80 in - conjuction with -E to get all the requests to HTTP servers - o Update manpage - o Missing static function declaration in the protocol handlers - o Use protocol flags defined in libnetfilter_conntrack - o Bumped version to 0.991 - -2005-11-22 - - o Fix oversized number of options - -2005-11-11 - - o don't check for kernel header path in configure, since we don't use - kernel headers - o don't check for libnfnetlink, we don't use it directly - o move plugins into pkglibdir - o remove 'lib' prefix of plugins, they're not really libraries - o remove version information from plugin filenames - o Bumped version to 0.99 -2005-11-09 - - o set status to zero, libnetfilter_conntrack now activate - IPS_CONFIRMED since all conntrack in hash must be confirmed. - o Bumped version to 0.98 - -2005-11-08 - - o Fix warnings generated by gcc -Wall - o Fix conntrack exit value at error - o Replace obsolete inet_addr by inet_aton - -2005-11-05 - - o Improved conntrack -h output - o add htons for icmp id. - - o -t and -u are optional at update. - o Fixed versioning :( - o Bumped version to 0.97 - -2005-11-03 - - o Use extra 'data' argument of nfct_register_callback() function that - I've introduced in libetfilter_conntrack. - - o moves conntrack tool from bin to sbin directory since this - application is an administration utility and it requires uid==0 or - CAP_NET_ADMIN - - o check if --state missing when -p is passed - o command type is passed to final_check: checkings based on the - command can be done now. - o kill duplicated definition of IPS_* bits: Already present in - libnetfilter_conntrack. - o Move action and command enum to conntrack.h - o kill NIPQUAD macro - o make conntrack handler cth static. - o Bumped version to 0.96 - -2005-11-01 - - o Fix error message describing illegal option -E -i - o -D -i ID requires tuple information: Display an error message - o Use NFCT_ALL_CT_GROUPS flag instead of NFCT_ALL_GROUPS - o Event mask doesn't make sense for expectations, kill dead code - o Bumped version to 0.95 - - o Fix wrong formating in conntrack -h - -2005-10-30 - - Special thanks to Deti Fiegl from the Leibniz Supercomputing Centre in - Munich, Germany for providing the "fast" hardware to reproduce - spurious bugs ;) - - o Replace misleading message "Not enough memory" by "Can't open handler" - o New option -i for expectation dumping: conntrack -L expect [-i] - o sed 's/VERSION/CONNTRACK_VERSION/g' - o Fix nfct_open flags, now uses NFCT_ALL_GROUPS when needed - o Bumped version to 0.94 - -2005-10-28 - - o New option -i for dumping: conntrack -L [-i] - o Fixed warning in findproto due to a stupid wrong type definition - o sed 's/nfct_set_callback/nfct_register_callback/g' - o killed the 'retry' logic, *sigh* it is broken in some cases - o killed broken and unneeded protocol handler destructors (fini) - o killed unregister_proto - o Fixed code indentation in the command selector - o Bumped version to 0.93 - -2005-10-27 - - o Use conntrack VERSION instead of the old LIBCT_VERSION - o proto_list and lib_dir are now static - o kill dead code: function dump_tuple - o Bumped version to 0.92 - -2005-10-25 - - o Add missing autogen.sh file - -2005-10-24 - - o use NFCT_ANY_GROUP flag in nfct_open() - -2005-10-21 - - o Bumped version to 0.90 - o Add support for id and marks - -2005-10-20 - - o Kill some more files that generated by the autocrap - o Resync with the lastest libnetfilter_conntrack API changes - -2005-10-16 - - o Rename libct_proto.h to conntrack.h - o Remove config.h.in from svn, it's autogenerated by the autocrap :) - o Remove dead functions in the SCTP protocol helper - -2005-10-14 - - o Kill config.h.in, it's generated by the autocrap - o The conntrack tool now uses libnetfilter_conntrack :) - o libct.c has been killed, now it's in libnetfilter_conntrack - o Check if you're root or CAP_NET_ADMIN - o Bumped version number to 0.86 - -2005-10-07 - - o Fixed ICMP options - - o Multiple fixes for the ICMP protocol handler - o Fix ICMP output: wrong output. type and code were set to zero. - -2005-10-05 - - o Fix up counters - o Fix up compilation (IPS_* stuff missing), still need a proper fix - o Bumped version number to 0.82 - -2005-09-24 - - o Get rid of C++ style comments - o Remove remaining bits of "-A --action", group-mask and dump-mask - o Clean up #include's - o Fix double-free when exiting via signal handler (Ctrl+C) - o Add "version" member to plugins - o Fix some Endianness issues when printing CTA_STATUS - -2005-08-31 - - o Fix packet and bytes counters (use __be64_to_cpu) - o Fix ip_conntrack_netlink load-on-demand - -2005-07-12 - - o Use conntrack netlink attributes: Major change - o Kill action setting: Mask based dumping - o Fix ChangeLog - -2005-05-23 - - o Fixed syntax error (tab/space issue) in help message - o Fixed getopt handling on big endian machines - o Fixed possible future read-over-end-of-array in TCP extension - o Add manpage - o Add missing space at output of libct_proto_icmp.c - o Add status bits that were introduced in 2.6.11 - o Add SCTP extension - o Add support for expect creation - o Bump version number to 0.63 - -2005-05-17 - - o Added descriptive error messages. - o Fix wrong flags check in [tcp|udp] proto helpers. - -2005-05-16 - - o Implemented ICMP proto helper - o Added help() and final_check() functions for proto helpers. - -2005-05-01 - - o Created changelog file - o Deleted libctnetlink.h and libnfnetlink.h from the include/ dir. - o Added support for version (-V) and help (-h) - o Added event mask based support - o Added GPLv2 headers - o Use fprintf instead of printf - o Defined print_tuple and print_proto output interfaces - o ctnl_[get|del]_conntrack handles return value from kernel via msgerr - o Added support for conntrack table flushing - o Added test case file (test.sh) - o Improve dump output - - - o Autoconf stuff for conntrack + some pablo's modifications. - o Fixed packet counters formatting (use %llu instead of %lu) - -2005-04-25 - - o Added support for mask based event dumping - o Added support for mask based event notification - o On-demand autoload of ip_conntrack_netlink diff --git a/cli/conntrack.8 b/cli/conntrack.8 deleted file mode 100644 index 307180b..0000000 --- a/cli/conntrack.8 +++ /dev/null @@ -1,142 +0,0 @@ -.TH CONNTRACK 8 "Jun 23, 2005" "" "" - -.\" Man page written by Harald Welte . diff --git a/cli/extensions/Makefile.am b/cli/extensions/Makefile.am deleted file mode 100644 index 5366ee3..0000000 --- a/cli/extensions/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ -include $(top_srcdir)/Make_global.am - -AM_CFLAGS=-fPIC -Wall -LIBS= - -pkglib_LTLIBRARIES = ct_proto_tcp.la ct_proto_udp.la \ - ct_proto_icmp.la ct_proto_sctp.la - -ct_proto_tcp_la_SOURCES = libct_proto_tcp.c -ct_proto_tcp_la_LDFLAGS = -module -avoid-version -ct_proto_udp_la_SOURCES = libct_proto_udp.c -ct_proto_udp_la_LDFLAGS = -module -avoid-version -ct_proto_icmp_la_SOURCES = libct_proto_icmp.c -ct_proto_icmp_la_LDFLAGS = -module -avoid-version -ct_proto_sctp_la_SOURCES = libct_proto_sctp.c -ct_proto_sctp_la_LDFLAGS = -module -avoid-version diff --git a/cli/extensions/libct_proto_icmp.c b/cli/extensions/libct_proto_icmp.c deleted file mode 100644 index e7cb04d..0000000 --- a/cli/extensions/libct_proto_icmp.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * (C) 2005 by Pablo Neira Ayuso - * Harald Welte - * - * 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 -#include -#include -#include /* For htons */ -#include -#include -#include -#include "conntrack.h" - -static struct option opts[] = { - {"icmp-type", 1, 0, '1'}, - {"icmp-code", 1, 0, '2'}, - {"icmp-id", 1, 0, '3'}, - {0, 0, 0, 0} -}; - -static void help() -{ - fprintf(stdout, "--icmp-type icmp type\n"); - fprintf(stdout, "--icmp-code icmp code\n"); - fprintf(stdout, "--icmp-id icmp id\n"); -} - -/* Add 1; spaces filled with 0. */ -static u_int8_t invmap[] - = { [ICMP_ECHO] = ICMP_ECHOREPLY + 1, - [ICMP_ECHOREPLY] = ICMP_ECHO + 1, - [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1, - [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1, - [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1, - [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1, - [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1, - [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1}; - -static int parse(char c, char *argv[], - struct nfct_tuple *orig, - struct nfct_tuple *reply, - struct nfct_tuple *exptuple, - struct nfct_tuple *mask, - union nfct_protoinfo *proto, - unsigned int *flags) -{ - switch(c) { - case '1': - if (optarg) { - orig->l4dst.icmp.type = atoi(optarg); - reply->l4dst.icmp.type = - invmap[orig->l4dst.icmp.type] - 1; - *flags |= ICMP_TYPE; - } - break; - case '2': - if (optarg) { - orig->l4dst.icmp.code = atoi(optarg); - reply->l4dst.icmp.code = 0; - *flags |= ICMP_CODE; - } - break; - case '3': - if (optarg) { - orig->l4src.icmp.id = htons(atoi(optarg)); - reply->l4dst.icmp.id = 0; - *flags |= ICMP_ID; - } - break; - } - return 1; -} - -static int final_check(unsigned int flags, - unsigned int command, - struct nfct_tuple *orig, - struct nfct_tuple *reply) -{ - if (!(flags & ICMP_TYPE)) - return 0; - else if (!(flags & ICMP_CODE)) - return 0; - - return 1; -} - -static struct ctproto_handler icmp = { - .name = "icmp", - .protonum = IPPROTO_ICMP, - .parse_opts = parse, - .final_check = final_check, - .help = help, - .opts = opts, - .version = VERSION, -}; - -static void __attribute__ ((constructor)) init(void); - -static void init(void) -{ - register_proto(&icmp); -} diff --git a/cli/extensions/libct_proto_icmp.man b/cli/extensions/libct_proto_icmp.man deleted file mode 100644 index 3b860d0..0000000 --- a/cli/extensions/libct_proto_icmp.man +++ /dev/null @@ -1,10 +0,0 @@ -This module matches on ICMP-specific fields. -.TP -.BI "--icmp-type " "TYPE" -ICMP Type. Has to be specified numerically. -.TP -.BI "--icmp-code " "CODE" -ICMP Code. Has to be specified numerically. -.TP -.BI "--icmp-id " "ID" -ICMP Id. Has to be specified numerically. diff --git a/cli/extensions/libct_proto_sctp.c b/cli/extensions/libct_proto_sctp.c deleted file mode 100644 index 1c8f0d1..0000000 --- a/cli/extensions/libct_proto_sctp.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * (C) 2005 by Harald Welte - * 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. - * - */ -#include -#include -#include -#include -#include /* For htons */ -#include "conntrack.h" -#include -#include - -static struct option opts[] = { - {"orig-port-src", 1, 0, '1'}, - {"orig-port-dst", 1, 0, '2'}, - {"reply-port-src", 1, 0, '3'}, - {"reply-port-dst", 1, 0, '4'}, - {"state", 1, 0, '5'}, - {"tuple-port-src", 1, 0, '6'}, - {"tuple-port-dst", 1, 0, '7'}, - {0, 0, 0, 0} -}; - -static const char *states[] = { - "NONE", - "CLOSED", - "COOKIE_WAIT", - "COOKIE_ECHOED", - "ESTABLISHED", - "SHUTDOWN_SENT", - "SHUTDOWN_RECV", - "SHUTDOWN_ACK_SENT", -}; - -static void help() -{ - fprintf(stdout, "--orig-port-src original source port\n"); - fprintf(stdout, "--orig-port-dst original destination port\n"); - fprintf(stdout, "--reply-port-src reply source port\n"); - fprintf(stdout, "--reply-port-dst reply destination port\n"); - fprintf(stdout, "--state SCTP state, fe. ESTABLISHED\n"); - fprintf(stdout, "--tuple-port-src expectation tuple src port\n"); - fprintf(stdout, "--tuple-port-src expectation tuple dst port\n"); -} - -static int parse_options(char c, char *argv[], - struct nfct_tuple *orig, - struct nfct_tuple *reply, - struct nfct_tuple *exptuple, - struct nfct_tuple *mask, - union nfct_protoinfo *proto, - unsigned int *flags) -{ - switch(c) { - case '1': - if (optarg) { - orig->l4src.sctp.port = htons(atoi(optarg)); - *flags |= SCTP_ORIG_SPORT; - } - break; - case '2': - if (optarg) { - orig->l4dst.sctp.port = htons(atoi(optarg)); - *flags |= SCTP_ORIG_DPORT; - } - break; - case '3': - if (optarg) { - reply->l4src.sctp.port = htons(atoi(optarg)); - *flags |= SCTP_REPL_SPORT; - } - break; - case '4': - if (optarg) { - reply->l4dst.sctp.port = htons(atoi(optarg)); - *flags |= SCTP_REPL_DPORT; - } - break; - case '5': - if (optarg) { - int i; - for (i=0; i<10; i++) { - if (strcmp(optarg, states[i]) == 0) { - /* FIXME: Add state to - * nfct_protoinfo - proto->sctp.state = i; */ - break; - } - } - if (i == 10) { - printf("doh?\n"); - return 0; - } - *flags |= SCTP_STATE; - } - break; - case '6': - if (optarg) { - exptuple->l4src.sctp.port = htons(atoi(optarg)); - *flags |= SCTP_EXPTUPLE_SPORT; - } - break; - case '7': - if (optarg) { - exptuple->l4dst.sctp.port = htons(atoi(optarg)); - *flags |= SCTP_EXPTUPLE_DPORT; - } - - } - return 1; -} - -static int final_check(unsigned int flags, - unsigned int command, - struct nfct_tuple *orig, - struct nfct_tuple *reply) -{ - int ret = 0; - - if ((flags & (SCTP_ORIG_SPORT|SCTP_ORIG_DPORT)) - && !(flags & (SCTP_REPL_SPORT|SCTP_REPL_DPORT))) { - reply->l4src.sctp.port = orig->l4dst.sctp.port; - reply->l4dst.sctp.port = orig->l4src.sctp.port; - ret = 1; - } else if (!(flags & (SCTP_ORIG_SPORT|SCTP_ORIG_DPORT)) - && (flags & (SCTP_REPL_SPORT|SCTP_REPL_DPORT))) { - orig->l4src.sctp.port = reply->l4dst.sctp.port; - orig->l4dst.sctp.port = reply->l4src.sctp.port; - ret = 1; - } - if ((flags & (SCTP_ORIG_SPORT|SCTP_ORIG_DPORT)) - && ((flags & (SCTP_REPL_SPORT|SCTP_REPL_DPORT)))) - ret = 1; - - /* --state is missing and we are trying to create a conntrack */ - if (ret && (command & CT_CREATE) && (!(flags & SCTP_STATE))) - ret = 0; - - return ret; -} - -static struct ctproto_handler sctp = { - .name = "sctp", - .protonum = IPPROTO_SCTP, - .parse_opts = parse_options, - .final_check = final_check, - .help = help, - .opts = opts, - .version = VERSION, -}; - -static void __attribute__ ((constructor)) init(void); - -static void init(void) -{ - register_proto(&sctp); -} diff --git a/cli/extensions/libct_proto_tcp.c b/cli/extensions/libct_proto_tcp.c deleted file mode 100644 index ee24206..0000000 --- a/cli/extensions/libct_proto_tcp.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * (C) 2005 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 -#include -#include -#include -#include /* For htons */ -#include -#include - -#include "conntrack.h" - -static struct option opts[] = { - {"orig-port-src", 1, 0, '1'}, - {"orig-port-dst", 1, 0, '2'}, - {"reply-port-src", 1, 0, '3'}, - {"reply-port-dst", 1, 0, '4'}, - {"mask-port-src", 1, 0, '5'}, - {"mask-port-dst", 1, 0, '6'}, - {"state", 1, 0, '7'}, - {"tuple-port-src", 1, 0, '8'}, - {"tuple-port-dst", 1, 0, '9'}, - {0, 0, 0, 0} -}; - -static const char *states[] = { - "NONE", - "SYN_SENT", - "SYN_RECV", - "ESTABLISHED", - "FIN_WAIT", - "CLOSE_WAIT", - "LAST_ACK", - "TIME_WAIT", - "CLOSE", - "LISTEN" -}; - -static void help() -{ - fprintf(stdout, "--orig-port-src original source port\n"); - fprintf(stdout, "--orig-port-dst original destination port\n"); - fprintf(stdout, "--reply-port-src reply source port\n"); - fprintf(stdout, "--reply-port-dst reply destination port\n"); - fprintf(stdout, "--mask-port-src mask source port\n"); - fprintf(stdout, "--mask-port-dst mask destination port\n"); - fprintf(stdout, "--tuple-port-src expectation tuple src port\n"); - fprintf(stdout, "--tuple-port-src expectation tuple dst port\n"); - fprintf(stdout, "--state TCP state, fe. ESTABLISHED\n"); -} - -static int parse_options(char c, char *argv[], - struct nfct_tuple *orig, - struct nfct_tuple *reply, - struct nfct_tuple *exptuple, - struct nfct_tuple *mask, - union nfct_protoinfo *proto, - unsigned int *flags) -{ - switch(c) { - case '1': - if (optarg) { - orig->l4src.tcp.port = htons(atoi(optarg)); - *flags |= TCP_ORIG_SPORT; - } - break; - case '2': - if (optarg) { - orig->l4dst.tcp.port = htons(atoi(optarg)); - *flags |= TCP_ORIG_DPORT; - } - break; - case '3': - if (optarg) { - reply->l4src.tcp.port = htons(atoi(optarg)); - *flags |= TCP_REPL_SPORT; - } - break; - case '4': - if (optarg) { - reply->l4dst.tcp.port = htons(atoi(optarg)); - *flags |= TCP_REPL_DPORT; - } - break; - case '5': - if (optarg) { - mask->l4src.tcp.port = htons(atoi(optarg)); - *flags |= TCP_MASK_SPORT; - } - break; - case '6': - if (optarg) { - mask->l4dst.tcp.port = htons(atoi(optarg)); - *flags |= TCP_MASK_DPORT; - } - break; - case '7': - if (optarg) { - int i; - for (i=0; i<10; i++) { - if (strcmp(optarg, states[i]) == 0) { - proto->tcp.state = i; - break; - } - } - if (i == 10) { - printf("doh?\n"); - return 0; - } - *flags |= TCP_STATE; - } - break; - case '8': - if (optarg) { - exptuple->l4src.tcp.port = htons(atoi(optarg)); - *flags |= TCP_EXPTUPLE_SPORT; - } - break; - case '9': - if (optarg) { - exptuple->l4dst.tcp.port = htons(atoi(optarg)); - *flags |= TCP_EXPTUPLE_DPORT; - } - break; - } - return 1; -} - -static int final_check(unsigned int flags, - unsigned int command, - struct nfct_tuple *orig, - struct nfct_tuple *reply) -{ - int ret = 0; - - if ((flags & (TCP_ORIG_SPORT|TCP_ORIG_DPORT)) - && !(flags & (TCP_REPL_SPORT|TCP_REPL_DPORT))) { - reply->l4src.tcp.port = orig->l4dst.tcp.port; - reply->l4dst.tcp.port = orig->l4src.tcp.port; - ret = 1; - } else if (!(flags & (TCP_ORIG_SPORT|TCP_ORIG_DPORT)) - && (flags & (TCP_REPL_SPORT|TCP_REPL_DPORT))) { - orig->l4src.tcp.port = reply->l4dst.tcp.port; - orig->l4dst.tcp.port = reply->l4src.tcp.port; - ret = 1; - } - if ((flags & (TCP_ORIG_SPORT|TCP_ORIG_DPORT)) - && ((flags & (TCP_REPL_SPORT|TCP_REPL_DPORT)))) - ret = 1; - - /* --state is missing and we are trying to create a conntrack */ - if (ret && (command & CT_CREATE) && (!(flags & TCP_STATE))) - ret = 0; - - return ret; -} - -static struct ctproto_handler tcp = { - .name = "tcp", - .protonum = IPPROTO_TCP, - .parse_opts = parse_options, - .final_check = final_check, - .help = help, - .opts = opts, - .version = VERSION, -}; - -static void __attribute__ ((constructor)) init(void); - -static void init(void) -{ - register_proto(&tcp); -} diff --git a/cli/extensions/libct_proto_tcp.man b/cli/extensions/libct_proto_tcp.man deleted file mode 100644 index 41783f8..0000000 --- a/cli/extensions/libct_proto_tcp.man +++ /dev/null @@ -1,16 +0,0 @@ -This module matches on TCP-specific fields. -.TP -.BI "--orig-port-src " "PORT" -Source port in original direction -.TP -.BI "--orig-port-dst " "PORT" -Destination port in original direction -.TP -.BI "--reply-port-src " "PORT" -Source port in reply direction -.TP -.BI "--reply-port-dst " "PORT" -Destination port in reply direction -.TP -.BI "--state " "[NONE|SYN_SENT|SYN_RECV|ESTABLISHED|FIN_WAIT|CLOSE_WAIT|LAST_ACK|TIME_WAIT|CLOSE|LISTEN]" -TCP state diff --git a/cli/extensions/libct_proto_udp.c b/cli/extensions/libct_proto_udp.c deleted file mode 100644 index 48079e0..0000000 --- a/cli/extensions/libct_proto_udp.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * (C) 2005 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 -#include -#include -#include /* For htons */ -#include "conntrack.h" -#include -#include - -static struct option opts[] = { - {"orig-port-src", 1, 0, '1'}, - {"orig-port-dst", 1, 0, '2'}, - {"reply-port-src", 1, 0, '3'}, - {"reply-port-dst", 1, 0, '4'}, - {"mask-port-src", 1, 0, '5'}, - {"mask-port-dst", 1, 0, '6'}, - {"tuple-port-src", 1, 0, '7'}, - {"tuple-port-dst", 1, 0, '8'}, - {0, 0, 0, 0} -}; - -static void help() -{ - fprintf(stdout, "--orig-port-src original source port\n"); - fprintf(stdout, "--orig-port-dst original destination port\n"); - fprintf(stdout, "--reply-port-src reply source port\n"); - fprintf(stdout, "--reply-port-dst reply destination port\n"); - fprintf(stdout, "--mask-port-src mask source port\n"); - fprintf(stdout, "--mask-port-dst mask destination port\n"); - fprintf(stdout, "--tuple-port-src expectation tuple src port\n"); - fprintf(stdout, "--tuple-port-src expectation tuple dst port\n"); -} - -static int parse_options(char c, char *argv[], - struct nfct_tuple *orig, - struct nfct_tuple *reply, - struct nfct_tuple *exptuple, - struct nfct_tuple *mask, - union nfct_protoinfo *proto, - unsigned int *flags) -{ - switch(c) { - case '1': - if (optarg) { - orig->l4src.udp.port = htons(atoi(optarg)); - *flags |= UDP_ORIG_SPORT; - } - break; - case '2': - if (optarg) { - orig->l4dst.udp.port = htons(atoi(optarg)); - *flags |= UDP_ORIG_DPORT; - } - break; - case '3': - if (optarg) { - reply->l4src.udp.port = htons(atoi(optarg)); - *flags |= UDP_REPL_SPORT; - } - break; - case '4': - if (optarg) { - reply->l4dst.udp.port = htons(atoi(optarg)); - *flags |= UDP_REPL_DPORT; - } - break; - case '5': - if (optarg) { - mask->l4src.udp.port = htons(atoi(optarg)); - *flags |= UDP_MASK_SPORT; - } - break; - case '6': - if (optarg) { - mask->l4dst.udp.port = htons(atoi(optarg)); - *flags |= UDP_MASK_DPORT; - } - break; - case '7': - if (optarg) { - exptuple->l4src.udp.port = htons(atoi(optarg)); - *flags |= UDP_EXPTUPLE_SPORT; - } - break; - case '8': - if (optarg) { - exptuple->l4dst.udp.port = htons(atoi(optarg)); - *flags |= UDP_EXPTUPLE_DPORT; - } - - } - return 1; -} - -static int final_check(unsigned int flags, - unsigned int command, - struct nfct_tuple *orig, - struct nfct_tuple *reply) -{ - if ((flags & (UDP_ORIG_SPORT|UDP_ORIG_DPORT)) - && !(flags & (UDP_REPL_SPORT|UDP_REPL_DPORT))) { - reply->l4src.udp.port = orig->l4dst.udp.port; - reply->l4dst.udp.port = orig->l4src.udp.port; - return 1; - } else if (!(flags & (UDP_ORIG_SPORT|UDP_ORIG_DPORT)) - && (flags & (UDP_REPL_SPORT|UDP_REPL_DPORT))) { - orig->l4src.udp.port = reply->l4dst.udp.port; - orig->l4dst.udp.port = reply->l4src.udp.port; - return 1; - } - if ((flags & (UDP_ORIG_SPORT|UDP_ORIG_DPORT)) - && ((flags & (UDP_REPL_SPORT|UDP_REPL_DPORT)))) - return 1; - - return 0; -} - -static struct ctproto_handler udp = { - .name = "udp", - .protonum = IPPROTO_UDP, - .parse_opts = parse_options, - .final_check = final_check, - .help = help, - .opts = opts, - .version = VERSION, -}; - -static void __attribute__ ((constructor)) init(void); - -static void init(void) -{ - register_proto(&udp); -} diff --git a/cli/extensions/libct_proto_udp.man b/cli/extensions/libct_proto_udp.man deleted file mode 100644 index c67fedf..0000000 --- a/cli/extensions/libct_proto_udp.man +++ /dev/null @@ -1,13 +0,0 @@ -This module matches on UDP-specific fields. -.TP -.BI "--orig-port-src " "PORT" -Source port in original direction -.TP -.BI "--orig-port-dst " "PORT" -Destination port in original direction -.TP -.BI "--reply-port-src " "PORT" -Source port in reply direction -.TP -.BI "--reply-port-dst " "PORT" -Destination port in reply direction diff --git a/cli/include/conntrack.h b/cli/include/conntrack.h deleted file mode 100644 index fb3b9b6..0000000 --- a/cli/include/conntrack.h +++ /dev/null @@ -1,160 +0,0 @@ -#ifndef _CONNTRACK_H -#define _CONNTRACK_H - -#ifdef HAVE_CONFIG_H -#include "../config.h" -#endif - -#include "linux_list.h" -#include -#include - -#define PROGNAME "conntrack" - -#include -#ifndef IPPROTO_SCTP -#define IPPROTO_SCTP 132 -#endif - -enum action { - CT_NONE = 0, - - CT_LIST_BIT = 0, - CT_LIST = (1 << CT_LIST_BIT), - - CT_CREATE_BIT = 1, - CT_CREATE = (1 << CT_CREATE_BIT), - - CT_UPDATE_BIT = 2, - CT_UPDATE = (1 << CT_UPDATE_BIT), - - CT_DELETE_BIT = 3, - CT_DELETE = (1 << CT_DELETE_BIT), - - CT_GET_BIT = 4, - CT_GET = (1 << CT_GET_BIT), - - CT_FLUSH_BIT = 5, - CT_FLUSH = (1 << CT_FLUSH_BIT), - - CT_EVENT_BIT = 6, - CT_EVENT = (1 << CT_EVENT_BIT), - - CT_VERSION_BIT = 7, - CT_VERSION = (1 << CT_VERSION_BIT), - - CT_HELP_BIT = 8, - CT_HELP = (1 << CT_HELP_BIT), - - EXP_LIST_BIT = 9, - EXP_LIST = (1 << EXP_LIST_BIT), - - EXP_CREATE_BIT = 10, - EXP_CREATE = (1 << EXP_CREATE_BIT), - - EXP_DELETE_BIT = 11, - EXP_DELETE = (1 << EXP_DELETE_BIT), - - EXP_GET_BIT = 12, - EXP_GET = (1 << EXP_GET_BIT), - - EXP_FLUSH_BIT = 13, - EXP_FLUSH = (1 << EXP_FLUSH_BIT), - - EXP_EVENT_BIT = 14, - EXP_EVENT = (1 << EXP_EVENT_BIT), -}; -#define NUMBER_OF_CMD 15 - -enum options { - CT_OPT_ORIG_SRC_BIT = 0, - CT_OPT_ORIG_SRC = (1 << CT_OPT_ORIG_SRC_BIT), - - CT_OPT_ORIG_DST_BIT = 1, - CT_OPT_ORIG_DST = (1 << CT_OPT_ORIG_DST_BIT), - - CT_OPT_ORIG = (CT_OPT_ORIG_SRC | CT_OPT_ORIG_DST), - - CT_OPT_REPL_SRC_BIT = 2, - CT_OPT_REPL_SRC = (1 << CT_OPT_REPL_SRC_BIT), - - CT_OPT_REPL_DST_BIT = 3, - CT_OPT_REPL_DST = (1 << CT_OPT_REPL_DST_BIT), - - CT_OPT_REPL = (CT_OPT_REPL_SRC | CT_OPT_REPL_DST), - - CT_OPT_PROTO_BIT = 4, - CT_OPT_PROTO = (1 << CT_OPT_PROTO_BIT), - - CT_OPT_TIMEOUT_BIT = 5, - CT_OPT_TIMEOUT = (1 << CT_OPT_TIMEOUT_BIT), - - CT_OPT_STATUS_BIT = 6, - CT_OPT_STATUS = (1 << CT_OPT_STATUS_BIT), - - CT_OPT_ZERO_BIT = 7, - CT_OPT_ZERO = (1 << CT_OPT_ZERO_BIT), - - CT_OPT_EVENT_MASK_BIT = 8, - CT_OPT_EVENT_MASK = (1 << CT_OPT_EVENT_MASK_BIT), - - CT_OPT_EXP_SRC_BIT = 9, - CT_OPT_EXP_SRC = (1 << CT_OPT_EXP_SRC_BIT), - - CT_OPT_EXP_DST_BIT = 10, - CT_OPT_EXP_DST = (1 << CT_OPT_EXP_DST_BIT), - - CT_OPT_MASK_SRC_BIT = 11, - CT_OPT_MASK_SRC = (1 << CT_OPT_MASK_SRC_BIT), - - CT_OPT_MASK_DST_BIT = 12, - CT_OPT_MASK_DST = (1 << CT_OPT_MASK_DST_BIT), - - CT_OPT_NATRANGE_BIT = 13, - CT_OPT_NATRANGE = (1 << CT_OPT_NATRANGE_BIT), - - CT_OPT_MARK_BIT = 14, - CT_OPT_MARK = (1 << CT_OPT_MARK_BIT), - - CT_OPT_ID_BIT = 15, - CT_OPT_ID = (1 << CT_OPT_ID_BIT), - - CT_OPT_FAMILY_BIT = 16, - CT_OPT_FAMILY = (1 << CT_OPT_FAMILY_BIT), - - CT_OPT_MAX_BIT = CT_OPT_FAMILY_BIT -}; -#define NUMBER_OF_OPT CT_OPT_MAX_BIT+1 - -struct ctproto_handler { - struct list_head head; - - char *name; - u_int16_t protonum; - char *version; - - enum ctattr_protoinfo protoinfo_attr; - - int (*parse_opts)(char c, char *argv[], - struct nfct_tuple *orig, - struct nfct_tuple *reply, - struct nfct_tuple *exptuple, - struct nfct_tuple *mask, - union nfct_protoinfo *proto, - unsigned int *flags); - - int (*final_check)(unsigned int flags, - unsigned int command, - struct nfct_tuple *orig, - struct nfct_tuple *reply); - - void (*help)(); - - struct option *opts; - - unsigned int option_offset; -}; - -extern void register_proto(struct ctproto_handler *h); - -#endif diff --git a/cli/src/conntrack.c b/cli/src/conntrack.c deleted file mode 100644 index 30fbf69..0000000 --- a/cli/src/conntrack.c +++ /dev/null @@ -1,1131 +0,0 @@ -/* - * (C) 2005 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. - * - * Note: - * Yes, portions of this code has been stolen from iptables ;) - * Special thanks to the the Netfilter Core Team. - * Thanks to Javier de Miguel Rodriguez - * for introducing me to advanced firewalling stuff. - * - * --pablo 13/04/2005 - * - * 2005-04-16 Harald Welte : - * Add support for conntrack accounting and conntrack mark - * 2005-06-23 Harald Welte : - * Add support for expect creation - * 2005-09-24 Harald Welte : - * Remove remaints of "-A" - * - */ -#include -#include -#include -#include -#include -#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'}; - -static const char cmd_need_param[NUMBER_OF_CMD] -= { 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2 }; - -static const char optflags[NUMBER_OF_OPT] -= {'s','d','r','q','p','t','u','z','e','[',']','{','}','a','m','i','f'}; - -static struct option original_opts[] = { - {"dump", 2, 0, 'L'}, - {"create", 1, 0, 'I'}, - {"delete", 1, 0, 'D'}, - {"update", 1, 0, 'U'}, - {"get", 1, 0, 'G'}, - {"flush", 1, 0, 'F'}, - {"event", 1, 0, 'E'}, - {"version", 0, 0, 'V'}, - {"help", 0, 0, 'h'}, - {"orig-src", 1, 0, 's'}, - {"orig-dst", 1, 0, 'd'}, - {"reply-src", 1, 0, 'r'}, - {"reply-dst", 1, 0, 'q'}, - {"protonum", 1, 0, 'p'}, - {"timeout", 1, 0, 't'}, - {"status", 1, 0, 'u'}, - {"zero", 0, 0, 'z'}, - {"event-mask", 1, 0, 'e'}, - {"tuple-src", 1, 0, '['}, - {"tuple-dst", 1, 0, ']'}, - {"mask-src", 1, 0, '{'}, - {"mask-dst", 1, 0, '}'}, - {"nat-range", 1, 0, 'a'}, - {"mark", 1, 0, 'm'}, - {"id", 2, 0, 'i'}, - {"family", 1, 0, 'f'}, - {0, 0, 0, 0} -}; - -#define OPTION_OFFSET 256 - -static struct nfct_handle *cth; -static struct option *opts = original_opts; -static unsigned int global_option_offset = 0; - -/* Table of legal combinations of commands and options. If any of the - * given commands make an option legal, that option is legal (applies to - * CMD_LIST and CMD_ZERO only). - * Key: - * 0 illegal - * 1 compulsory - * 2 optional - */ - -static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = -/* Well, it's better than "Re: Linux vs FreeBSD" */ -{ - /* s d r q p t u z e x y k l a m i f*/ -/*CT_LIST*/ {2,2,2,2,2,0,0,2,0,0,0,0,0,0,2,2,2}, -/*CT_CREATE*/ {2,2,2,2,1,1,1,0,0,0,0,0,0,2,2,0,0}, -/*CT_UPDATE*/ {2,2,2,2,1,2,2,0,0,0,0,0,0,0,2,2,0}, -/*CT_DELETE*/ {2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,0}, -/*CT_GET*/ {2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,2,0}, -/*CT_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*CT_EVENT*/ {2,2,2,2,2,0,0,0,2,0,0,0,0,0,2,0,0}, -/*VERSION*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*HELP*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_LIST*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2}, -/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0}, -/*EXP_DELETE*/{1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_GET*/ {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -}; - -static char *lib_dir = CONNTRACK_LIB_DIR; - -static LIST_HEAD(proto_list); - -void register_proto(struct ctproto_handler *h) -{ - if (strcmp(h->version, VERSION) != 0) { - fprintf(stderr, "plugin `%s': version %s (I'm %s)\n", - h->name, h->version, VERSION); - exit(1); - } - list_add(&h->head, &proto_list); -} - -static struct ctproto_handler *findproto(char *name) -{ - struct list_head *i; - struct ctproto_handler *cur = NULL, *handler = NULL; - - if (!name) - return handler; - - lib_dir = getenv("CONNTRACK_LIB_DIR"); - if (!lib_dir) - lib_dir = CONNTRACK_LIB_DIR; - - list_for_each(i, &proto_list) { - cur = (struct ctproto_handler *) i; - if (strcmp(cur->name, name) == 0) { - handler = cur; - break; - } - } - - if (!handler) { - char path[sizeof("ct_proto_.so") - + strlen(name) + strlen(lib_dir)]; - sprintf(path, "%s/ct_proto_%s.so", lib_dir, name); - if (dlopen(path, RTLD_NOW)) - handler = findproto(name); - else - fprintf(stderr, "%s\n", dlerror()); - } - - return handler; -} - -enum exittype { - OTHER_PROBLEM = 1, - PARAMETER_PROBLEM, - VERSION_PROBLEM -}; - -void extension_help(struct ctproto_handler *h) -{ - fprintf(stdout, "\n"); - fprintf(stdout, "Proto `%s' help:\n", h->name); - h->help(); -} - -void -exit_tryhelp(int status) -{ - fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n", - PROGNAME, PROGNAME); - exit(status); -} - -static void -exit_error(enum exittype status, char *msg, ...) -{ - va_list args; - - /* On error paths, make sure that we don't leak the memory - * reserved during options merging */ - if (opts != original_opts) { - free(opts); - opts = original_opts; - global_option_offset = 0; - } - va_start(args, msg); - fprintf(stderr,"%s v%s: ", PROGNAME, VERSION); - vfprintf(stderr, msg, args); - va_end(args); - fprintf(stderr, "\n"); - if (status == PARAMETER_PROBLEM) - exit_tryhelp(status); - exit(status); -} - -static void -generic_cmd_check(int command, int options) -{ - int i; - - for (i = 0; i < NUMBER_OF_CMD; i++) { - if (!(command & (1< illegal, 1 => legal, 0 => undecided. */ - - for (j = 0; j < NUMBER_OF_CMD; j++) { - if (!(command & (1<size; i++) - if (strncasecmp(str, p->parameter[i], strlen) == 0) { - *value |= p->value[i]; - ret = 1; - break; - } - - return ret; -} - -static void -parse_parameter(const char *arg, unsigned int *status, int parse_type) -{ - const char *comma; - - while ((comma = strchr(arg, ',')) != NULL) { - if (comma == arg - || !do_parse_parameter(arg, comma-arg, status, parse_type)) - exit_error(PARAMETER_PROBLEM,"Bad parameter `%s'", arg); - arg = comma+1; - } - - if (strlen(arg) == 0 - || !do_parse_parameter(arg, strlen(arg), status, parse_type)) - exit_error(PARAMETER_PROBLEM, "Bad parameter `%s'", arg); -} - -static void -add_command(unsigned int *cmd, const int newcmd, const int othercmds) -{ - if (*cmd & (~othercmds)) - exit_error(PARAMETER_PROBLEM, "Invalid commands combination\n"); - *cmd |= newcmd; -} - -unsigned int check_type(int argc, char *argv[]) -{ - char *table = NULL; - - /* Nasty bug or feature in getopt_long ? - * It seems that it behaves badly with optional arguments. - * Fortunately, I just stole the fix from iptables ;) */ - if (optarg) - return 0; - else if (optind < argc && argv[optind][0] != '-' - && argv[optind][0] != '!') - table = argv[optind++]; - - if (!table) - return 0; - - if (strncmp("expect", table, 6) == 0) - return 1; - else if (strncmp("conntrack", table, 9) == 0) - return 0; - else - exit_error(PARAMETER_PROBLEM, "unknown type `%s'\n", table); - - return 0; -} - -static void set_family(int *family, int new) -{ - if (*family == AF_UNSPEC) - *family = new; - else if (*family != new) - exit_error(PARAMETER_PROBLEM, "mismatched address family\n"); -} - -struct addr_parse { - struct in_addr addr; - struct in6_addr addr6; - unsigned int family; -}; - -int __parse_inetaddr(const char *cp, struct addr_parse *parse) -{ - if (inet_aton(cp, &parse->addr)) - return AF_INET; -#ifdef HAVE_INET_PTON_IPV6 - else if (inet_pton(AF_INET6, cp, &parse->addr6) > 0) - return AF_INET6; -#endif - - exit_error(PARAMETER_PROBLEM, "Invalid IP address `%s'.", cp); -} - -int parse_inetaddr(const char *cp, union nfct_address *address) -{ - struct addr_parse parse; - int ret; - - if ((ret = __parse_inetaddr(cp, &parse)) == AF_INET) - address->v4 = parse.addr.s_addr; - else if (ret == AF_INET6) - memcpy(address->v6, &parse.addr6, sizeof(parse.addr6)); - - return ret; -} - -/* Shamelessly stolen from libipt_DNAT ;). Ranges expected in network order. */ -static void -nat_parse(char *arg, int portok, struct nfct_nat *range) -{ - char *colon, *dash, *error; - struct addr_parse parse; - - memset(range, 0, sizeof(range)); - colon = strchr(arg, ':'); - - if (colon) { - int port; - - if (!portok) - exit_error(PARAMETER_PROBLEM, - "Need TCP or UDP with port specification"); - - port = atoi(colon+1); - if (port == 0 || port > 65535) - exit_error(PARAMETER_PROBLEM, - "Port `%s' not valid\n", colon+1); - - error = strchr(colon+1, ':'); - if (error) - exit_error(PARAMETER_PROBLEM, - "Invalid port:port syntax - use dash\n"); - - dash = strchr(colon, '-'); - if (!dash) { - range->l4min.tcp.port - = range->l4max.tcp.port - = htons(port); - } else { - int maxport; - - maxport = atoi(dash + 1); - if (maxport == 0 || maxport > 65535) - exit_error(PARAMETER_PROBLEM, - "Port `%s' not valid\n", dash+1); - if (maxport < port) - /* People are stupid. */ - exit_error(PARAMETER_PROBLEM, - "Port range `%s' funky\n", colon+1); - range->l4min.tcp.port = htons(port); - range->l4max.tcp.port = htons(maxport); - } - /* Starts with a colon? No IP info... */ - if (colon == arg) - return; - *colon = '\0'; - } - - dash = strchr(arg, '-'); - if (colon && dash && dash > colon) - dash = NULL; - - if (dash) - *dash = '\0'; - - if (__parse_inetaddr(arg, &parse) != AF_INET) - return; - - range->min_ip = parse.addr.s_addr; - if (dash) { - if (__parse_inetaddr(dash+1, &parse) != AF_INET) - return; - range->max_ip = parse.addr.s_addr; - } else - range->max_ip = parse.addr.s_addr; -} - -static void event_sighandler(int s) -{ - fprintf(stdout, "Now closing conntrack event dumping...\n"); - nfct_close(cth); - exit(0); -} - -static const char usage_commands[] = - "Commands:\n" - " -L [table] [options]\t\tList conntrack or expectation table\n" - " -G [table] parameters\t\tGet conntrack or expectation\n" - " -D [table] parameters\t\tDelete conntrack or expectation\n" - " -I [table] parameters\t\tCreate a conntrack or expectation\n" - " -U [table] parameters\t\tUpdate a conntrack\n" - " -E [table] [options]\t\tShow events\n" - " -F [table]\t\t\tFlush table\n"; - -static const char usage_tables[] = - "Tables: conntrack, expect\n"; - -static const char usage_conntrack_parameters[] = - "Conntrack parameters and options:\n" - " -a, --nat-range min_ip[-max_ip]\tNAT ip range\n" - " -m, --mark mark\t\t\tSet mark\n" - " -e, --event-mask eventmask\t\tEvent mask, eg. NEW,DESTROY\n" - " -z, --zero \t\t\t\tZero counters while listing\n" - ; - -static const char usage_expectation_parameters[] = - "Expectation parameters and options:\n" - " --tuple-src ip\tSource address in expect tuple\n" - " --tuple-dst ip\tDestination address in expect tuple\n" - " --mask-src ip\t\tSource mask address\n" - " --mask-dst ip\t\tDestination mask address\n"; - -static const char usage_parameters[] = - "Common parameters and options:\n" - " -s, --orig-src ip\t\tSource address from original direction\n" - " -d, --orig-dst ip\t\tDestination address from original direction\n" - " -r, --reply-src ip\t\tSource addres from reply direction\n" - " -q, --reply-dst ip\t\tDestination address from reply direction\n" - " -p, --protonum proto\t\tLayer 4 Protocol, eg. 'tcp'\n" - " -f, --family proto\t\tLayer 3 Protocol, eg. 'ipv6'\n" - " -t, --timeout timeout\t\tSet timeout\n" - " -u, --status status\t\tSet status, eg. ASSURED\n" - " -i, --id [id]\t\t\tShow or set conntrack ID\n" - ; - - -void usage(char *prog) { - fprintf(stdout, "Tool to manipulate conntrack and expectations. Version %s\n", VERSION); - fprintf(stdout, "Usage: %s [commands] [options]\n", prog); - - fprintf(stdout, "\n%s", usage_commands); - fprintf(stdout, "\n%s", usage_tables); - fprintf(stdout, "\n%s", usage_conntrack_parameters); - fprintf(stdout, "\n%s", usage_expectation_parameters); - fprintf(stdout, "\n%s", usage_parameters); -} - -#define CT_COMPARISON (CT_OPT_PROTO | CT_OPT_ORIG | CT_OPT_REPL | CT_OPT_MARK) - -static struct nfct_tuple orig, reply, mask; -static struct nfct_tuple exptuple; -static struct ctproto_handler *h; -static union nfct_protoinfo proto; -static struct nfct_nat range; -static struct nfct_conntrack *ct; -static struct nfct_expect *exp; -static unsigned long timeout; -static unsigned int status; -static unsigned int mark; -static unsigned int id = NFCT_ANY_ID; -static struct nfct_conntrack_compare cmp; - -int main(int argc, char *argv[]) -{ - int c; - unsigned int command = 0, options = 0; - unsigned int type = 0, event_mask = 0; - unsigned int l3flags = 0, l4flags = 0, metaflags = 0; - int res = 0; - int family = AF_UNSPEC; - struct nfct_conntrack_compare *pcmp; - - while ((c = getopt_long(argc, argv, - "L::I::U::D::G::E::F::hVs:d:r:q:p:t:u:e:a:z[:]:{:}:m:i::f:", - opts, NULL)) != -1) { - switch(c) { - case 'L': - type = check_type(argc, argv); - if (type == 0) - add_command(&command, CT_LIST, CT_NONE); - else if (type == 1) - add_command(&command, EXP_LIST, CT_NONE); - break; - case 'I': - type = check_type(argc, argv); - if (type == 0) - add_command(&command, CT_CREATE, CT_NONE); - else if (type == 1) - add_command(&command, EXP_CREATE, CT_NONE); - break; - case 'U': - type = check_type(argc, argv); - if (type == 0) - add_command(&command, CT_UPDATE, CT_NONE); - else - exit_error(PARAMETER_PROBLEM, "Can't update " - "expectations"); - break; - case 'D': - type = check_type(argc, argv); - if (type == 0) - add_command(&command, CT_DELETE, CT_NONE); - else if (type == 1) - add_command(&command, EXP_DELETE, CT_NONE); - break; - case 'G': - type = check_type(argc, argv); - if (type == 0) - add_command(&command, CT_GET, CT_NONE); - else if (type == 1) - add_command(&command, EXP_GET, CT_NONE); - break; - case 'F': - type = check_type(argc, argv); - if (type == 0) - add_command(&command, CT_FLUSH, CT_NONE); - else if (type == 1) - add_command(&command, EXP_FLUSH, CT_NONE); - break; - case 'E': - type = check_type(argc, argv); - if (type == 0) - add_command(&command, CT_EVENT, CT_NONE); - else if (type == 1) - add_command(&command, EXP_EVENT, CT_NONE); - break; - case 'V': - add_command(&command, CT_VERSION, CT_NONE); - break; - case 'h': - add_command(&command, CT_HELP, CT_NONE); - break; - case 's': - options |= CT_OPT_ORIG_SRC; - if (optarg) { - orig.l3protonum = - parse_inetaddr(optarg, &orig.src); - set_family(&family, orig.l3protonum); - if (orig.l3protonum == AF_INET) - l3flags |= IPV4_ORIG_SRC; - else if (orig.l3protonum == AF_INET6) - l3flags |= IPV6_ORIG_SRC; - } - break; - case 'd': - options |= CT_OPT_ORIG_DST; - if (optarg) { - orig.l3protonum = - parse_inetaddr(optarg, &orig.dst); - set_family(&family, orig.l3protonum); - if (orig.l3protonum == AF_INET) - l3flags |= IPV4_ORIG_DST; - else if (orig.l3protonum == AF_INET6) - l3flags |= IPV6_ORIG_DST; - } - break; - case 'r': - options |= CT_OPT_REPL_SRC; - if (optarg) { - reply.l3protonum = - parse_inetaddr(optarg, &reply.src); - set_family(&family, reply.l3protonum); - if (orig.l3protonum == AF_INET) - l3flags |= IPV4_REPL_SRC; - else if (orig.l3protonum == AF_INET6) - l3flags |= IPV6_REPL_SRC; - } - break; - case 'q': - options |= CT_OPT_REPL_DST; - if (optarg) { - reply.l3protonum = - parse_inetaddr(optarg, &reply.dst); - set_family(&family, reply.l3protonum); - if (orig.l3protonum == AF_INET) - l3flags |= IPV4_REPL_DST; - else if (orig.l3protonum == AF_INET6) - l3flags |= IPV6_REPL_DST; - } - break; - case 'p': - options |= CT_OPT_PROTO; - h = findproto(optarg); - if (!h) - exit_error(PARAMETER_PROBLEM, "proto needed\n"); - orig.protonum = h->protonum; - reply.protonum = h->protonum; - exptuple.protonum = h->protonum; - mask.protonum = h->protonum; - opts = merge_options(opts, h->opts, - &h->option_offset); - break; - case 't': - options |= CT_OPT_TIMEOUT; - if (optarg) - timeout = atol(optarg); - break; - case 'u': { - if (!optarg) - continue; - - options |= CT_OPT_STATUS; - parse_parameter(optarg, &status, PARSE_STATUS); - break; - } - case 'e': - options |= CT_OPT_EVENT_MASK; - parse_parameter(optarg, &event_mask, PARSE_EVENT); - break; - case 'z': - options |= CT_OPT_ZERO; - break; - case '{': - options |= CT_OPT_MASK_SRC; - if (optarg) { - mask.l3protonum = - parse_inetaddr(optarg, &mask.src); - set_family(&family, mask.l3protonum); - } - break; - case '}': - options |= CT_OPT_MASK_DST; - if (optarg) { - mask.l3protonum = - parse_inetaddr(optarg, &mask.dst); - set_family(&family, mask.l3protonum); - } - break; - case '[': - options |= CT_OPT_EXP_SRC; - if (optarg) { - exptuple.l3protonum = - parse_inetaddr(optarg, &exptuple.src); - set_family(&family, exptuple.l3protonum); - } - break; - case ']': - options |= CT_OPT_EXP_DST; - if (optarg) { - exptuple.l3protonum = - parse_inetaddr(optarg, &exptuple.dst); - set_family(&family, exptuple.l3protonum); - } - break; - case 'a': - options |= CT_OPT_NATRANGE; - set_family(&family, AF_INET); - nat_parse(optarg, 1, &range); - break; - case 'm': - options |= CT_OPT_MARK; - mark = atol(optarg); - metaflags |= NFCT_MARK; - break; - case 'i': { - char *s = NULL; - options |= CT_OPT_ID; - if (optarg) - break; - else if (optind < argc && argv[optind][0] != '-' - && argv[optind][0] != '!') - s = argv[optind++]; - - if (s) - id = atol(s); - break; - } - case 'f': - options |= CT_OPT_FAMILY; - if (strncmp(optarg, "ipv4", strlen("ipv4")) == 0) - set_family(&family, AF_INET); - else if (strncmp(optarg, "ipv6", strlen("ipv6")) == 0) - set_family(&family, AF_INET6); - else - exit_error(PARAMETER_PROBLEM, "Unknown " - "protocol family\n"); - break; - default: - if (h && h->parse_opts - &&!h->parse_opts(c - h->option_offset, argv, &orig, - &reply, &exptuple, &mask, &proto, - &l4flags)) - exit_error(PARAMETER_PROBLEM, "parse error\n"); - - /* Unknown argument... */ - if (!h) { - usage(argv[0]); - exit_error(PARAMETER_PROBLEM, "Missing " - "arguments...\n"); - } - break; - } - } - - /* default family */ - if (family == AF_UNSPEC) - family = AF_INET; - - generic_cmd_check(command, options); - generic_opt_check(command, options); - - if (!(command & CT_HELP) - && h && h->final_check - && !h->final_check(l4flags, command, &orig, &reply)) { - usage(argv[0]); - extension_help(h); - exit_error(PARAMETER_PROBLEM, "Missing protocol arguments!\n"); - } - - switch(command) { - - case CT_LIST: - cth = nfct_open(CONNTRACK, 0); - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - - if (options & CT_COMPARISON) { - - if (options & CT_OPT_ZERO) - exit_error(PARAMETER_PROBLEM, "Can't use -z " - "with filtering parameters"); - - ct = nfct_conntrack_alloc(&orig, &reply, timeout, - &proto, status, mark, id, - NULL); - if (!ct) - exit_error(OTHER_PROBLEM, "Not enough memory"); - - cmp.ct = ct; - cmp.flags = metaflags; - cmp.l3flags = l3flags; - cmp.l4flags = l4flags; - pcmp = &cmp; - } - - if (options & CT_OPT_ID) - nfct_register_callback(cth, - nfct_default_conntrack_display_id, - (void *) pcmp); - else - nfct_register_callback(cth, - nfct_default_conntrack_display, - (void *) pcmp); - - if (options & CT_OPT_ZERO) - res = - nfct_dump_conntrack_table_reset_counters(cth, family); - else - res = nfct_dump_conntrack_table(cth, family); - nfct_close(cth); - break; - - case EXP_LIST: - cth = nfct_open(EXPECT, 0); - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - if (options & CT_OPT_ID) - nfct_register_callback(cth, - nfct_default_expect_display_id, - NULL); - else - nfct_register_callback(cth, - nfct_default_expect_display, - NULL); - res = nfct_dump_expect_list(cth, family); - nfct_close(cth); - break; - - case CT_CREATE: - if ((options & CT_OPT_ORIG) - && !(options & CT_OPT_REPL)) { - reply.l3protonum = orig.l3protonum; - memcpy(&reply.src, &orig.dst, sizeof(reply.src)); - memcpy(&reply.dst, &orig.src, sizeof(reply.dst)); - } else if (!(options & CT_OPT_ORIG) - && (options & CT_OPT_REPL)) { - orig.l3protonum = reply.l3protonum; - memcpy(&orig.src, &reply.dst, sizeof(orig.src)); - memcpy(&orig.dst, &reply.src, sizeof(orig.dst)); - } - if (options & CT_OPT_NATRANGE) - ct = nfct_conntrack_alloc(&orig, &reply, timeout, - &proto, status, mark, id, - &range); - else - ct = nfct_conntrack_alloc(&orig, &reply, timeout, - &proto, status, mark, id, - NULL); - if (!ct) - exit_error(OTHER_PROBLEM, "Not Enough memory"); - - cth = nfct_open(CONNTRACK, 0); - if (!cth) { - nfct_conntrack_free(ct); - exit_error(OTHER_PROBLEM, "Can't open handler"); - } - res = nfct_create_conntrack(cth, ct); - nfct_close(cth); - nfct_conntrack_free(ct); - break; - - case EXP_CREATE: - if (options & CT_OPT_ORIG) - exp = nfct_expect_alloc(&orig, &exptuple, - &mask, timeout, id); - else if (options & CT_OPT_REPL) - exp = nfct_expect_alloc(&reply, &exptuple, - &mask, timeout, id); - if (!exp) - exit_error(OTHER_PROBLEM, "Not enough memory"); - - cth = nfct_open(EXPECT, 0); - if (!cth) { - nfct_expect_free(exp); - exit_error(OTHER_PROBLEM, "Can't open handler"); - } - res = nfct_create_expectation(cth, exp); - nfct_expect_free(exp); - nfct_close(cth); - break; - - case CT_UPDATE: - if ((options & CT_OPT_ORIG) - && !(options & CT_OPT_REPL)) { - reply.l3protonum = orig.l3protonum; - memcpy(&reply.src, &orig.dst, sizeof(reply.src)); - memcpy(&reply.dst, &orig.src, sizeof(reply.dst)); - } else if (!(options & CT_OPT_ORIG) - && (options & CT_OPT_REPL)) { - orig.l3protonum = reply.l3protonum; - memcpy(&orig.src, &reply.dst, sizeof(orig.src)); - memcpy(&orig.dst, &reply.src, sizeof(orig.dst)); - } - ct = nfct_conntrack_alloc(&orig, &reply, timeout, - &proto, status, mark, id, - NULL); - if (!ct) - exit_error(OTHER_PROBLEM, "Not enough memory"); - - cth = nfct_open(CONNTRACK, 0); - if (!cth) { - nfct_conntrack_free(ct); - exit_error(OTHER_PROBLEM, "Can't open handler"); - } - res = nfct_update_conntrack(cth, ct); - nfct_conntrack_free(ct); - nfct_close(cth); - break; - - case CT_DELETE: - if (!(options & CT_OPT_ORIG) && !(options & CT_OPT_REPL)) - exit_error(PARAMETER_PROBLEM, "Can't kill conntracks " - "just by its ID"); - cth = nfct_open(CONNTRACK, 0); - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - if (options & CT_OPT_ORIG) - res = nfct_delete_conntrack(cth, &orig, - NFCT_DIR_ORIGINAL, - id); - else if (options & CT_OPT_REPL) - res = nfct_delete_conntrack(cth, &reply, - NFCT_DIR_REPLY, - id); - nfct_close(cth); - break; - - case EXP_DELETE: - cth = nfct_open(EXPECT, 0); - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - if (options & CT_OPT_ORIG) - res = nfct_delete_expectation(cth, &orig, id); - else if (options & CT_OPT_REPL) - res = nfct_delete_expectation(cth, &reply, id); - nfct_close(cth); - break; - - case CT_GET: - cth = nfct_open(CONNTRACK, 0); - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - nfct_register_callback(cth, nfct_default_conntrack_display, - NULL); - if (options & CT_OPT_ORIG) - res = nfct_get_conntrack(cth, &orig, - NFCT_DIR_ORIGINAL, id); - else if (options & CT_OPT_REPL) - res = nfct_get_conntrack(cth, &reply, - NFCT_DIR_REPLY, id); - nfct_close(cth); - break; - - case EXP_GET: - cth = nfct_open(EXPECT, 0); - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - nfct_register_callback(cth, nfct_default_expect_display, - NULL); - if (options & CT_OPT_ORIG) - res = nfct_get_expectation(cth, &orig, id); - else if (options & CT_OPT_REPL) - res = nfct_get_expectation(cth, &reply, id); - nfct_close(cth); - break; - - case CT_FLUSH: - cth = nfct_open(CONNTRACK, 0); - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - res = nfct_flush_conntrack_table(cth, AF_INET); - nfct_close(cth); - break; - - case EXP_FLUSH: - cth = nfct_open(EXPECT, 0); - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - res = nfct_flush_expectation_table(cth, AF_INET); - nfct_close(cth); - break; - - case CT_EVENT: - if (options & CT_OPT_EVENT_MASK) - cth = nfct_open(CONNTRACK, event_mask); - else - cth = nfct_open(CONNTRACK, NFCT_ALL_CT_GROUPS); - - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - signal(SIGINT, event_sighandler); - - if (options & CT_COMPARISON) { - ct = nfct_conntrack_alloc(&orig, &reply, timeout, - &proto, status, mark, id, - NULL); - if (!ct) - exit_error(OTHER_PROBLEM, "Not enough memory"); - - cmp.ct = ct; - cmp.flags = metaflags; - cmp.l3flags = l3flags; - cmp.l4flags = l4flags; - pcmp = &cmp; - } - - nfct_register_callback(cth, - nfct_default_conntrack_event_display, - (void *) pcmp); - res = nfct_event_conntrack(cth); - nfct_close(cth); - break; - - case EXP_EVENT: - cth = nfct_open(EXPECT, NF_NETLINK_CONNTRACK_EXP_NEW); - if (!cth) - exit_error(OTHER_PROBLEM, "Can't open handler"); - signal(SIGINT, event_sighandler); - nfct_register_callback(cth, nfct_default_expect_display, - NULL); - res = nfct_event_expectation(cth); - nfct_close(cth); - break; - - case CT_VERSION: - fprintf(stdout, "%s v%s\n", PROGNAME, VERSION); - break; - case CT_HELP: - usage(argv[0]); - if (options & CT_OPT_PROTO) - extension_help(h); - break; - default: - usage(argv[0]); - break; - } - - if (opts != original_opts) { - free(opts); - opts = original_opts; - global_option_offset = 0; - } - - if (res < 0) { - fprintf(stderr, "Operation failed: %s\n", err2str(res, command)); - exit(OTHER_PROBLEM); - } - - return 0; -} diff --git a/cli/test.sh b/cli/test.sh deleted file mode 100644 index 4694236..0000000 --- a/cli/test.sh +++ /dev/null @@ -1,110 +0,0 @@ -CONNTRACK=conntrack - -SRC=1.1.1.1 -DST=2.2.2.2 -SPORT=2005 -DPORT=21 - -case $1 in - dump) - echo "Dumping conntrack table" - $CONNTRACK -L - ;; - flush) - echo "Flushing conntrack table" - $CONNTRACK -F - ;; - new) - echo "creating a new conntrack" - $CONNTRACK -I --orig-src $SRC --orig-dst $DST \ - --reply-src $DST --reply-dst $SRC -p tcp \ - --orig-port-src $SPORT --orig-port-dst $DPORT \ - --reply-port-src $DPORT --reply-port-dst $SPORT \ - --state LISTEN -u SEEN_REPLY -t 50 - ;; - new-simple) - echo "creating a new conntrack (simplified)" - $CONNTRACK -I --orig-src $SRC --orig-dst $DST \ - -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \ - --state LISTEN -u SEEN_REPLY -t 50 - ;; - new-nat) - echo "creating a new conntrack (NAT)" - $CONNTRACK -I --orig-src $SRC --orig-dst $DST \ - -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \ - --state LISTEN -u SEEN_REPLY,SRC_NAT -t 50 -a 8.8.8.8 - ;; - get) - echo "getting a conntrack" - $CONNTRACK -G --orig-src $SRC --orig-dst $DST \ - -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \ - --reply-port-src $DPORT --reply-port-dst $SPORT - ;; - change) - echo "change a conntrack" - $CONNTRACK -U --orig-src $SRC --orig-dst $DST \ - --reply-src $DST --reply-dst $SRC -p tcp \ - --orig-port-src $SPORT --orig-port-dst $DPORT \ - --reply-port-src $DPORT --reply-port-dst $SPORT \ - --state TIME_WAIT -u ASSURED,SEEN_REPLY -t 500 - ;; - delete) - $CONNTRACK -D --orig-src $SRC --orig-dst $DST \ - -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT - ;; - output) - proc=$(cat /proc/net/ip_conntrack | wc -l) - netl=$($CONNTRACK -L | wc -l) - count=$(cat /proc/sys/net/ipv4/netfilter/ip_conntrack_count) - if [ $proc -ne $netl ]; then - echo "proc is $proc and netl is $netl and count is $count" - else - if [ $proc -ne $count ]; then - echo "proc is $proc and netl is $netl and count is $count" - else - echo "now $proc" - fi - fi - ;; - dump-expect) - $CONNTRACK -L expect - ;; - flush-expect) - $CONNTRACK -F expect - ;; - create-expect) - # requires modprobe ip_conntrack_ftp - $CONNTRACK -I expect --orig-src $SRC --orig-dst $DST \ - --tuple-src 4.4.4.4 --tuple-dst 5.5.5.5 \ - --mask-src 255.255.255.0 --mask-dst 255.255.255.255 \ - -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \ - -t 200 --tuple-port-src 10 --tuple-port-dst 300 \ - --mask-port-src 10 --mask-port-dst 300 - ;; - get-expect) - $CONNTRACK -G expect --orig-src 4.4.4.4 --orig-dst 5.5.5.5 \ - --p tcp --orig-port-src 0 --orig-port-dst 0 \ - --mask-port-src 10 --mask-port-dst 11 - ;; - delete-expect) - $CONNTRACK -D expect --orig-src 4.4.4.4 \ - --orig-dst 5.5.5.5 -p tcp --orig-port-src 0 \ - --orig-port-dst 0 --mask-port-src 10 --mask-port-dst 11 - ;; - *) - echo "Usage: $0 [dump" - echo " |new" - echo " |new-simple" - echo " |new-nat" - echo " |get" - echo " |change" - echo " |delete" - echo " |output" - echo " |flush" - echo " |dump-expect" - echo " |flush-expect" - echo " |create-expect" - echo " |get-expect" - echo " |delete-expect]" - ;; -esac diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..5bd9815 --- /dev/null +++ b/configure.in @@ -0,0 +1,106 @@ +AC_INIT(conntrackd, 0.9.2, pablo@netfilter.org) + +AC_CANONICAL_SYSTEM + +AM_INIT_AUTOMAKE + +AC_PROG_CC +AM_PROG_LIBTOOL +AC_PROG_INSTALL +AC_PROG_LN_S +AM_PROG_LEX +AC_PROG_YACC + +case $target in +*-*-linux*) ;; +*) AC_MSG_ERROR([Linux only, dude!]);; +esac + +AC_CHECK_PROGS(XYACC,$YACC bison yacc,none) +if test "$XYACC" = "none" +then + echo "*** Error: No suitable bison/yacc found. ***" + echo " Please install the 'bison' package." + exit 1 +fi +AC_CHECK_PROGS(XLEX,$LEX flex lex,none) +if test "$XLEX" = "none" +then + echo "*** Error: No suitable bison/yacc found. ***" + echo " Please install the 'bison' package." + exit 1 +fi + +AC_CHECK_HEADERS([linux/capability.h],, [AC_MSG_ERROR([Cannot find linux/capabibility.h])]) + +# Checks for libraries. +# FIXME: Replace `main' with a function in `-lc': +dnl AC_CHECK_LIB([c], [main]) +# FIXME: Replace `main' with a function in `-ldl': + +AC_CHECK_LIB([nfnetlink], [nfnl_talk] ,,,[-lnfnetlink]) +AC_CHECK_LIB([netfilter_conntrack], [nfct_dump_conntrack_table] ,,,[-lnetfilter_conntrack]) +AC_CHECK_LIB([pthread], [pthread_create] ,,,[-lpthread]) + +AC_CHECK_HEADERS(arpa/inet.h) +dnl check for inet_pton +AC_CHECK_FUNCS(inet_pton) +dnl Some systems have it, but not IPv6 +if test "$ac_cv_func_inet_pton" = "yes" ; then +AC_MSG_CHECKING(if inet_pton supports IPv6) +AC_TRY_RUN( + [ +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +int main() + { + struct in6_addr addr6; + if (inet_pton(AF_INET6, "::1", &addr6) < 1) + exit(1); + else + exit(0); + } + ], [ AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED(HAVE_INET_PTON_IPV6, 1, [Define to 1 if inet_pton supports IPv6.]) + ], AC_MSG_RESULT(no), AC_MSG_RESULT(no)) +fi + +# Checks for header files. +dnl AC_HEADER_STDC +dnl AC_CHECK_HEADERS([netinet/in.h stdlib.h]) + +# Checks for typedefs, structures, and compiler characteristics. +dnl AC_C_CONST +dnl AC_C_INLINE + +# Checks for library functions. +dnl AC_FUNC_MALLOC +dnl AC_FUNC_VPRINTF +dnl AC_CHECK_FUNCS([memset]) + +dnl-------------------------------- + +if test ! -z "$libdir"; then + MODULE_DIR="\\\"$libdir/conntrack/\\\"" + CFLAGS="$CFLAGS -DCONNTRACK_LIB_DIR=$MODULE_DIR" +fi + +dnl-------------------------------- + +dnl AC_CONFIG_FILES([Makefile +dnl debug/Makefile +dnl debug/src/Makefile +dnl extensions/Makefile +dnl src/Makefile]) + +AC_OUTPUT(Makefile src/Makefile include/Makefile extensions/Makefile examples/Makefile examples/stats/Makefile examples/sync/Makefile examples/sync/persistent/Makefile examples/sync/nack/Makefile examples/sync/persistent/node1/Makefile examples/sync/persistent/node2/Makefile examples/sync/nack/node1/Makefile examples/sync/nack/node2/Makefile) diff --git a/conntrack.8 b/conntrack.8 new file mode 100644 index 0000000..307180b --- /dev/null +++ b/conntrack.8 @@ -0,0 +1,142 @@ +.TH CONNTRACK 8 "Jun 23, 2005" "" "" + +.\" Man page written by Harald Welte . diff --git a/daemon/AUTHORS b/daemon/AUTHORS deleted file mode 100644 index e6c2f6b..0000000 --- a/daemon/AUTHORS +++ /dev/null @@ -1 +0,0 @@ -Pablo Neira Ayuso diff --git a/daemon/CHANGELOG b/daemon/CHANGELOG deleted file mode 100644 index afab61d..0000000 --- a/daemon/CHANGELOG +++ /dev/null @@ -1,184 +0,0 @@ -version 0.9.3 (yet unreleased) ------------------------------- -o fix commit of confirmed expectations (reported by Nishit Shah) -o fix double increment of counters in cache_update_force() (Niko Tyni) -o nl_dump_handler must return NFCT_CB_CONTINUE (Niko Tyni) -o initialize buffer in nl_event_handler() and nl_dump_handler() (Niko Tyni) -o CacheCommit value can be set via conntrackd.conf for the NACK approach -o fix leaks in the hashtable/cache flush path (Niko Tyni) -o fix leak if a connection already exists in the cache (Niko Tyni) -o introduce a new header that encapsulates netlink messages -o remove all '_entry' tail from all functions in cache.c -o split cache.c: move cache iterators to file cache_iterators.c -o fix inconsistencies in the cache API related to counters -o cleanup 'usage' message -o fix typo in examples/sync/nack/node1/conntrackd.conf -o introduce message checksumming as described in RFC1071 (enabled by default) -o major cleanups in the synchronization code -o just warn once that the maximum netlink socket buffer has been reached -o fix ignore conntrack entries by IP and introduce ignore pool abstraction layer -o introduce netlink socket buffer overrun handler -o constification of hash, compare and hashtable_test functions in hash.c -o introduce ACKnowledgement mechanisms to reduce the size of the resend queue -o remove OK messages at startup since provide useless data -o fix compilation warning in mcast.c: recvfrom takes socklen_t not size_t -o add a lock per buffer: makes buffer code thread safe -o introduce 'Replicate' clause to explicitely set states to be replicated -o kill cache feature abuse: introduce nicer cache hooks for sync algorithms -o fix oversized buffer allocated in the stack in the cache functions -o add support to dump internal/external cache in XML format '-x' - -version 0.9.2 (2006/01/17) --------------------------- -o remove spamming packet lost messages -o generalize network netlink sequence tracking -o fix bogus error message on resync `-R' -o fix endianess issues in the network netlink message -o introduce generic netlink multicast primitives to send and receive -o fix bogus replayed multicast message due to sequence numbering wraparound -o introduce counter for malformed netlink messages received -o introduce a new syntax for the `Sync' section in the configuration file -o several cleanups and remove unused variables -o add autostuff to include examples in the tarball (reported by Victor Lozano) -o use the new API available in libnetfilter_conntrack-0.0.50 -o implement a NACK based protocol for replication - -version 0.9.1 (2006/11/06) --------------------------- -o conntrackd requires kernel >= 2.6.18 -o remove bogus TIMERS_MODE constant -o implement bulk mode '-B': first works to address the preemption issue -o fix minor reduction conflicts in the configfile grammar -o check for CAP_NET_ADMIN instead of requiring root privileges -o check that linux/capability.h exists -o fix formatting at dump statistics '-s' -o move dump traffic stats before multicast traffic stats -o move event and dump handler to a generic infrastructure: kill events.c file -o kill unused function inc_ct_stats -o kill file resync.h -o cleanup broadcast_sync: renamed to mcast_send_sync -o sed 's/perror/debug/g' local.c -o fix bogus increment of update_fail stats at dump stage -o display descriptive error if we can't connect to conntrackd via UNIX socket -o remove debugging message from alarm.c -o move dump_mcast_stats to mcast.c where it really belongs -o rename stats.c to traffic_stats.c -o check for replayed/lost multicast message: simple seq tracking w/o recovery -o reissue nfnl_catch on ENOENT error: a message for other subsystem -o remove test/ directory in tree -o improve cache commit stats -o kill last_commit and last_flush from cache statistics: use the logfile -o recover cache naming for dump stats `-s' -o display multicast sequence tracking statistics: packets lost and replayed -o zero ct_sync_state and ct_stats_state structures after allocation -o improve keepalived scripts: - - resync with conntrack table on transition to master - - send bulk on transition to backup -o implement alarm cascade of ten levels -o implement timer cache flavour: limited life of entries in the external cache -o implement a global lock that protects operation with conntrack entries -o remove debug checking in cache_del_entry -o set a reduced timeout for committed entries: 180 seconds by default -o update comments on the sync-mode code -o introduce delay destroy messages facility -o increase timer for external states from 60 to 180 seconds -o remove unused replicate/dont_replicated constants -o fix cache entry clashing issue (reported by Maik Hentsche) -o fix bogus increment of error stats in the external cache -o remove pollution generated by `[REQ] cache dump' message from logfile - -version 0.9.0 (2006/09/17) --------------------------- -o implement initial for IPv6 (untested) -o implement generic extensible cache: kill the internal and external caches -o implement persistence cache feature -o implement lifetime cache feature -o modify UNIX facilities identification numbers: - separate master conntrack facilities and internal plugin facilities -o break backward compatibility of configuration file: - remove IgnoreLoopback, use IgnoreTrafficFor instead - remove IgnoreMulticastTraffic, use IgnoreTrafficFor instead -o merge event/event_subsys and sync/sync_subsys initialization to run.c -o improve control of the iteration process in the hashtables -o fix wrong locking in the alarm thread -o supersede AcceptNAT by StripNAT clause -o replace ignore traffic array by a hashtable -o move lockfile checking before daemonization -o on initialization error give a descriptive error -o introduce netlink socket size grown limitator -o introduce force resync with master conntrack table facility '-R' -o ignore SIGPIPE signal -o kill post_step since it is not used anymore - -version 0.8.3 (2006/09/03) --------------------------- -Author: Maik Hentsche - -o Fix typo in conntrackd -h -o Disable debugging messages by default -o No signals while signals handlings -o Add extra checkings at forking -o Check maximum size for file passed via -C - -Author: Pablo Neira Ayuso - -o retry select() if EINTR is returned (Reported by Maik Hentsche) -o Fix bug in slist_for_each_entry (Reported by Maik Hetsche) -o Signal handler registration done after intialization -o Implement alarm thread (based on Maik Hentsche's patch) -o Fix segfault on conntrackd -k (Reported by Maik Hentsche) -o Fix bug on alarm removal (Reported by Maik Hentsche) -o configure stops if bison, flex or yacc are not installed - -version 0.8.2 (2006/07/05) --------------------------- -o RelaxTransitions clause introduced in Sync mode -o multicast messages sequence tracking -o SocketBufferSize clause to set up the netlink socket buffer -o use new libnfnetlink API to solve limitations of nfnl_listen -o extra sanity checkings for netlink multicast messages -o improve statistics -o tons of cleanups 8) - -version 0.8.1 (2006/06/13) --------------------------- -o -f now just flushes the internal and external caches -o -F flushes the master conntrack table -o fix segfault under heavy load and signal received -o added -S mode for statistics: still needs more thinking - -version 0.8.0 (2006/06/11) --------------------------- -o more work to generalize the daemon: now it's ready to implement -modular support for adaptive timers and conntrack statistics, time -to implement them ;). This is *still* a work in progress. - -version 0.7.2 (2006/06/05) --------------------------- -o stupid bug in normal and alarm caches initialization: flush unset -o fix racy signal handling - -version 0.7.1 (2006/06/05) --------------------------- -o Bugfix for multicast sockets communication - -version 0.7 (2006/06/01) ------------------------- -o Major code re-structuration: internal and external cache abstraction -o sequence tracking for event messages -o expect more changes, I still dislike some stuff in its current status ;) - -version 0.6 (2006/05/31) ------------------------- -o Lock file support -o use new API nfct_conntrack_event_raw -o major code clean ups - -version 0.5 (2006/05/30) -------------------------- -o Fix multicast server binds to wrong interface -o Include clause `IgnoreProtocol', deprecates IgnoreUDP and IgnoreICMP - -version 0.4 (2006/05/29) ------------------------- -o Initial release diff --git a/daemon/CONTRIBUTORS b/daemon/CONTRIBUTORS deleted file mode 100644 index c5e40b4..0000000 --- a/daemon/CONTRIBUTORS +++ /dev/null @@ -1,3 +0,0 @@ -Maik Hentsche : - - Feedback & Brainstorming - - Bug hunting diff --git a/daemon/INSTALL b/daemon/INSTALL deleted file mode 100644 index 0de8dc0..0000000 --- a/daemon/INSTALL +++ /dev/null @@ -1,199 +0,0 @@ -Copyright (C) 2006-2007 Pablo Neira Ayuso - -1.Basic Installation -==================== - - To compile and install 'conntrackd' just follow the classical steps: - - $ ./configure - $ make - # make install - # mkdir /etc/conntrackd/ - -2.1. Synchronization Mode -========================= - - Conntrackd can replicate the status of the connections that are currently - being processed by your stateful firewall based on Linux. This section - describes how to setup the daemon in synchronization mode: - -2.1.1. Requirements - - You have to install the following software in order to get conntrackd working, - make sure that you have installed them correctly before going forward: - - o linux kernel version >= 2.6.18 (http://www.kernel.org) with support for: - - connection tracking system (quite obvious ;) - - nfnetlink - - ctnetlink (ip_conntrack_netlink) - - connection tracking event notification API - - o libnfnetlink: the netfilter netlink library - - Since conntrackd version 0.9.2 you can used the official release availble at - http://www.netfilter.org/projects/libnfnetlink/files/ - - Up to conntrackd version 0.9.1 use the unofficial release available at the - download section - - o libnetfilter_conntrack: the netfilter conntrack library - - Since conntrackd version 0.9.2 you can used the official release availble at - http://www.netfilter.org/projects/libnetfilter_conntrack/files/ - - Up to conntrackd version 0.9.1 use the unnoficial release available at the - download section - - o Keepalived version 1.x (http://www.keepalived.org) - check if your distribution comes with a recent version - -2.1.2. Configuration - - 1) Setting up keepalived - - There is an example file available inside the conntrackd tarball: - - For node 1: conntrackd-x.x.x/examples/sync/node1/keepalived.conf - For node 2: conntrackd-x.x.x/examples/sync/node2/keepalived.conf - - These files can be used to set up a simple VRRP cluster composed of - two machines that hold the virtual IPs 192.168.0.100 on eth0 and - 192.168.1.100 on eth1. - - If you are not familiar with keepalived, please read the official - docs available at http://www.keepalived.org - - Please, make sure that keepalived is correctly working before passing - to step 2) - - 2) Setting up conntrackd - - To setup 'conntrackd' in synchronization mode, you have to put the - configuration file in the directory /etc/conntrackd. - - On node 1: - # cp examples/sync/_type_/node1/conntrackd.conf /etc/conntrackd.conf - - On node 2: - # cp examples/sync/_type_/node1/conntrackd.conf /etc/conntrackd.conf - - Where _type_ is the synchronization type selected, currently there are - two: the persistent mode and the NACK mode. The persistent mode consumes - more resources than the NACK mode, however the NACK mode is still - experimental - - Do not forget to edit the files in order to adapt them to the - setting that you are deploying. - - Note: If you don't want to put the config file under /etc/conntrackd, - just tell conntrackd where to find it passing the option -C - - 3) Running conntrackd - - Conntrackd can run in console mode, in that case just type 'conntrackd', - otherwise, if you want to run it in daemon mode the type 'conntrackd -d'. - - 4) Checking that conntrackd is working fine - - Conntrackd comes with several facilities to check its status: - - - Dump the cache of connections that are currently being processed by - this node (aka. internal cache): - - # conntrackd -i - - - Dump the cache of connections that has been transfered from - others active nodes in the network (aka. external cache) - - # conntrackd -e - - - Dump statistics collected by the replication daemon: - - # conntrackd -s - - 5) Setting up interaction with keepalived - - If keepalived detects the failure of the active node, then it designates - a candidate node that will replace the failing active. On such event, - the external cache, eg. the cache that contains the connections processed - by other nodes, must be commited. To commit the external cache, just type: - - # conntrackd -c - - See that keepalived provides a shell script interface to interact with - other programs, so we can automate the process of commiting the external - cache by introducing the following line in the keepalived file: - - notify_master /etc/conntrackd/script_master.sh - - The script 'script_master.sh' just the following: - - #!/bin/sh - /usr/sbin/conntrackd -c - - Therefore, on failure event, the candidate node takes over the virtual - IPs and the connections that the failing active was processing. Observe - that this file differs for the NACK mode. - - 6) Disable TCP window tracking - - Until the appropiate patches don't go into kernel mainline, you will have - to disable TCP window tracking, consider this as a temporary solution: - - # echo 1 > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_be_liberal - -2.2. Statistics mode -==================== - - Conntrackd can also run as statistics daemon, if you are not interested in - this mode, just skip it. It is not required in order to get the - synchronization mode working. This section details how to setup the daemon - in statistics mode: - -2.2.1. Requirements - - You have to install the following software in order to get conntrackd working, - make sure that you have them installed correctly before going forward: - - o linux kernel version >= 2.6.18 (http://www.kernel.org) with support for: - - connection tracking system - - nfnetlink - - ctnetlink (ip_conntrack_netlink) - - connection tracking event notification API - - o libnfnetlink: the netfilter netlink library - - Since conntrackd version 0.9.2 you can used the official release availble at - http://www.netfilter.org/projects/libnfnetlink/files/ - - Up to conntrackd version 0.9.1 use the unofficial release available at the - download section - - o libnetfilter_conntrack: the netfilter conntrack library - - Since conntrackd version 0.9.2 you can used the official release availble at - http://www.netfilter.org/projects/libnetfilter_conntrack/files/ - - Up to conntrackd version 0.9.1 use the unnoficial release available at the - download section - -2.2.2. Configuration - - Setting up conntrackd in statistics mode is rather easy. Just copy the - configuration file - - # cp examples/stats/conntrackd.conf /etc/conntrackd.conf - -2.2.3. Running conntrackd in statistics mode - - To run conntrackd in statistics mode: - - # conntrackd -S - - Alternatively, you can run conntrackd in daemon mode: - - # conntrackd -S -d - - In order to dump the statistics, just type: - - # conntrackd -s diff --git a/daemon/Make_global.am b/daemon/Make_global.am deleted file mode 100644 index 685add7..0000000 --- a/daemon/Make_global.am +++ /dev/null @@ -1 +0,0 @@ -INCLUDES=$(all_includes) -I$(top_srcdir)/include diff --git a/daemon/Makefile.am b/daemon/Makefile.am deleted file mode 100644 index 998f4c6..0000000 --- a/daemon/Makefile.am +++ /dev/null @@ -1,21 +0,0 @@ -include Make_global.am - -# not a GNU package. You can remove this line, if -# have all needed files, that a GNU package needs -AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 - -# man_MANS = "" -# EXTRA_DIST = $(man_MANS) Make_global.am debian -EXTRA_DIST = Make_global.am CHANGELOG TODO - -SUBDIRS = src -DIST_SUBDIRS = include src examples -LINKOPTS = -lnfnetlink -lnetfilter_conntrack -lpthread -AM_CFLAGS = -g - -$(OBJECTS): libtool -libtool: $(LIBTOOL_DEPS) - $(SHELL) ./config.status --recheck - -dist-hook: - rm -rf `find $(distdir)/debian -name .svn` diff --git a/daemon/TODO b/daemon/TODO deleted file mode 100644 index 130b1f8..0000000 --- a/daemon/TODO +++ /dev/null @@ -1,18 +0,0 @@ -There are several tasks that are pending to be done, I have classified them -by dificulty levels: - -Relatively easy -=============== - -- test ipv6 support -- improve shell scripts -- test NACK based protocol -- manpage for conntrackd - -Requires some work -================== - -- study better keepalived transitions -- implement support for TCP window tracking (patches are on the table) - - at the moment you have to disable it: - echo 1 > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_be_liberal diff --git a/daemon/autogen.sh b/daemon/autogen.sh deleted file mode 100755 index e76d3ef..0000000 --- a/daemon/autogen.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -run () -{ - echo "running: $*" - eval $* - - if test $? != 0 ; then - echo "error: while running '$*'" - exit 1 - fi -} - -run aclocal -run libtoolize -f -#run autoheader -run automake -a -run autoconf diff --git a/daemon/configure.in b/daemon/configure.in deleted file mode 100644 index 92e512a..0000000 --- a/daemon/configure.in +++ /dev/null @@ -1,106 +0,0 @@ -AC_INIT(conntrackd, 0.9.2, pablo@netfilter.org) - -AC_CANONICAL_SYSTEM - -AM_INIT_AUTOMAKE - -AC_PROG_CC -AM_PROG_LIBTOOL -AC_PROG_INSTALL -AC_PROG_LN_S -AM_PROG_LEX -AC_PROG_YACC - -case $target in -*-*-linux*) ;; -*) AC_MSG_ERROR([Linux only, dude!]);; -esac - -AC_CHECK_PROGS(XYACC,$YACC bison yacc,none) -if test "$XYACC" = "none" -then - echo "*** Error: No suitable bison/yacc found. ***" - echo " Please install the 'bison' package." - exit 1 -fi -AC_CHECK_PROGS(XLEX,$LEX flex lex,none) -if test "$XLEX" = "none" -then - echo "*** Error: No suitable bison/yacc found. ***" - echo " Please install the 'bison' package." - exit 1 -fi - -AC_CHECK_HEADERS([linux/capability.h],, [AC_MSG_ERROR([Cannot find linux/capabibility.h])]) - -# Checks for libraries. -# FIXME: Replace `main' with a function in `-lc': -dnl AC_CHECK_LIB([c], [main]) -# FIXME: Replace `main' with a function in `-ldl': - -AC_CHECK_LIB([nfnetlink], [nfnl_talk] ,,,[-lnfnetlink]) -AC_CHECK_LIB([netfilter_conntrack], [nfct_dump_conntrack_table] ,,,[-lnetfilter_conntrack]) -AC_CHECK_LIB([pthread], [pthread_create] ,,,[-lpthread]) - -AC_CHECK_HEADERS(arpa/inet.h) -dnl check for inet_pton -AC_CHECK_FUNCS(inet_pton) -dnl Some systems have it, but not IPv6 -if test "$ac_cv_func_inet_pton" = "yes" ; then -AC_MSG_CHECKING(if inet_pton supports IPv6) -AC_TRY_RUN( - [ -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -int main() - { - struct in6_addr addr6; - if (inet_pton(AF_INET6, "::1", &addr6) < 1) - exit(1); - else - exit(0); - } - ], [ AC_MSG_RESULT(yes) - AC_DEFINE_UNQUOTED(HAVE_INET_PTON_IPV6, 1, [Define to 1 if inet_pton supports IPv6.]) - ], AC_MSG_RESULT(no), AC_MSG_RESULT(no)) -fi - -# Checks for header files. -dnl AC_HEADER_STDC -dnl AC_CHECK_HEADERS([netinet/in.h stdlib.h]) - -# Checks for typedefs, structures, and compiler characteristics. -dnl AC_C_CONST -dnl AC_C_INLINE - -# Checks for library functions. -dnl AC_FUNC_MALLOC -dnl AC_FUNC_VPRINTF -dnl AC_CHECK_FUNCS([memset]) - -dnl-------------------------------- - -dnl if test ! -z "$libdir"; then -dnl MODULE_DIR="\\\"$libdir/conntrack/\\\"" -dnl CFLAGS="$CFLAGS -DCONNTRACK_LIB_DIR=$MODULE_DIR" -dnl fi - -dnl-------------------------------- - -dnl AC_CONFIG_FILES([Makefile -dnl debug/Makefile -dnl debug/src/Makefile -dnl extensions/Makefile -dnl src/Makefile]) - -AC_OUTPUT(Makefile src/Makefile include/Makefile examples/Makefile examples/stats/Makefile examples/sync/Makefile examples/sync/persistent/Makefile examples/sync/nack/Makefile examples/sync/persistent/node1/Makefile examples/sync/persistent/node2/Makefile examples/sync/nack/node1/Makefile examples/sync/nack/node2/Makefile) diff --git a/daemon/examples/Makefile.am b/daemon/examples/Makefile.am deleted file mode 100644 index be83d42..0000000 --- a/daemon/examples/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS = stats sync diff --git a/daemon/examples/debian.conntrackd.init.d b/daemon/examples/debian.conntrackd.init.d deleted file mode 100644 index ba847dd..0000000 --- a/daemon/examples/debian.conntrackd.init.d +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh -# -# /etc/init.d/conntrackd -# -# Maximilian Wilhelm -# -- Mon, 06 Nov 2006 18:39:07 +0100 -# - -export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin - -NAME="conntrackd" -DAEMON=`command -v conntrackd` -CONFIG="/etc/conntrack/conntrackd.conf" -PIDFILE="/var/run/${NAME}.pid" - - -# Gracefully exit if there is no daemon (debian way of life) -if [ ! -x "${DAEMON}" ]; then - exit 0 -fi - -# Check for config file -if [ ! -f /etc/conntrackd/conntrackd.conf ]; then - echo "Error: There is no config file for $NAME" >&2 - exit 1; -fi - -case "$1" in - start) - echo -n "Starting $NAME: " - start-stop-daemon --start --quiet --make-pidfile --pidfile "/var/run/${NAME}.pid" --background --exec "${DAEMON}" && echo "done." || echo "FAILED!" - ;; - stop) - echo -n "Stopping $NAME:" - start-stop-daemon --stop --quiet --oknodo --pidfile "/var/run/${NAME}.pid" && echo "done." || echo "FAILED!" - ;; - - restart) - $0 start - $0 stop - ;; - - *) - echo "Usage: /etc/init.d/conntrackd {start|stop|restart}" - exit 1 -esac - -exit 0 diff --git a/daemon/examples/stats/Makefile.am b/daemon/examples/stats/Makefile.am deleted file mode 100644 index b43c3b8..0000000 --- a/daemon/examples/stats/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -EXTRA_DIST = conntrackd.conf diff --git a/daemon/examples/stats/conntrackd.conf b/daemon/examples/stats/conntrackd.conf deleted file mode 100644 index e514ac0..0000000 --- a/daemon/examples/stats/conntrackd.conf +++ /dev/null @@ -1,69 +0,0 @@ -# -# General settings -# -General { - # - # Number of buckets in the caches: hash table - # - HashSize 8192 - - # - # Maximum number of conntracks: - # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max - # - HashLimit 65535 - - # - # Logfile - # - LogFile /var/log/conntrackd.log - - # - # Lockfile - # - LockFile /var/lock/conntrack.lock - - # - # Unix socket configuration - # - UNIX { - Path /tmp/sync.sock - Backlog 20 - } - - # - # Netlink socket buffer size - # - SocketBufferSize 262142 - - # - # Increase the socket buffer up to maximun if required - # - SocketBufferSizeMaxGrown 655355 -} - -# -# Ignore traffic for a certain set of IP's: Usually -# all the IP assigned to the firewall since local -# traffic must be ignored, just forwarded connections -# are worth to replicate -# -IgnoreTrafficFor { - IPv4_address 127.0.0.1 # loopback -} - -# -# Do not replicate certain protocol traffic -# -IgnoreProtocol { - UDP -# ICMP -# IGMP -# VRRP - # numeric numbers also valid -} - -# -# Strip NAT traffic -# -StripNAT diff --git a/daemon/examples/sync/Makefile.am b/daemon/examples/sync/Makefile.am deleted file mode 100644 index 28e7643..0000000 --- a/daemon/examples/sync/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS = persistent nack diff --git a/daemon/examples/sync/nack/Makefile.am b/daemon/examples/sync/nack/Makefile.am deleted file mode 100644 index 6fd99b1..0000000 --- a/daemon/examples/sync/nack/Makefile.am +++ /dev/null @@ -1,2 +0,0 @@ -EXTRA_DIST = script_backup.sh script_master.sh -SUBDIRS = node1 node2 diff --git a/daemon/examples/sync/nack/README b/daemon/examples/sync/nack/README deleted file mode 100644 index 66987f7..0000000 --- a/daemon/examples/sync/nack/README +++ /dev/null @@ -1 +0,0 @@ -This directory contains the files for the NACK based protocol diff --git a/daemon/examples/sync/nack/node1/Makefile.am b/daemon/examples/sync/nack/node1/Makefile.am deleted file mode 100644 index edc0ed7..0000000 --- a/daemon/examples/sync/nack/node1/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -EXTRA_DIST = conntrackd.conf keepalived.conf diff --git a/daemon/examples/sync/nack/node1/conntrackd.conf b/daemon/examples/sync/nack/node1/conntrackd.conf deleted file mode 100644 index f24fa7e..0000000 --- a/daemon/examples/sync/nack/node1/conntrackd.conf +++ /dev/null @@ -1,125 +0,0 @@ -# -# Synchronizer settings -# -Sync { - Mode NACK { - # - # Size of the buffer that hold destroy messages for - # possible resends (in bytes) - # - ResendBufferSize 262144 - - # - # Entries committed to the connection tracking table - # starts with a limited timeout of N seconds until the - # takeover process is completed. - # - CommitTimeout 180 - - # Set Acknowledgement window size - ACKWindowSize 20 - } - - # - # Multicast IP and interface where messages are - # broadcasted (dedicated link). IMPORTANT: Make sure - # that iptables accepts traffic for destination - # 225.0.0.50, eg: - # - # iptables -I INPUT -d 225.0.0.50 -j ACCEPT - # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT - # - Multicast { - IPv4_address 225.0.0.50 - IPv4_interface 192.168.100.100 # IP of dedicated link - Group 3780 - Backlog 20 - } - - # Enable/Disable message checksumming - Checksum on - - # Uncomment this if you want to replicate just certain TCP states. - # This option introduces a tradeoff in the replication: it reduces - # CPU consumption and lost messages rate at the cost of having - # backup replicas that don't contain the current state that the active - # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, - # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. - # - # Replicate ESTABLISHED TIME_WAIT for TCP -} - -# -# General settings -# -General { - # - # Number of buckets in the caches: hash table - # - HashSize 8192 - - # - # Maximum number of conntracks: - # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max - # - HashLimit 65535 - - # - # Logfile - # - LogFile /var/log/conntrackd.log - - # - # Lockfile - # - LockFile /var/lock/conntrack.lock - - # - # Unix socket configuration - # - UNIX { - Path /tmp/sync.sock - Backlog 20 - } - - # - # Netlink socket buffer size - # - SocketBufferSize 262142 - - # - # Increase the socket buffer up to maximum if required - # - SocketBufferSizeMaxGrown 655355 -} - -# -# Ignore traffic for a certain set of IP's: Usually -# all the IP assigned to the firewall since local -# traffic must be ignored, just forwarded connections -# are worth to replicate -# -IgnoreTrafficFor { - IPv4_address 127.0.0.1 # loopback - IPv4_address 192.168.0.1 - IPv4_address 192.168.1.1 - IPv4_address 192.168.100.100 # dedicated link ip - IPv4_address 192.168.0.100 # virtual IP 1 - IPv4_address 192.168.1.100 # virtual IP 2 -} - -# -# Do not replicate certain protocol traffic -# -IgnoreProtocol { - UDP - ICMP - IGMP - VRRP - # numeric numbers also valid -} - -# -# Strip NAT traffic -# -StripNAT diff --git a/daemon/examples/sync/nack/node1/keepalived.conf b/daemon/examples/sync/nack/node1/keepalived.conf deleted file mode 100644 index 41aa35b..0000000 --- a/daemon/examples/sync/nack/node1/keepalived.conf +++ /dev/null @@ -1,38 +0,0 @@ -vrrp_sync_group G1 { # must be before vrrp_instance declaration - group { - VI_1 - VI_2 - } - notify_master /etc/conntrackd/script_master.sh - notify_backup /etc/conntrackd/script_backup.sh -} - -vrrp_instance VI_1 { - interface eth1 - state SLAVE - virtual_router_id 61 - priority 80 - advert_int 3 - authentication { - auth_type PASS - auth_pass papas_con_tomate - } - virtual_ipaddress { - 192.168.0.100 # default CIDR mask is /32 - } -} - -vrrp_instance VI_2 { - interface eth0 - state SLAVE - virtual_router_id 62 - priority 80 - advert_int 3 - authentication { - auth_type PASS - auth_pass papas_con_tomate - } - virtual_ipaddress { - 192.168.1.100 - } -} diff --git a/daemon/examples/sync/nack/node2/Makefile.am b/daemon/examples/sync/nack/node2/Makefile.am deleted file mode 100644 index edc0ed7..0000000 --- a/daemon/examples/sync/nack/node2/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -EXTRA_DIST = conntrackd.conf keepalived.conf diff --git a/daemon/examples/sync/nack/node2/conntrackd.conf b/daemon/examples/sync/nack/node2/conntrackd.conf deleted file mode 100644 index 4f15773..0000000 --- a/daemon/examples/sync/nack/node2/conntrackd.conf +++ /dev/null @@ -1,124 +0,0 @@ -# -# Synchronizer settings -# -Sync { - Mode NACK { - # - # Size of the buffer that hold destroy messages for - # possible resends (in bytes) - # - ResendBufferSize 262144 - - # Entries committed to the connection tracking table - # starts with a limited timeout of N seconds until the - # takeover process is completed. - # - CommitTimeout 180 - - # Set Acknowledgement window size - ACKWindowSize 20 - } - - # - # Multicast IP and interface where messages are - # broadcasted (dedicated link). IMPORTANT: Make sure - # that iptables accepts traffic for destination - # 225.0.0.50, eg: - # - # iptables -I INPUT -d 225.0.0.50 -j ACCEPT - # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT - # - Multicast { - IPv4_address 225.0.0.50 - IPv4_interface 192.168.100.200 # IP of dedicated link - Group 3780 - Backlog 20 - } - - # Enable/Disable message checksumming - Checksum on - - # Uncomment this if you want to replicate just certain TCP states. - # This option introduces a tradeoff in the replication: it reduces - # CPU consumption and lost messages rate at the cost of having - # backup replicas that don't contain the current state that the active - # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, - # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. - # - # Replicate ESTABLISHED TIME_WAIT for TCP -} - -# -# General settings -# -General { - # - # Number of buckets in the caches: hash table - # - HashSize 8192 - - # - # Maximum number of conntracks: - # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max - # - HashLimit 65535 - - # - # Logfile - # - LogFile /var/log/conntrackd.log - - # - # Lockfile - # - LockFile /var/lock/conntrack.lock - - # - # Unix socket configuration - # - UNIX { - Path /tmp/sync.sock - Backlog 20 - } - - # - # Netlink socket buffer size - # - SocketBufferSize 262142 - - # - # Increase the socket buffer up to maximum if required - # - SocketBufferSizeMaxGrown 655355 -} - -# -# Ignore traffic for a certain set of IP's: Usually -# all the IP assigned to the firewall since local -# traffic must be ignored, just forwarded connections -# are worth to replicate -# -IgnoreTrafficFor { - IPv4_address 127.0.0.1 # loopback - IPv4_address 192.168.0.2 - IPv4_address 192.168.1.2 - IPv4_address 192.168.100.200 # dedicated link ip - IPv4_address 192.168.0.200 # virtual IP 1 - IPv4_address 192.168.1.200 # virtual IP 2 -} - -# -# Do not replicate certain protocol traffic -# -IgnoreProtocol { - UDP - ICMP - IGMP - VRRP - # numeric numbers also valid -} - -# -# Strip NAT traffic -# -StripNAT diff --git a/daemon/examples/sync/nack/node2/keepalived.conf b/daemon/examples/sync/nack/node2/keepalived.conf deleted file mode 100644 index 41aa35b..0000000 --- a/daemon/examples/sync/nack/node2/keepalived.conf +++ /dev/null @@ -1,38 +0,0 @@ -vrrp_sync_group G1 { # must be before vrrp_instance declaration - group { - VI_1 - VI_2 - } - notify_master /etc/conntrackd/script_master.sh - notify_backup /etc/conntrackd/script_backup.sh -} - -vrrp_instance VI_1 { - interface eth1 - state SLAVE - virtual_router_id 61 - priority 80 - advert_int 3 - authentication { - auth_type PASS - auth_pass papas_con_tomate - } - virtual_ipaddress { - 192.168.0.100 # default CIDR mask is /32 - } -} - -vrrp_instance VI_2 { - interface eth0 - state SLAVE - virtual_router_id 62 - priority 80 - advert_int 3 - authentication { - auth_type PASS - auth_pass papas_con_tomate - } - virtual_ipaddress { - 192.168.1.100 - } -} diff --git a/daemon/examples/sync/nack/script_backup.sh b/daemon/examples/sync/nack/script_backup.sh deleted file mode 100755 index 813e375..0000000 --- a/daemon/examples/sync/nack/script_backup.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -/usr/sbin/conntrackd -n # request a resync from other nodes via multicast diff --git a/daemon/examples/sync/nack/script_master.sh b/daemon/examples/sync/nack/script_master.sh deleted file mode 100755 index ff1dbc0..0000000 --- a/daemon/examples/sync/nack/script_master.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -/usr/sbin/conntrackd -c # commit the cache -/usr/sbin/conntrackd -f # flush the caches -/usr/sbin/conntrackd -R # resync with kernel conntrack table diff --git a/daemon/examples/sync/persistent/Makefile.am b/daemon/examples/sync/persistent/Makefile.am deleted file mode 100644 index 6fd99b1..0000000 --- a/daemon/examples/sync/persistent/Makefile.am +++ /dev/null @@ -1,2 +0,0 @@ -EXTRA_DIST = script_backup.sh script_master.sh -SUBDIRS = node1 node2 diff --git a/daemon/examples/sync/persistent/README b/daemon/examples/sync/persistent/README deleted file mode 100644 index 36b5989..0000000 --- a/daemon/examples/sync/persistent/README +++ /dev/null @@ -1 +0,0 @@ -This directory contains the files for the PERSISTENT based protocol diff --git a/daemon/examples/sync/persistent/node1/Makefile.am b/daemon/examples/sync/persistent/node1/Makefile.am deleted file mode 100644 index edc0ed7..0000000 --- a/daemon/examples/sync/persistent/node1/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -EXTRA_DIST = conntrackd.conf keepalived.conf diff --git a/daemon/examples/sync/persistent/node1/conntrackd.conf b/daemon/examples/sync/persistent/node1/conntrackd.conf deleted file mode 100644 index 90afeb7..0000000 --- a/daemon/examples/sync/persistent/node1/conntrackd.conf +++ /dev/null @@ -1,130 +0,0 @@ -# -# Synchronizer settings -# -Sync { - Mode PERSISTENT { - # - # If a conntrack entry is not modified in <= 15 seconds, then - # a message is broadcasted. This mechanism is used to - # resynchronize nodes that just joined the multicast group - # - RefreshTime 15 - - # - # If we don't receive a notification about the state of - # an entry in the external cache after N seconds, then - # remove it. - # - CacheTimeout 180 - - # - # Entries committed to the connection tracking table - # starts with a limited timeout of N seconds until the - # takeover process is completed. - # - CommitTimeout 180 - } - - # - # Multicast IP and interface where messages are - # broadcasted (dedicated link). IMPORTANT: Make sure - # that iptables accepts traffic for destination - # 225.0.0.50, eg: - # - # iptables -I INPUT -d 225.0.0.50 -j ACCEPT - # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT - # - Multicast { - IPv4_address 225.0.0.50 - IPv4_interface 192.168.100.100 # IP of dedicated link - Group 3780 - Backlog 20 - } - - # Enable/Disable message checksumming - Checksum on - - # Uncomment this if you want to replicate just certain TCP states. - # This option introduces a tradeoff in the replication: it reduces - # CPU consumption and lost messages rate at the cost of having - # backup replicas that don't contain the current state that the active - # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, - # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. - # - # Replicate ESTABLISHED TIME_WAIT for TCP -} - -# -# General settings -# -General { - # - # Number of buckets in the caches: hash table - # - HashSize 8192 - - # - # Maximum number of conntracks: - # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max - # - HashLimit 65535 - - # - # Logfile - # - LogFile /var/log/conntrackd.log - - # - # Lockfile - # - LockFile /var/lock/conntrack.lock - - # - # Unix socket configuration - # - UNIX { - Path /tmp/sync.sock - Backlog 20 - } - - # - # Netlink socket buffer size - # - SocketBufferSize 262142 - - # - # Increase the socket buffer up to maximum if required - # - SocketBufferSizeMaxGrown 655355 -} - -# -# Ignore traffic for a certain set of IP's: Usually -# all the IP assigned to the firewall since local -# traffic must be ignored, just forwarded connections -# are worth to replicate -# -IgnoreTrafficFor { - IPv4_address 127.0.0.1 # loopback - IPv4_address 192.168.0.1 - IPv4_address 192.168.1.1 - IPv4_address 192.168.100.100 # dedicated link ip - IPv4_address 192.168.0.100 # virtual IP 1 - IPv4_address 192.168.1.100 # virtual IP 2 -} - -# -# Do not replicate certain protocol traffic -# -IgnoreProtocol { - UDP - ICMP - IGMP - VRRP - # numeric numbers also valid -} - -# -# Strip NAT traffic -# -StripNAT diff --git a/daemon/examples/sync/persistent/node1/keepalived.conf b/daemon/examples/sync/persistent/node1/keepalived.conf deleted file mode 100644 index 41aa35b..0000000 --- a/daemon/examples/sync/persistent/node1/keepalived.conf +++ /dev/null @@ -1,38 +0,0 @@ -vrrp_sync_group G1 { # must be before vrrp_instance declaration - group { - VI_1 - VI_2 - } - notify_master /etc/conntrackd/script_master.sh - notify_backup /etc/conntrackd/script_backup.sh -} - -vrrp_instance VI_1 { - interface eth1 - state SLAVE - virtual_router_id 61 - priority 80 - advert_int 3 - authentication { - auth_type PASS - auth_pass papas_con_tomate - } - virtual_ipaddress { - 192.168.0.100 # default CIDR mask is /32 - } -} - -vrrp_instance VI_2 { - interface eth0 - state SLAVE - virtual_router_id 62 - priority 80 - advert_int 3 - authentication { - auth_type PASS - auth_pass papas_con_tomate - } - virtual_ipaddress { - 192.168.1.100 - } -} diff --git a/daemon/examples/sync/persistent/node2/Makefile.am b/daemon/examples/sync/persistent/node2/Makefile.am deleted file mode 100644 index edc0ed7..0000000 --- a/daemon/examples/sync/persistent/node2/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -EXTRA_DIST = conntrackd.conf keepalived.conf diff --git a/daemon/examples/sync/persistent/node2/conntrackd.conf b/daemon/examples/sync/persistent/node2/conntrackd.conf deleted file mode 100644 index aee4a29..0000000 --- a/daemon/examples/sync/persistent/node2/conntrackd.conf +++ /dev/null @@ -1,130 +0,0 @@ -# -# Synchronizer settings -# -Sync { - Mode PERSISTENT { - # - # If a conntrack entry is not modified in <= 15 seconds, then - # a message is broadcasted. This mechanism is used to - # resynchronize nodes that just joined the multicast group - # - RefreshTime 15 - - # - # If we don't receive a notification about the state of - # an entry in the external cache after N seconds, then - # remove it. - # - CacheTimeout 180 - - # - # Entries committed to the connection tracking table - # starts with a limited timeout of N seconds until the - # takeover process is completed. - # - CommitTimeout 180 - } - - # - # Multicast IP and interface where messages are - # broadcasted (dedicated link). IMPORTANT: Make sure - # that iptables accepts traffic for destination - # 225.0.0.50, eg: - # - # iptables -I INPUT -d 225.0.0.50 -j ACCEPT - # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT - # - Multicast { - IPv4_address 225.0.0.50 - IPv4_interface 192.168.100.200 # IP of dedicated link - Group 3780 - Backlog 20 - } - - # Enable/Disable message checksumming - Checksum on - - # Uncomment this if you want to replicate just certain TCP states. - # This option introduces a tradeoff in the replication: it reduces - # CPU consumption and lost messages rate at the cost of having - # backup replicas that don't contain the current state that the active - # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, - # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. - # - # Replicate ESTABLISHED TIME_WAIT for TCP -} - -# -# General settings -# -General { - # - # Number of buckets in the caches: hash table - # - HashSize 8192 - - # - # Maximum number of conntracks: - # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max - # - HashLimit 65535 - - # - # Logfile - # - LogFile /var/log/conntrackd.log - - # - # Lockfile - # - LockFile /var/lock/conntrack.lock - - # - # Unix socket configuration - # - UNIX { - Path /tmp/sync.sock - Backlog 20 - } - - # - # Netlink socket buffer size - # - SocketBufferSize 262142 - - # - # Increase the socket buffer up to maximum if required - # - SocketBufferSizeMaxGrown 655355 -} - -# -# Ignore traffic for a certain set of IP's: Usually -# all the IP assigned to the firewall since local -# traffic must be ignored, just forwarded connections -# are worth to replicate -# -IgnoreTrafficFor { - IPv4_address 127.0.0.1 # loopback - IPv4_address 192.168.0.2 - IPv4_address 192.168.1.2 - IPv4_address 192.168.100.200 # dedicated link ip - IPv4_address 192.168.0.200 # virtual IP 1 - IPv4_address 192.168.1.200 # virtual IP 2 -} - -# -# Do not replicate certain protocol traffic -# -IgnoreProtocol { - UDP - ICMP - IGMP - VRRP - # numeric numbers also valid -} - -# -# Strip NAT traffic -# -StripNAT diff --git a/daemon/examples/sync/persistent/node2/keepalived.conf b/daemon/examples/sync/persistent/node2/keepalived.conf deleted file mode 100644 index 41aa35b..0000000 --- a/daemon/examples/sync/persistent/node2/keepalived.conf +++ /dev/null @@ -1,38 +0,0 @@ -vrrp_sync_group G1 { # must be before vrrp_instance declaration - group { - VI_1 - VI_2 - } - notify_master /etc/conntrackd/script_master.sh - notify_backup /etc/conntrackd/script_backup.sh -} - -vrrp_instance VI_1 { - interface eth1 - state SLAVE - virtual_router_id 61 - priority 80 - advert_int 3 - authentication { - auth_type PASS - auth_pass papas_con_tomate - } - virtual_ipaddress { - 192.168.0.100 # default CIDR mask is /32 - } -} - -vrrp_instance VI_2 { - interface eth0 - state SLAVE - virtual_router_id 62 - priority 80 - advert_int 3 - authentication { - auth_type PASS - auth_pass papas_con_tomate - } - virtual_ipaddress { - 192.168.1.100 - } -} diff --git a/daemon/examples/sync/persistent/script_backup.sh b/daemon/examples/sync/persistent/script_backup.sh deleted file mode 100755 index 8ea2ad8..0000000 --- a/daemon/examples/sync/persistent/script_backup.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -/usr/sbin/conntrackd -B diff --git a/daemon/examples/sync/persistent/script_master.sh b/daemon/examples/sync/persistent/script_master.sh deleted file mode 100755 index 70c26c9..0000000 --- a/daemon/examples/sync/persistent/script_master.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -/usr/sbin/conntrackd -c -/usr/sbin/conntrackd -R diff --git a/daemon/include/Makefile.am b/daemon/include/Makefile.am deleted file mode 100644 index e669d73..0000000 --- a/daemon/include/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ - -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 - diff --git a/daemon/include/alarm.h b/daemon/include/alarm.h deleted file mode 100644 index 93e6482..0000000 --- a/daemon/include/alarm.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _TIMER_H_ -#define _TIMER_H_ - -#include "linux_list.h" - -struct alarm_list { - struct list_head head; - unsigned long expires; - void *data; - void (*function)(struct alarm_list *a, void *data); -}; - -#endif diff --git a/daemon/include/buffer.h b/daemon/include/buffer.h deleted file mode 100644 index 8d72dfb..0000000 --- a/daemon/include/buffer.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _BUFFER_H_ -#define _BUFFER_H_ - -#include -#include -#include -#include -#include "linux_list.h" - -struct buffer { - pthread_mutex_t lock; - size_t max_size; - size_t cur_size; - struct list_head head; -}; - -struct buffer_node { - struct list_head head; - size_t size; - char data[0]; -}; - -struct buffer *buffer_create(size_t max_size); -void buffer_destroy(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)); - -#endif diff --git a/daemon/include/cache.h b/daemon/include/cache.h deleted file mode 100644 index 7d9559a..0000000 --- a/daemon/include/cache.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef _CACHE_H_ -#define _CACHE_H_ - -#include -#include - -/* cache features */ -enum { - NO_FEATURES = 0, - - TIMER_FEATURE = 0, - TIMER = (1 << TIMER_FEATURE), - - LIFETIME_FEATURE = 2, - LIFETIME = (1 << LIFETIME_FEATURE), - - __CACHE_MAX_FEATURE -}; -#define CACHE_MAX_FEATURE __CACHE_MAX_FEATURE - -struct cache; -struct us_conntrack; - -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); -}; - -extern struct cache_feature lifetime_feature; -extern struct cache_feature timer_feature; - -#define CACHE_MAX_NAMELEN 32 - -struct cache { - char name[CACHE_MAX_NAMELEN]; - struct hashtable *h; - - unsigned int num_features; - struct cache_feature **features; - unsigned int feature_type[CACHE_MAX_FEATURE]; - unsigned int *feature_offset; - struct cache_extra *extra; - unsigned int extra_offset; - - /* statistics */ - 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 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); -}; - -struct nf_conntrack; - -struct cache *cache_create(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); -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_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 *); - -/* iterators */ -void cache_dump(struct cache *c, int fd, int type); -void cache_commit(struct cache *c); -void cache_flush(struct cache *c); -void cache_bulk(struct cache *c); - -#endif diff --git a/daemon/include/conntrackd.h b/daemon/include/conntrackd.h deleted file mode 100644 index a5f7a3a..0000000 --- a/daemon/include/conntrackd.h +++ /dev/null @@ -1,174 +0,0 @@ -#ifndef _CONNTRACKD_H_ -#define _CONNTRACKD_H_ - -#include "mcast.h" -#include "local.h" - -#include -#include -#include "cache.h" -#include "debug.h" -#include -#include "state_helper.h" -#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 DEFAULT_CONFIGFILE "/etc/conntrackd/conntrackd.conf" -#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 = (1 << SYNC_MODE_PERSISTENT_BIT), - - SYNC_MODE_NACK_BIT = 4, - SYNC_MODE_NACK = (1 << SYNC_MODE_NACK_BIT), - - DONT_CHECKSUM_BIT = 5, - DONT_CHECKSUM = (1 << DONT_CHECKSUM_BIT), -}; - -/* daemon/request modes */ -#define NOT_SET 0 -#define DAEMON 1 -#define REQUEST 2 - -/* conntrackd modes */ -#define SYNC_MODE 0 -#define STATS_MODE 1 - -/* FILENAME_MAX is 4096 on my system, perhaps too much? */ -#ifndef FILENAME_MAXLEN -#define FILENAME_MAXLEN 256 -#endif - -union inet_address { - u_int32_t ipv4; - u_int32_t ipv6[4]; - u_int32_t all[4]; -}; - -#define CONFIG(x) conf.x - -struct ct_conf { - char logfile[FILENAME_MAXLEN]; - char lockfile[FILENAME_MAXLEN]; - int hashsize; /* hashtable size */ - struct mcast_conf mcast; /* multicast settings */ - struct local_conf local; /* unix socket facilities */ - int limit; - int refresh; - int cache_timeout; /* cache entries timeout */ - int commit_timeout; /* committed entries timeout */ - unsigned int netlink_buffer_size; - unsigned int netlink_buffer_size_max_grown; - unsigned char ignore_protocol[IPPROTO_MAX]; - union inet_address *listen_to; - unsigned int listen_to_len; - unsigned int flags; - int family; /* protocol family */ - unsigned int resend_buffer_size;/* NACK protocol */ - unsigned int window_size; -}; - -#define STATE(x) st.x - -struct ct_general_state { - sigset_t block; - FILE *log; - int local; - struct ct_mode *mode; - 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 */ - u_int64_t malformed; - u_int64_t bytes[NFCT_DIR_MAX]; - u_int64_t packets[NFCT_DIR_MAX]; -}; - -#define STATE_SYNC(x) state.sync->x - -struct ct_sync_state { - struct cache *internal; /* internal events cache (netlink) */ - struct cache *external; /* external events cache (mcast) */ - - struct mcast_sock *mcast_server; /* multicast socket: incoming */ - struct mcast_sock *mcast_client; /* multicast socket: outgoing */ - - struct sync_mode *mcast_sync; - struct buffer *buffer; - - u_int32_t last_seq_sent; /* last sequence number sent */ - u_int32_t last_seq_recv; /* last sequence number recv */ - u_int64_t packets_replayed; /* number of replayed packets */ - u_int64_t packets_lost; /* lost packets: sequence tracking */ -}; - -#define STATE_STATS(x) state.stats->x - -struct ct_stats_state { - struct cache *cache; /* internal events cache (netlink) */ -}; - -union ct_state { - struct ct_sync_state *sync; - struct ct_stats_state *stats; -}; - -extern struct ct_conf conf; -extern union ct_state state; -extern struct ct_general_state st; - -#ifndef IPPROTO_VRRP -#define IPPROTO_VRRP 112 -#endif - -struct ct_mode { - int (*init)(void); - int (*add_fds_to_set)(fd_set *readfds); - void (*step)(fd_set *readfds); - 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 (*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); -}; - -/* conntrackd modes */ -extern struct ct_mode sync_mode; -extern struct ct_mode stats_mode; - -#define MAX(x, y) x > y ? x : y - -#endif diff --git a/daemon/include/debug.h b/daemon/include/debug.h deleted file mode 100644 index 67f2c71..0000000 --- a/daemon/include/debug.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _DEBUG_H -#define _DEBUG_H - -#if 0 -#define debug printf -#else -#define debug -#endif - -#include -#include -#include - -static inline void debug_ct(struct nf_conntrack *ct, char *msg) -{ - 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"); -} - -#endif diff --git a/daemon/include/hash.h b/daemon/include/hash.h deleted file mode 100644 index fd971e7..0000000 --- a/daemon/include/hash.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _NF_SET_HASH_H_ -#define _NF_SET_HASH_H_ - -#include -#include -#include "slist.h" -#include "linux_list.h" - -struct hashtable; -struct hashtable_node; - -struct hashtable { - u_int32_t hashsize; - u_int32_t limit; - u_int32_t count; - u_int32_t initval; - u_int32_t datasize; - - u_int32_t (*hash)(const void *data, struct hashtable *table); - int (*compare)(const void *data1, const void *data2); - - struct slist_head members[0]; -}; - -struct hashtable_node { - struct slist_head head; - char data[0]; -}; - -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, - u_int32_t (*hash)(const void *data, 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_test(struct hashtable *table, const void *data); -int hashtable_del(struct hashtable *table, void *data); -int hashtable_flush(struct hashtable *table); -int hashtable_iterate(struct hashtable *table, void *data, - int (*iterate)(void *data1, void *data2)); -unsigned int hashtable_counter(struct hashtable *table); - -#endif diff --git a/daemon/include/ignore.h b/daemon/include/ignore.h deleted file mode 100644 index 40cb02d..0000000 --- a/daemon/include/ignore.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _IGNORE_H_ -#define _IGNORE_H_ - -struct ignore_pool { - struct hashtable *h; -}; - -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); - -#endif diff --git a/daemon/include/jhash.h b/daemon/include/jhash.h deleted file mode 100644 index 38b8780..0000000 --- a/daemon/include/jhash.h +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef _LINUX_JHASH_H -#define _LINUX_JHASH_H - -#define u32 unsigned int -#define u8 char - -/* jhash.h: Jenkins hash support. - * - * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net) - * - * http://burtleburtle.net/bob/hash/ - * - * These are the credits from Bob's sources: - * - * lookup2.c, by Bob Jenkins, December 1996, Public Domain. - * hash(), hash2(), hash3, and mix() are externally useful functions. - * Routines to test the hash are included if SELF_TEST is defined. - * You can use this free for any purpose. It has no warranty. - * - * Copyright (C) 2003 David S. Miller (davem@redhat.com) - * - * I've modified Bob's hash to be useful in the Linux kernel, and - * any bugs present are surely my fault. -DaveM - */ - -/* NOTE: Arguments are modified. */ -#define __jhash_mix(a, b, c) \ -{ \ - a -= b; a -= c; a ^= (c>>13); \ - b -= c; b -= a; b ^= (a<<8); \ - c -= a; c -= b; c ^= (b>>13); \ - a -= b; a -= c; a ^= (c>>12); \ - b -= c; b -= a; b ^= (a<<16); \ - c -= a; c -= b; c ^= (b>>5); \ - a -= b; a -= c; a ^= (c>>3); \ - b -= c; b -= a; b ^= (a<<10); \ - c -= a; c -= b; c ^= (b>>15); \ -} - -/* The golden ration: an arbitrary value */ -#define JHASH_GOLDEN_RATIO 0x9e3779b9 - -/* The most generic version, hashes an arbitrary sequence - * of bytes. No alignment or length assumptions are made about - * the input key. - */ -static inline u32 jhash(const void *key, u32 length, u32 initval) -{ - u32 a, b, c, len; - const u8 *k = key; - - len = length; - a = b = JHASH_GOLDEN_RATIO; - c = initval; - - while (len >= 12) { - a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24)); - b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24)); - c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24)); - - __jhash_mix(a,b,c); - - k += 12; - len -= 12; - } - - c += length; - switch (len) { - case 11: c += ((u32)k[10]<<24); - case 10: c += ((u32)k[9]<<16); - case 9 : c += ((u32)k[8]<<8); - case 8 : b += ((u32)k[7]<<24); - case 7 : b += ((u32)k[6]<<16); - case 6 : b += ((u32)k[5]<<8); - case 5 : b += k[4]; - case 4 : a += ((u32)k[3]<<24); - case 3 : a += ((u32)k[2]<<16); - case 2 : a += ((u32)k[1]<<8); - case 1 : a += k[0]; - }; - - __jhash_mix(a,b,c); - - return c; -} - -/* A special optimized version that handles 1 or more of u32s. - * The length parameter here is the number of u32s in the key. - */ -static inline u32 jhash2(u32 *k, u32 length, u32 initval) -{ - u32 a, b, c, len; - - a = b = JHASH_GOLDEN_RATIO; - c = initval; - len = length; - - while (len >= 3) { - a += k[0]; - b += k[1]; - c += k[2]; - __jhash_mix(a, b, c); - k += 3; len -= 3; - } - - c += length * 4; - - switch (len) { - case 2 : b += k[1]; - case 1 : a += k[0]; - }; - - __jhash_mix(a,b,c); - - return c; -} - - -/* A special ultra-optimized versions that knows they are hashing exactly - * 3, 2 or 1 word(s). - * - * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally - * done at the end is not done here. - */ -static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval) -{ - a += JHASH_GOLDEN_RATIO; - b += JHASH_GOLDEN_RATIO; - c += initval; - - __jhash_mix(a, b, c); - - return c; -} - -static inline u32 jhash_2words(u32 a, u32 b, u32 initval) -{ - return jhash_3words(a, b, 0, initval); -} - -static inline u32 jhash_1word(u32 a, u32 initval) -{ - return jhash_3words(a, 0, 0, initval); -} - -#endif /* _LINUX_JHASH_H */ diff --git a/daemon/include/linux_list.h b/daemon/include/linux_list.h deleted file mode 100644 index 57b56d7..0000000 --- a/daemon/include/linux_list.h +++ /dev/null @@ -1,725 +0,0 @@ -#ifndef _LINUX_LIST_H -#define _LINUX_LIST_H - -#undef offsetof -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) - -/** - * container_of - cast a member of a structure out to the containing structure - * - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -/* - * Check at compile time that something is of a particular type. - * Always evaluates to 1 so you may use it easily in comparisons. - */ -#define typecheck(type,x) \ -({ type __dummy; \ - typeof(x) __dummy2; \ - (void)(&__dummy == &__dummy2); \ - 1; \ -}) - -#define prefetch(x) 1 - -/* empty define to make this work in userspace -HW */ -#ifndef smp_wmb -#define smp_wmb() -#endif - -/* - * These are non-NULL pointers that will result in page faults - * under normal circumstances, used to verify that nobody uses - * non-initialized list entries. - */ -#define LIST_POISON1 ((void *) 0x00100100) -#define LIST_POISON2 ((void *) 0x00200200) - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add_rcu(struct list_head * new, - struct list_head * prev, struct list_head * next) -{ - new->next = next; - new->prev = prev; - smp_wmb(); - next->prev = new; - prev->next = new; -} - -/** - * list_add_rcu - add a new entry to rcu-protected list - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - * - * The caller must take whatever precautions are necessary - * (such as holding appropriate locks) to avoid racing - * with another list-mutation primitive, such as list_add_rcu() - * or list_del_rcu(), running on this same list. - * However, it is perfectly legal to run concurrently with - * the _rcu list-traversal primitives, such as - * list_for_each_entry_rcu(). - */ -static inline void list_add_rcu(struct list_head *new, struct list_head *head) -{ - __list_add_rcu(new, head, head->next); -} - -/** - * list_add_tail_rcu - add a new entry to rcu-protected list - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - * - * The caller must take whatever precautions are necessary - * (such as holding appropriate locks) to avoid racing - * with another list-mutation primitive, such as list_add_tail_rcu() - * or list_del_rcu(), running on this same list. - * However, it is perfectly legal to run concurrently with - * the _rcu list-traversal primitives, such as - * list_for_each_entry_rcu(). - */ -static inline void list_add_tail_rcu(struct list_head *new, - struct list_head *head) -{ - __list_add_rcu(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_del(struct list_head * prev, struct list_head * next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is - * in an undefined state. - */ -static inline void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->next = LIST_POISON1; - entry->prev = LIST_POISON2; -} - -/** - * list_del_rcu - deletes entry from list without re-initialization - * @entry: the element to delete from the list. - * - * Note: list_empty on entry does not return true after this, - * the entry is in an undefined state. It is useful for RCU based - * lockfree traversal. - * - * In particular, it means that we can not poison the forward - * pointers that may still be used for walking the list. - * - * The caller must take whatever precautions are necessary - * (such as holding appropriate locks) to avoid racing - * with another list-mutation primitive, such as list_del_rcu() - * or list_add_rcu(), running on this same list. - * However, it is perfectly legal to run concurrently with - * the _rcu list-traversal primitives, such as - * list_for_each_entry_rcu(). - * - * Note that the caller is not permitted to immediately free - * the newly deleted entry. Instead, either synchronize_kernel() - * or call_rcu() must be used to defer freeing until an RCU - * grace period has elapsed. - */ -static inline void list_del_rcu(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->prev = LIST_POISON2; -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static inline void list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/** - * list_move - delete from one list and add as another's head - * @list: the entry to move - * @head: the head that will precede our entry - */ -static inline void list_move(struct list_head *list, struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add(list, head); -} - -/** - * list_move_tail - delete from one list and add as another's tail - * @list: the entry to move - * @head: the head that will follow our entry - */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add_tail(list, head); -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static inline int list_empty(const struct list_head *head) -{ - return head->next == head; -} - -/** - * list_empty_careful - tests whether a list is - * empty _and_ checks that no other CPU might be - * in the process of still modifying either member - * - * NOTE: using list_empty_careful() without synchronization - * can only be safe if the only activity that can happen - * to the list entry is list_del_init(). Eg. it cannot be used - * if another CPU could re-list_add() it. - * - * @head: the list to test. - */ -static inline int list_empty_careful(const struct list_head *head) -{ - struct list_head *next = head->next; - return (next == head) && (next == head->prev); -} - -static inline void __list_splice(struct list_head *list, - struct list_head *head) -{ - struct list_head *first = list->next; - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static inline void list_splice(struct list_head *list, struct list_head *head) -{ - if (!list_empty(list)) - __list_splice(list, head); -} - -/** - * list_splice_init - join two lists and reinitialise the emptied list. - * @list: the new list to add. - * @head: the place to add it in the first list. - * - * The list at @list is reinitialised - */ -static inline void list_splice_init(struct list_head *list, - struct list_head *head) -{ - if (!list_empty(list)) { - __list_splice(list, head); - INIT_LIST_HEAD(list); - } -} - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - container_of(ptr, type, member) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next, prefetch(pos->next); pos != (head); \ - pos = pos->next, prefetch(pos->next)) - -/** - * __list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - * - * This variant differs from list_for_each() in that it's the - * simplest possible list iteration code, no prefetching is done. - * Use this for code that knows the list to be very short (empty - * or 1 entry) most of the time. - */ -#define __list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -/** - * list_for_each_prev - iterate over a list backwards - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ - pos = pos->prev, prefetch(pos->prev)) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/** - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next)) - -/** - * list_for_each_entry_reverse - iterate backwards over list of given type. - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_reverse(pos, head, member) \ - for (pos = list_entry((head)->prev, typeof(*pos), member), \ - prefetch(pos->member.prev); \ - &pos->member != (head); \ - pos = list_entry(pos->member.prev, typeof(*pos), member), \ - prefetch(pos->member.prev)) - -/** - * list_prepare_entry - prepare a pos entry for use as a start point in - * list_for_each_entry_continue - * @pos: the type * to use as a start point - * @head: the head of the list - * @member: the name of the list_struct within the struct. - */ -#define list_prepare_entry(pos, head, member) \ - ((pos) ? : list_entry(head, typeof(*pos), member)) - -/** - * list_for_each_entry_continue - iterate over list of given type - * continuing after existing point - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_continue(pos, head, member) \ - for (pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next)) - -/** - * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @pos: the type * to use as a loop counter. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/** - * list_for_each_rcu - iterate over an rcu-protected list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - * - * This list-traversal primitive may safely run concurrently with - * the _rcu list-mutation primitives such as list_add_rcu() - * as long as the traversal is guarded by rcu_read_lock(). - */ -#define list_for_each_rcu(pos, head) \ - for (pos = (head)->next, prefetch(pos->next); pos != (head); \ - pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next)) - -#define __list_for_each_rcu(pos, head) \ - for (pos = (head)->next; pos != (head); \ - pos = pos->next, ({ smp_read_barrier_depends(); 0;})) - -/** - * list_for_each_safe_rcu - iterate over an rcu-protected list safe - * against removal of list entry - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - * - * This list-traversal primitive may safely run concurrently with - * the _rcu list-mutation primitives such as list_add_rcu() - * as long as the traversal is guarded by rcu_read_lock(). - */ -#define list_for_each_safe_rcu(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next) - -/** - * list_for_each_entry_rcu - iterate over rcu list of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * This list-traversal primitive may safely run concurrently with - * the _rcu list-mutation primitives such as list_add_rcu() - * as long as the traversal is guarded by rcu_read_lock(). - */ -#define list_for_each_entry_rcu(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member), \ - ({ smp_read_barrier_depends(); 0;}), \ - prefetch(pos->member.next)) - - -/** - * list_for_each_continue_rcu - iterate over an rcu-protected list - * continuing after existing point. - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - * - * This list-traversal primitive may safely run concurrently with - * the _rcu list-mutation primitives such as list_add_rcu() - * as long as the traversal is guarded by rcu_read_lock(). - */ -#define list_for_each_continue_rcu(pos, head) \ - for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \ - (pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next)) - -/* - * Double linked lists with a single pointer list head. - * Mostly useful for hash tables where the two pointer list head is - * too wasteful. - * You lose the ability to access the tail in O(1). - */ - -struct hlist_head { - struct hlist_node *first; -}; - -struct hlist_node { - struct hlist_node *next, **pprev; -}; - -#define HLIST_HEAD_INIT { .first = NULL } -#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } -#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) -#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL) - -static inline int hlist_unhashed(const struct hlist_node *h) -{ - return !h->pprev; -} - -static inline int hlist_empty(const struct hlist_head *h) -{ - return !h->first; -} - -static inline void __hlist_del(struct hlist_node *n) -{ - struct hlist_node *next = n->next; - struct hlist_node **pprev = n->pprev; - *pprev = next; - if (next) - next->pprev = pprev; -} - -static inline void hlist_del(struct hlist_node *n) -{ - __hlist_del(n); - n->next = LIST_POISON1; - n->pprev = LIST_POISON2; -} - -/** - * hlist_del_rcu - deletes entry from hash list without re-initialization - * @n: the element to delete from the hash list. - * - * Note: list_unhashed() on entry does not return true after this, - * the entry is in an undefined state. It is useful for RCU based - * lockfree traversal. - * - * In particular, it means that we can not poison the forward - * pointers that may still be used for walking the hash list. - * - * The caller must take whatever precautions are necessary - * (such as holding appropriate locks) to avoid racing - * with another list-mutation primitive, such as hlist_add_head_rcu() - * or hlist_del_rcu(), running on this same list. - * However, it is perfectly legal to run concurrently with - * the _rcu list-traversal primitives, such as - * hlist_for_each_entry(). - */ -static inline void hlist_del_rcu(struct hlist_node *n) -{ - __hlist_del(n); - n->pprev = LIST_POISON2; -} - -static inline void hlist_del_init(struct hlist_node *n) -{ - if (n->pprev) { - __hlist_del(n); - INIT_HLIST_NODE(n); - } -} - -#define hlist_del_rcu_init hlist_del_init - -static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) -{ - struct hlist_node *first = h->first; - n->next = first; - if (first) - first->pprev = &n->next; - h->first = n; - n->pprev = &h->first; -} - - -/** - * hlist_add_head_rcu - adds the specified element to the specified hlist, - * while permitting racing traversals. - * @n: the element to add to the hash list. - * @h: the list to add to. - * - * The caller must take whatever precautions are necessary - * (such as holding appropriate locks) to avoid racing - * with another list-mutation primitive, such as hlist_add_head_rcu() - * or hlist_del_rcu(), running on this same list. - * However, it is perfectly legal to run concurrently with - * the _rcu list-traversal primitives, such as - * hlist_for_each_entry(), but only if smp_read_barrier_depends() - * is used to prevent memory-consistency problems on Alpha CPUs. - * Regardless of the type of CPU, the list-traversal primitive - * must be guarded by rcu_read_lock(). - * - * OK, so why don't we have an hlist_for_each_entry_rcu()??? - */ -static inline void hlist_add_head_rcu(struct hlist_node *n, - struct hlist_head *h) -{ - struct hlist_node *first = h->first; - n->next = first; - n->pprev = &h->first; - smp_wmb(); - if (first) - first->pprev = &n->next; - h->first = n; -} - -/* next must be != NULL */ -static inline void hlist_add_before(struct hlist_node *n, - struct hlist_node *next) -{ - n->pprev = next->pprev; - n->next = next; - next->pprev = &n->next; - *(n->pprev) = n; -} - -static inline void hlist_add_after(struct hlist_node *n, - struct hlist_node *next) -{ - next->next = n->next; - n->next = next; - next->pprev = &n->next; - - if(next->next) - next->next->pprev = &next->next; -} - -#define hlist_entry(ptr, type, member) container_of(ptr,type,member) - -#define hlist_for_each(pos, head) \ - for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \ - pos = pos->next) - -#define hlist_for_each_safe(pos, n, head) \ - for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ - pos = n) - -/** - * hlist_for_each_entry - iterate over list of given type - * @tpos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @head: the head for your list. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry(tpos, pos, head, member) \ - for (pos = (head)->first; \ - pos && ({ prefetch(pos->next); 1;}) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_continue - iterate over a hlist continuing after existing point - * @tpos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_continue(tpos, pos, member) \ - for (pos = (pos)->next; \ - pos && ({ prefetch(pos->next); 1;}) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_from - iterate over a hlist continuing from existing point - * @tpos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_from(tpos, pos, member) \ - for (; pos && ({ prefetch(pos->next); 1;}) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @tpos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @n: another &struct hlist_node to use as temporary storage - * @head: the head for your list. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ - for (pos = (head)->first; \ - pos && ({ n = pos->next; 1; }) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = n) - -/** - * hlist_for_each_entry_rcu - iterate over rcu list of given type - * @pos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @head: the head for your list. - * @member: the name of the hlist_node within the struct. - * - * This list-traversal primitive may safely run concurrently with - * the _rcu list-mutation primitives such as hlist_add_rcu() - * as long as the traversal is guarded by rcu_read_lock(). - */ -#define hlist_for_each_entry_rcu(tpos, pos, head, member) \ - for (pos = (head)->first; \ - pos && ({ prefetch(pos->next); 1;}) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next, ({ smp_read_barrier_depends(); 0; }) ) - -#endif diff --git a/daemon/include/local.h b/daemon/include/local.h deleted file mode 100644 index 350b8bf..0000000 --- a/daemon/include/local.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _LOCAL_SOCKET_H_ -#define _LOCAL_SOCKET_H_ - -#include - -#ifndef UNIX_PATH_MAX -#define UNIX_PATH_MAX 108 -#endif - -struct local_conf { - int backlog; - int reuseaddr; - char path[UNIX_PATH_MAX]; -}; - -/* local server */ -int local_server_create(struct local_conf *conf); -void local_server_destroy(int fd); -int do_local_server_step(int fd, void *data, - void (*process)(int fd, void *data)); - -/* local client */ -int local_client_create(struct local_conf *conf); -void local_client_destroy(int fd); -int do_local_client_step(int fd, void (*process)(char *buf)); -int do_local_request(int, struct local_conf *,void (*step)(char *buf)); -void local_step(char *buf); - -#endif diff --git a/daemon/include/log.h b/daemon/include/log.h deleted file mode 100644 index 9ecff30..0000000 --- a/daemon/include/log.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _LOG_H_ -#define _LOG_H_ - -#include - -FILE *init_log(char *filename); -void dlog(FILE *fd, char *format, ...); -void close_log(FILE *fd); - -#endif diff --git a/daemon/include/mcast.h b/daemon/include/mcast.h deleted file mode 100644 index 0f3e3cd..0000000 --- a/daemon/include/mcast.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef _MCAST_H_ -#define _MCAST_H_ - -#include - -struct mcast_conf { - int ipproto; - int backlog; - int reuseaddr; - unsigned short port; - union { - struct in_addr inet_addr; - struct in6_addr inet_addr6; - } in; - union { - struct in_addr interface_addr; - struct in6_addr interface_addr6; - } ifa; -}; - -struct mcast_stats { - u_int64_t bytes; - u_int64_t messages; - u_int64_t error; -}; - -struct mcast_sock { - int fd; - union { - struct sockaddr_in ipv4; - struct sockaddr_in6 ipv6; - } addr; - struct mcast_stats stats; -}; - -struct mcast_sock *mcast_server_create(struct mcast_conf *conf); -void mcast_server_destroy(struct mcast_sock *m); - -struct mcast_sock *mcast_client_create(struct mcast_conf *conf); -void mcast_client_destroy(struct mcast_sock *m); - -int mcast_send(struct mcast_sock *m, void *data, int size); -int mcast_recv(struct mcast_sock *m, void *data, int size); - -struct mcast_stats *mcast_get_stats(struct mcast_sock *m); -void mcast_dump_stats(int fd, struct mcast_sock *s, struct mcast_sock *r); - -#endif diff --git a/daemon/include/network.h b/daemon/include/network.h deleted file mode 100644 index dab50db..0000000 --- a/daemon/include/network.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _NETWORK_H_ -#define _NETWORK_H_ - -#include - -struct nlnetwork { - u_int16_t flags; - u_int16_t checksum; - u_int32_t seq; -}; - -struct nlnetwork_ack { - u_int16_t flags; - u_int16_t checksum; - u_int32_t seq; - u_int32_t from; - u_int32_t to; -}; - -enum { - NET_HELLO_BIT = 0, - NET_HELLO = (1 << NET_HELLO_BIT), - - NET_RESYNC_BIT = 1, - NET_RESYNC = (1 << NET_RESYNC_BIT), - - NET_NACK_BIT = 2, - NET_NACK = (1 << NET_NACK_BIT), - - NET_ACK_BIT = 3, - NET_ACK = (1 << NET_ACK_BIT), -}; - -#endif diff --git a/daemon/include/slist.h b/daemon/include/slist.h deleted file mode 100644 index ab7fa34..0000000 --- a/daemon/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 && ({ prefetch(pos.next); 1; }); \ - 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/daemon/include/state_helper.h b/daemon/include/state_helper.h deleted file mode 100644 index 1ed0b79..0000000 --- a/daemon/include/state_helper.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _STATE_HELPER_H_ -#define _STATE_HELPER_H_ - -enum { - ST_H_SKIP, - ST_H_REPLICATE -}; - -struct state_replication_helper { - u_int8_t proto; - unsigned int state; - - int (*verdict)(const struct state_replication_helper *h, - const struct nf_conntrack *ct); -}; - -int state_helper_verdict(int type, struct nf_conntrack *ct); -void state_helper_register(struct state_replication_helper *h, int state); - -#endif diff --git a/daemon/include/sync.h b/daemon/include/sync.h deleted file mode 100644 index 7756c87..0000000 --- a/daemon/include/sync.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _SYNC_HOOKS_H_ -#define _SYNC_HOOKS_H_ - -struct nlnetwork; -struct us_conntrack; - -struct sync_mode { - int internal_cache_flags; - int external_cache_flags; - struct cache_extra *internal_cache_extra; - struct cache_extra *external_cache_extra; - - int (*init)(void); - void (*kill)(void); - int (*local)(int fd, int type, void *data); - int (*pre_recv)(const struct nlnetwork *net); - void (*post_send)(const struct nlnetwork *net, struct us_conntrack *u); -}; - -extern struct sync_mode notrack; -extern struct sync_mode nack; - -#endif diff --git a/daemon/include/us-conntrack.h b/daemon/include/us-conntrack.h deleted file mode 100644 index 3d71e22..0000000 --- a/daemon/include/us-conntrack.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _US_CONNTRACK_H_ -#define _US_CONNTRACK_H_ - -#include - -/* be careful, do not modify the layout */ -struct us_conntrack { - struct nf_conntrack *ct; - struct cache *cache; /* add new attributes here */ - char data[0]; -}; - -#endif diff --git a/daemon/src/Makefile.am b/daemon/src/Makefile.am deleted file mode 100644 index 5d1c6cb..0000000 --- a/daemon/src/Makefile.am +++ /dev/null @@ -1,22 +0,0 @@ -include $(top_srcdir)/Make_global.am - -YACC=@YACC@ -d - -CLEANFILES = read_config_yy.c read_config_lex.c - -sbin_PROGRAMS = conntrackd -conntrackd_SOURCES = alarm.c main.c run.c hash.c buffer.c \ - local.c log.c mcast.c netlink.c proxy.c lock.c \ - ignore_pool.c \ - cache.c cache_iterators.c \ - cache_lifetime.c cache_timer.c \ - sync-mode.c sync-notrack.c sync-nack.c \ - traffic_stats.c stats-mode.c \ - network.c checksum.c \ - state_helper.c state_helper_tcp.c \ - read_config_yy.y read_config_lex.l - -conntrackd_LDFLAGS = $(all_libraries) -lnfnetlink -lnetfilter_conntrack \ - -lpthread - -EXTRA_DIST = read_config_yy.h diff --git a/daemon/src/alarm.c b/daemon/src/alarm.c deleted file mode 100644 index 1a465c2..0000000 --- a/daemon/src/alarm.c +++ /dev/null @@ -1,141 +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 -#include "linux_list.h" -#include "conntrackd.h" -#include "alarm.h" -#include "jhash.h" -#include -#include -#include - -/* alarm cascade */ -#define ALARM_CASCADE_SIZE 10 -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)); -} - -void destroy_alarm(struct alarm_list *t) -{ - free(t); -} - -void set_alarm_expiration(struct alarm_list *t, unsigned long expires) -{ - t->expires = expires; -} - -void set_alarm_function(struct alarm_list *t, - void (*fcn)(struct alarm_list *a, void *data)) -{ - t->function = fcn; -} - -void set_alarm_data(struct alarm_list *t, void *data) -{ - t->data = data; -} - -void init_alarm(struct alarm_list *t) -{ - INIT_LIST_HEAD(&t->head); - - t->expires = 0; - t->data = 0; - t->function = NULL; -} - -void add_alarm(struct alarm_list *alarm) -{ - unsigned int pos = jhash(alarm, sizeof(alarm), 0) % ALARM_CASCADE_SIZE; - - list_add(&alarm->head, &alarm_cascade[pos]); -} - -void del_alarm(struct alarm_list *alarm) -{ - list_del(&alarm->head); -} - -int mod_alarm(struct alarm_list *alarm, unsigned long expires) -{ - alarm->expires = expires; - return 0; -} - -void __run_alarms() -{ - 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; - - t->expires--; - 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 i; - - alarm_cascade = malloc(sizeof(struct list_head) * ALARM_CASCADE_SIZE); - if (alarm_cascade == NULL) - return -1; - - for (i=0; i - * - * 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" - -struct buffer *buffer_create(size_t max_size) -{ - struct buffer *b; - - b = malloc(sizeof(struct buffer)); - if (b == NULL) - return NULL; - memset(b, 0, sizeof(struct buffer)); - - b->max_size = max_size; - INIT_LIST_HEAD(&b->head); - pthread_mutex_init(&b->lock, NULL); - - return b; -} - -void buffer_destroy(struct buffer *b) -{ - struct list_head *i, *tmp; - struct buffer_node *node; - - pthread_mutex_lock(&b->lock); - 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); -} - -static struct buffer_node *buffer_node_create(const void *data, size_t size) -{ - struct buffer_node *n; - - n = malloc(sizeof(struct buffer_node) + size); - if (n == NULL) - return NULL; - - INIT_LIST_HEAD(&n->head); - n->size = size; - memcpy(n->data, data, size); - - return n; -} - -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; - ret = -1; - goto err; - } - -retry: - /* buffer is full: kill the oldest entry */ - if (b->cur_size + size > b->max_size) { - n = (struct buffer_node *) b->head.prev; - list_del(b->head.prev); - b->cur_size -= n->size; - free(n); - goto retry; - } - - n = buffer_node_create(data, size); - if (n == NULL) { - ret = -1; - goto err; - } - - list_add(&n->head, &b->head); - b->cur_size += size; - -err: - pthread_mutex_unlock(&b->lock); - return ret; -} - -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; - 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)) -{ - 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); -} diff --git a/daemon/src/cache.c b/daemon/src/cache.c deleted file mode 100644 index 6f7442b..0000000 --- a/daemon/src/cache.c +++ /dev/null @@ -1,446 +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 "jhash.h" -#include "hash.h" -#include "conntrackd.h" -#include -#include -#include "us-conntrack.h" -#include "cache.h" -#include "debug.h" - -static u_int32_t hash(const void *data, 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(u_int32_t), - ((nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16) | - (nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)))); - - b = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV4_DST), sizeof(u_int32_t), - ((nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16) | - (nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)))); - - return jhash_2words(a, b, 0) % table->hashsize; -} - -static u_int32_t hash6(const void *data, 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(u_int32_t), - ((nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16) | - (nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)))); - - b = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV6_DST), sizeof(u_int32_t), - ((nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16) | - (nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)))); - - return jhash_2words(a, b, 0) % table->hashsize; -} - -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) == - 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 compare(const void *data1, const void *data2) -{ - 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) == - 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 void *data1, const void *data2) -{ - 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)); -} - -struct cache_feature *cache_feature[CACHE_MAX_FEATURE] = { - [TIMER_FEATURE] = &timer_feature, - [LIFETIME_FEATURE] = &lifetime_feature, -}; - -struct cache *cache_create(char *name, - unsigned int features, - u_int8_t proto, - struct cache_extra *extra) -{ - size_t size = sizeof(struct us_conntrack); - int i, j = 0; - struct cache *c; - struct cache_feature *feature_array[CACHE_MAX_FEATURE] = {}; - unsigned int feature_offset[CACHE_MAX_FEATURE] = {}; - unsigned int feature_type[CACHE_MAX_FEATURE] = {}; - - c = malloc(sizeof(struct cache)); - if (!c) - return NULL; - memset(c, 0, sizeof(struct cache)); - - strcpy(c->name, name); - - for (i = 0; i < CACHE_MAX_FEATURE; i++) { - if ((1 << i) & features) { - feature_array[j] = cache_feature[i]; - feature_offset[j] = size; - feature_type[i] = j; - size += cache_feature[i]->size; - j++; - } - } - - memcpy(c->feature_type, feature_type, sizeof(feature_type)); - - c->features = malloc(sizeof(struct cache_feature) * j); - if (!c->features) { - free(c); - return NULL; - } - memcpy(c->features, feature_array, sizeof(struct cache_feature) * j); - c->num_features = j; - - c->extra_offset = size; - c->extra = extra; - if (extra) - size += extra->size; - - c->feature_offset = malloc(sizeof(unsigned int) * j); - if (!c->feature_offset) { - free(c->features); - free(c); - return NULL; - } - 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; - } - - if (!c->h) { - free(c->features); - free(c->feature_offset); - free(c); - return NULL; - } - - return c; -} - -void cache_destroy(struct cache *c) -{ - lock(); - hashtable_destroy(c->h); - unlock(); - free(c->features); - free(c->feature_offset); - free(c); -} - -static struct us_conntrack *__add(struct cache *c, struct nf_conntrack *ct) -{ - int i; - size_t size = c->h->datasize; - char buf[size]; - struct us_conntrack *u = (struct us_conntrack *) buf; - struct nf_conntrack *newct; - - memset(u, 0, size); - - u->cache = c; - if ((u->ct = newct = nfct_new()) == NULL) { - errno = ENOMEM; - return 0; - } - memcpy(u->ct, ct, nfct_sizeof(ct)); - - u = hashtable_add(c->h, u); - if (u) { - void *data = u->data; - - for (i = 0; i < c->num_features; i++) { - c->features[i]->add(u, data); - data += c->features[i]->size; - } - - if (c->extra) - c->extra->add(u, ((void *) u) + c->extra_offset); - - return u; - } - free(newct); - - return NULL; -} - -struct us_conntrack *__cache_add(struct cache *c, struct nf_conntrack *ct) -{ - struct us_conntrack *u; - - u = __add(c, ct); - if (u) { - c->add_ok++; - return u; - } - c->add_fail++; - - 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; - char buf[size]; - struct us_conntrack *u = (struct us_conntrack *) buf; - - u->ct = ct; - - u = (struct us_conntrack *) hashtable_test(c->h, u); - if (u) { - int i; - void *data = u->data; - - for (i = 0; i < c->num_features; i++) { - c->features[i]->update(u, data); - data += c->features[i]->size; - } - - if (c->extra) - c->extra->update(u, ((void *) u) + c->extra_offset); - - 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)); - - return u; - } - return NULL; -} - -struct us_conntrack *__cache_update(struct cache *c, struct nf_conntrack *ct) -{ - struct us_conntrack *u; - - u = __update(c, ct); - if (u) { - c->upd_ok++; - return u; - } - c->upd_fail++; - - return NULL; -} - -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; -} - -struct us_conntrack *cache_update_force(struct cache *c, - struct nf_conntrack *ct) -{ - 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; -} - -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; - - lock(); - ret = hashtable_test(c->h, u); - unlock(); - - return ret != NULL; -} - -static int __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; - - u = (struct us_conntrack *) hashtable_test(c->h, u); - if (u) { - int i; - void *data = u->data; - struct nf_conntrack *p = u->ct; - - for (i = 0; i < c->num_features; i++) { - c->features[i]->destroy(u, data); - data += c->features[i]->size; - } - - if (c->extra) - c->extra->destroy(u, ((void *) u) + c->extra_offset); - - hashtable_del(c->h, u); - free(p); - return 1; - } - return 0; -} - -int __cache_del(struct cache *c, struct nf_conntrack *ct) -{ - if (__del(c, ct)) { - c->del_ok++; - return 1; - } - c->del_fail++; - - 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; -} - -void *cache_get_extra(struct cache *c, void *data) -{ - return data + c->extra_offset; -} - -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" - "connections updated:\t\t%12u\tfailed:\t%12u\n" - "connections destroyed:\t\t%12u\tfailed:\t%12u\n\n", - c->name, - hashtable_counter(c->h), - c->add_ok, - c->add_fail, - c->upd_ok, - c->upd_fail, - c->del_ok, - c->del_fail); - unlock(); - send(fd, buf, size, 0); -} diff --git a/daemon/src/cache_iterators.c b/daemon/src/cache_iterators.c deleted file mode 100644 index 5d5d22b..0000000 --- a/daemon/src/cache_iterators.c +++ /dev/null @@ -1,229 +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 "jhash.h" -#include "hash.h" -#include "conntrackd.h" -#include -#include -#include "us-conntrack.h" -#include "debug.h" - -struct __dump_container { - int fd; - int type; -}; - -static int do_dump(void *data1, void *data2) -{ - char buf[1024]; - int size; - struct __dump_container *container = data1; - struct us_conntrack *u = data2; - void *data = u->data; - int i; - - memset(buf, 0, sizeof(buf)); - size = nfct_snprintf(buf, - sizeof(buf), - u->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; - } - } - 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 - }; - - lock(); - hashtable_iterate(c->h, (void *) &tmp, do_dump); - unlock(); -} - -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; - - 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); - - /* - * Set a reduced timeout for candidate-to-be-committed - * conntracks that live in the external cache - */ - nfct_set_attr_u32(ct, ATTR_TIMEOUT, CONFIG(commit_timeout)); - - ret = nfct_build_query(STATE(subsys_sync), - NFCT_Q_CREATE, - ct, - nlh, - sizeof(buf)); - - free(ct); - - if (ret == -1) { - /* XXX: Please cleanup this debug crap, default in logfile */ - debug("--- failed to build: %s --- \n", strerror(errno)); - return 0; - } - - ret = nfnl_query(STATE(sync), nlh); - if (ret == -1) { - switch(errno) { - case EEXIST: - c->commit_exist++; - break; - default: - 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 */ - return 0; -} - -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; - - lock(); - hashtable_iterate(c->h, c, do_commit); - unlock(); - - /* 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; - - /* log results */ - dlog(STATE(log), "Committed %u new entries", commit_ok); - - if (commit_exist) - dlog(STATE(log), "%u entries ignored, " - "already exist", commit_exist); - if (commit_fail) - dlog(STATE(log), "%u entries can't be " - "committed", commit_fail); -} - -static int do_flush(void *data1, void *data2) -{ - struct cache *c = data1; - struct us_conntrack *u = data2; - void *data = u->data; - int i; - - for (i = 0; i < c->num_features; i++) { - c->features[i]->destroy(u, data); - data += c->features[i]->size; - } - free(u->ct); - - return 0; -} - -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; - char buf[4096]; - struct nlnetwork *net = (struct nlnetwork *) buf; - - ret = build_network_msg(NFCT_Q_UPDATE, - STATE(subsys_sync), - u->ct, - buf, - sizeof(buf)); - if (ret == -1) - debug_ct(u->ct, "failed to build"); - - mcast_send_netmsg(STATE_SYNC(mcast_client), net); - STATE_SYNC(mcast_sync)->post_send(net, 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/daemon/src/cache_lifetime.c b/daemon/src/cache_lifetime.c deleted file mode 100644 index ae54df2..0000000 --- a/daemon/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 "conntrackd.h" -#include "us-conntrack.h" -#include "cache.h" -#include "alarm.h" - -static void lifetime_add(struct us_conntrack *u, void *data) -{ - long *lifetime = data; - struct timeval tv; - - gettimeofday(&tv, NULL); - - *lifetime = tv.tv_sec; -} - -static void lifetime_update(struct us_conntrack *u, void *data) -{ -} - -static void lifetime_destroy(struct us_conntrack *u, void *data) -{ -} - -static int lifetime_dump(struct us_conntrack *u, - 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/daemon/src/cache_timer.c b/daemon/src/cache_timer.c deleted file mode 100644 index 213b59a..0000000 --- a/daemon/src/cache_timer.c +++ /dev/null @@ -1,72 +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 "conntrackd.h" -#include "us-conntrack.h" -#include "cache.h" -#include "alarm.h" - -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); -} - -static void timer_add(struct us_conntrack *u, void *data) -{ - struct alarm_list *alarm = data; - - init_alarm(alarm); - set_alarm_expiration(alarm, CONFIG(cache_timeout)); - set_alarm_data(alarm, u); - set_alarm_function(alarm, timeout); - add_alarm(alarm); -} - -static void timer_update(struct us_conntrack *u, void *data) -{ - struct alarm_list *alarm = data; - mod_alarm(alarm, CONFIG(cache_timeout)); -} - -static void timer_destroy(struct us_conntrack *u, void *data) -{ - struct alarm_list *alarm = data; - del_alarm(alarm); -} - -static int timer_dump(struct us_conntrack *u, void *data, char *buf, int type) -{ - struct alarm_list *alarm = data; - - if (type == NFCT_O_XML) - return 0; - - return sprintf(buf, " [expires in %ds]", alarm->expires); -} - -struct cache_feature timer_feature = { - .size = sizeof(struct alarm_list), - .add = timer_add, - .update = timer_update, - .destroy = timer_destroy, - .dump = timer_dump -}; diff --git a/daemon/src/checksum.c b/daemon/src/checksum.c deleted file mode 100644 index 41866ff..0000000 --- a/daemon/src/checksum.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Extracted from RFC 1071 with some minor changes to fix compilation on GCC, - * this can probably be improved - * --pablo 11/feb/07 - */ - -#include - -unsigned short do_csum(const void *addr, unsigned int count) -{ - unsigned int sum = 0; - - /* checksumming disabled, just skip */ - if (CONFIG(flags) & DONT_CHECKSUM) - return 0; - - while(count > 1) { - /* This is the inner loop */ - sum += *((unsigned short *) addr++); - count -= 2; - } - - /* Add left-over byte, if any */ - if(count > 0) - sum += *((unsigned char *) addr); - - /* Fold 32-bit sum to 16 bits */ - while (sum>>16) - sum = (sum & 0xffff) + (sum >> 16); - - return ~sum; -} diff --git a/daemon/src/hash.c b/daemon/src/hash.c deleted file mode 100644 index 274a140..0000000 --- a/daemon/src/hash.c +++ /dev/null @@ -1,199 +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. - * - * Description: generic hash table implementation - */ - -#include -#include -#include -#include -#include -#include "slist.h" -#include "hash.h" - - -struct hashtable_node *hashtable_alloc_node(int datasize, void *data) -{ - struct hashtable_node *n; - int size = sizeof(struct hashtable_node) + datasize; - - n = malloc(size); - if (!n) - return NULL; - memset(n, 0, size); - 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, - u_int32_t (*hash)(const void *data, struct hashtable *table), - int (*compare)(const void *data1, const void *data2)) -{ - int i; - struct hashtable *h; - struct hashtype *t; - int size = sizeof(struct hashtable) - + hashsize * sizeof(struct slist_head); - - h = (struct hashtable *) malloc(size); - if (!h) { - errno = ENOMEM; - return NULL; - } - - memset(h, 0, size); - for (i=0; imembers[i]); - - h->hashsize = hashsize; - h->limit = limit; - h->datasize = datasize; - h->hash = hash; - h->compare = compare; - - return h; -} - -void hashtable_destroy(struct hashtable *h) -{ - hashtable_flush(h); - free(h); -} - -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) { - 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; -} - -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); - - slist_for_each(e, &table->members[id]) { - n = slist_entry(e, struct hashtable_node, head); - if (table->compare(n->data, data)) - return n->data; - } - - errno = ENOENT; - return NULL; -} - -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); - - 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; - } - } - errno = ENOENT; - return -1; -} - -int hashtable_flush(struct hashtable *table) -{ - int i; - struct slist_head *e, *next, *prev; - 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); - } - - table->count = 0; - - return 0; -} - -int hashtable_iterate(struct hashtable *table, void *data, - int (*iterate)(void *data1, void *data2)) -{ - int i; - struct slist_head *e, *next, *prev; - 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) - return -1; - } - } - return 0; -} - -unsigned int hashtable_counter(struct hashtable *table) -{ - return table->count; -} diff --git a/daemon/src/ignore_pool.c b/daemon/src/ignore_pool.c deleted file mode 100644 index 5946617..0000000 --- a/daemon/src/ignore_pool.c +++ /dev/null @@ -1,136 +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 "jhash.h" -#include "hash.h" -#include "conntrackd.h" -#include "ignore.h" -#include "debug.h" -#include - -#define IGNORE_POOL_SIZE 32 -#define IGNORE_POOL_LIMIT 1024 - -static u_int32_t hash(const void *data, struct hashtable *table) -{ - const u_int32_t *ip = data; - - return jhash_1word(*ip, 0) % table->hashsize; -} - -static u_int32_t hash6(const void *data, struct hashtable *table) -{ - return jhash(data, sizeof(u_int32_t)*4, 0) % table->hashsize; -} - -static int compare(const void *data1, const void *data2) -{ - const u_int32_t *ip1 = data1; - const u_int32_t *ip2 = data2; - - return *ip1 == *ip2; -} - -static int compare6(const void *data1, const void *data2) -{ - return memcmp(data1, data2, sizeof(u_int32_t)*4) == 0; -} - -struct ignore_pool *ignore_pool_create(u_int8_t proto) -{ - int i, j = 0; - struct ignore_pool *ip; - - ip = malloc(sizeof(struct ignore_pool)); - if (!ip) - 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(u_int32_t), - hash, - compare); - break; - case AF_INET6: - ip->h = hashtable_create(IGNORE_POOL_SIZE, - IGNORE_POOL_LIMIT, - sizeof(u_int32_t)*4, - hash6, - compare6); - break; - } - - if (!ip->h) { - free(ip); - return NULL; - } - - return ip; -} - -void ignore_pool_destroy(struct ignore_pool *ip) -{ - hashtable_destroy(ip->h); - free(ip); -} - -int ignore_pool_add(struct ignore_pool *ip, void *data) -{ - if (!hashtable_add(ip->h, data)) - return 0; - - return 1; -} - -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)) || - hashtable_test(ip->h, nfct_get_attr(ct, ATTR_REPL_IPV4_SRC)) || - 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) -{ - 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))); -} - -int ignore_pool_test(struct ignore_pool *ip, struct nf_conntrack *ct) -{ - int ret; - - switch(nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO)) { - case AF_INET: - ret = __ignore_pool_test_ipv4(ip, ct); - break; - case AF_INET6: - ret = __ignore_pool_test_ipv6(ip, ct); - break; - default: - dlog(STATE(log), "unknown conntrack layer 3 protocol?"); - break; - } - - return ret; -} diff --git a/daemon/src/local.c b/daemon/src/local.c deleted file mode 100644 index eef70ad..0000000 --- a/daemon/src/local.c +++ /dev/null @@ -1,159 +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. - * - * Description: UNIX sockets library - */ - -#include -#include -#include -#include -#include "debug.h" - -#include "local.h" - -int local_server_create(struct local_conf *conf) -{ - int fd; - int len; - struct sockaddr_un local; - - if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - debug("local_server_create:socket"); - return -1; - } - - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &conf->reuseaddr, - sizeof(conf->reuseaddr)) == -1) { - debug("local_server_create:setsockopt"); - close(fd); - return -1; - } - - local.sun_family = AF_UNIX; - strcpy(local.sun_path, conf->path); - len = strlen(local.sun_path) + sizeof(local.sun_family); - 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; - } - - return fd; -} - -void local_server_destroy(int fd) -{ - close(fd); -} - -int do_local_server_step(int fd, void *data, - void (*process)(int fd, void *data)) -{ - int rfd; - 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"); - return -1; - } - - process(rfd, data); - close(rfd); - - return 0; -} - -int local_client_create(struct local_conf *conf) -{ - int len; - struct sockaddr_un local; - int fd; - - if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) - return -1; - - local.sun_family = AF_UNIX; - strcpy(local.sun_path, conf->path); - len = strlen(local.sun_path) + sizeof(local.sun_family); - - if (connect(fd, (struct sockaddr *) &local, len) == -1) { - close(fd); - debug("local_client_create: connect: "); - return -1; - } - - return fd; -} - -void local_client_destroy(int fd) -{ - close(fd); -} - -int do_local_client_step(int fd, void (*process)(char *buf)) -{ - int numbytes; - char buf[1024]; - - memset(buf, 0, sizeof(buf)); - while ((numbytes = recv(fd, buf, sizeof(buf)-1, 0)) > 0) { - buf[sizeof(buf)-1] = '\0'; - if (process) - process(buf); - memset(buf, 0, sizeof(buf)); - } - - return 0; -} - -void local_step(char *buf) -{ - printf(buf); -} - -int do_local_request(int request, - struct local_conf *conf, - void (*step)(char *buf)) -{ - int fd, ret; - - fd = local_client_create(conf); - if (fd == -1) - return -1; - - ret = send(fd, &request, sizeof(int), 0); - if (ret == -1) { - debug("send:"); - return -1; - } - - do_local_client_step(fd, step); - - local_client_destroy(fd); - - return 0; -} diff --git a/daemon/src/lock.c b/daemon/src/lock.c deleted file mode 100644 index cd68baf..0000000 --- a/daemon/src/lock.c +++ /dev/null @@ -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/daemon/src/log.c b/daemon/src/log.c deleted file mode 100644 index 88cadea..0000000 --- a/daemon/src/log.c +++ /dev/null @@ -1,57 +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. - * - * Description: Logging support for the conntrack daemon - */ - -#include -#include -#include -#include - -FILE *init_log(char *filename) -{ - FILE *fd; - - fd = fopen(filename, "a+"); - if (fd == NULL) { - fprintf(stderr, "can't open log file `%s'\n", filename); - return NULL; - } - - 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 close_log(FILE *fd) -{ - fclose(fd); -} diff --git a/daemon/src/main.c b/daemon/src/main.c deleted file mode 100644 index 1c75970..0000000 --- a/daemon/src/main.c +++ /dev/null @@ -1,302 +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 -#include "conntrackd.h" -#include "log.h" -#include -#include -#include -#include -#include -#include -#include "hash.h" -#include "jhash.h" - -struct ct_general_state st; -union ct_state state; - -static const char usage_daemon_commands[] = - "Daemon mode commands:\n" - " -d [options]\t\tRun in daemon mode\n" - " -S [options]\t\tRun in statistics mode\n"; - -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, flush kernel conntrack table\n" - " -i, display content of the internal cache\n" - " -e, display the content of the external cache\n" - " -k, kill conntrack daemon\n" - " -s, dump statistics\n" - " -R, resync with kernel conntrack table\n" - " -n, request resync with other node (only NACK mode)\n" - " -x, dump cache in XML format (requires -i or -e)"; - -static const char usage_options[] = - "Options:\n" - " -C [configfile], configuration file path\n"; - -void show_usage(char *progname) -{ - fprintf(stdout, "Connection tracking userspace daemon v%s\n", VERSION); - fprintf(stdout, "Usage: %s [commands] [options]\n\n", progname); - fprintf(stdout, "%s\n", usage_daemon_commands); - fprintf(stdout, "%s\n", usage_client_commands); - fprintf(stdout, "%s\n", usage_options); -} - -/* These live in run.c */ -int init(int); -void run(void); - -void set_operation_mode(int *current, int want, char *argv[]) -{ - if (*current == NOT_SET) { - *current = want; - return; - } - if (*current != want) { - show_usage(argv[0]); - fprintf(stderr, "\nError: Invalid parameters\n"); - exit(EXIT_FAILURE); - } -} - -static int check_capabilities(void) -{ - int ret; - cap_user_header_t hcap; - cap_user_data_t dcap; - - hcap = malloc(sizeof(cap_user_header_t)); - if (!hcap) - return -1; - - hcap->version = _LINUX_CAPABILITY_VERSION; - hcap->pid = getpid(); - - dcap = malloc(sizeof(cap_user_data_t)); - if (!dcap) { - free(hcap); - return -1; - } - - if (capget(hcap, dcap) == -1) { - free(hcap); - free(dcap); - return -1; - } - - ret = dcap->permitted & (1 << CAP_NET_ADMIN); - - free(hcap); - free(dcap); - - return ret; -} - -int main(int argc, char *argv[]) -{ - int ret, i, config_set = 0, action; - char config_file[PATH_MAX]; - int type = 0, mode = 0; - struct utsname u; - int version, major, minor; - - /* Check kernel version: it must be >= 2.6.18 */ - if (uname(&u) == -1) { - fprintf(stderr, "Can't retrieve kernel version via uname()\n"); - exit(EXIT_FAILURE); - } - sscanf(u.release, "%d.%d.%d", &version, &major, &minor); - if (version < 2 && major < 6) { - fprintf(stderr, "Linux kernel version must be >= 2.6.18\n"); - exit(EXIT_FAILURE); - } - - if (major == 6 && minor < 18) { - fprintf(stderr, "Linux kernel version must be >= 2.6.18\n"); - exit(EXIT_FAILURE); - } - - ret = check_capabilities(); - switch (ret) { - case -1: - fprintf(stderr, "Can't get capabilities\n"); - exit(EXIT_FAILURE); - break; - case 0: - fprintf(stderr, "You require CAP_NET_ADMIN in order " - "to run conntrackd\n"); - exit(EXIT_FAILURE); - break; - default: - break; - } - - for (i=1; i= PATH_MAX){ - config_file[PATH_MAX-1]='\0'; - fprintf(stderr, "Path to config file " - "to long. Cutting it " - "down to %d characters", - PATH_MAX); - } - config_set = 1; - break; - } - show_usage(argv[0]); - fprintf(stderr, "Missing config filename\n"); - break; - case 'F': - set_operation_mode(&type, REQUEST, argv); - action = FLUSH_MASTER; - case 'f': - set_operation_mode(&type, REQUEST, argv); - action = FLUSH_CACHE; - break; - case 'R': - set_operation_mode(&type, REQUEST, argv); - action = RESYNC_MASTER; - break; - case 'B': - set_operation_mode(&type, REQUEST, argv); - action = SEND_BULK; - break; - case 'k': - set_operation_mode(&type, REQUEST, argv); - action = KILL; - break; - case 's': - set_operation_mode(&type, REQUEST, argv); - action = STATS; - break; - case 'S': - set_operation_mode(&mode, STATS_MODE, argv); - break; - case 'n': - set_operation_mode(&type, REQUEST, argv); - action = REQUEST_DUMP; - break; - case 'x': - if (action == DUMP_INTERNAL) - action = DUMP_INT_XML; - else if (action == DUMP_EXTERNAL) - action = DUMP_EXT_XML; - else { - show_usage(argv[0]); - fprintf(stderr, "Error: Invalid parameters\n"); - exit(EXIT_FAILURE); - - } - break; - default: - show_usage(argv[0]); - fprintf(stderr, "Unknown option: %s\n", argv[i]); - return 0; - break; - } - } - - if (config_set == 0) - strcpy(config_file, DEFAULT_CONFIGFILE); - - if ((ret = init_config(config_file)) == -1) { - fprintf(stderr, "can't open config file `%s'\n", config_file); - exit(EXIT_FAILURE); - } - - /* - * Setting up logfile - */ - STATE(log) = init_log(CONFIG(logfile)); - if (!STATE(log)) { - fprintf(stdout, "can't open logfile `%s\n'", CONFIG(logfile)); - exit(EXIT_FAILURE); - } - - if (type == REQUEST) { - if (do_local_request(action, &conf.local, local_step) == -1) - fprintf(stderr, "can't connect: is conntrackd " - "running? appropiate permissions?\n"); - exit(EXIT_SUCCESS); - } - - /* - * lock file - */ - if ((ret = open(CONFIG(lockfile), O_CREAT | O_EXCL | O_TRUNC)) == -1) { - fprintf(stderr, "lockfile `%s' exists, perhaps conntrackd " - "already running?\n", CONFIG(lockfile)); - exit(EXIT_FAILURE); - } - close(ret); - - /* Daemonize conntrackd */ - if (type == DAEMON) { - pid_t pid; - - if ((pid = fork()) == -1) { - dlog(STATE(log), "fork() failed: " - "%s", strerror(errno)); - exit(EXIT_FAILURE); - } else if (pid) - exit(EXIT_SUCCESS); - - dlog(STATE(log), "--- starting in daemon mode ---"); - } else - dlog(STATE(log), "--- starting in console mode ---"); - - /* - * initialization process - */ - - if (init(mode) == -1) { - close_log(STATE(log)); - fprintf(stderr, "ERROR: conntrackd cannot start, please " - "check the logfile for more info\n"); - unlink(CONFIG(lockfile)); - exit(EXIT_FAILURE); - } - - /* - * run main process - */ - run(); -} diff --git a/daemon/src/mcast.c b/daemon/src/mcast.c deleted file mode 100644 index 9904544..0000000 --- a/daemon/src/mcast.c +++ /dev/null @@ -1,287 +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. - * - * Description: multicast socket library - */ -#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) -{ - int yes = 1; - union { - struct ip_mreq ipv4; - struct ipv6_mreq ipv6; - } mreq; - struct mcast_sock *m; - - m = (struct mcast_sock *) malloc(sizeof(struct mcast_sock)); - if (!m) - return NULL; - memset(m, 0, sizeof(struct mcast_sock)); - - switch(conf->ipproto) { - case AF_INET: - mreq.ipv4.imr_multiaddr.s_addr = conf->in.inet_addr.s_addr; - mreq.ipv4.imr_interface.s_addr =conf->ifa.interface_addr.s_addr; - - 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); - break; - - case AF_INET6: - memcpy(&mreq.ipv6.ipv6mr_multiaddr, &conf->in.inet_addr6, - sizeof(u_int32_t) * 4); - memcpy(&mreq.ipv6.ipv6mr_interface, &conf->ifa.interface_addr6, - sizeof(u_int32_t) * 4); - - m->addr.ipv6.sin6_family = AF_INET6; - m->addr.ipv6.sin6_port = htons(conf->port); - m->addr.ipv6.sin6_addr = in6addr_any; - break; - } - - if ((m->fd = socket(conf->ipproto, SOCK_DGRAM, 0)) == -1) { - debug("mcast_sock_server_create:socket"); - free(m); - return NULL; - } - - 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; - } - - if (bind(m->fd, (struct sockaddr *) &m->addr, - sizeof(struct sockaddr)) == -1) { - debug("mcast_sock_server_create:bind"); - close(m->fd); - free(m); - return NULL; - } - - - switch(conf->ipproto) { - 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; - } - break; - 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; - } - break; - } - - return m; -} - -void mcast_server_destroy(struct mcast_sock *m) -{ - close(m->fd); - free(m); -} - -static int -__mcast_client_create_ipv4(struct mcast_sock *m, struct mcast_conf *conf) -{ - int no = 0; - - m->addr.ipv4.sin_family = AF_INET; - m->addr.ipv4.sin_port = htons(conf->port); - m->addr.ipv4.sin_addr = conf->in.inet_addr; - - if (setsockopt(m->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &no, - sizeof(int)) < 0) { - debug("mcast_sock_client_create:setsockopt2"); - close(m->fd); - return -1; - } - - 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); - free(m); - return -1; - } - - return 0; -} - -static int -__mcast_client_create_ipv6(struct mcast_sock *m, struct mcast_conf *conf) -{ - int no = 0; - - m->addr.ipv6.sin6_family = AF_INET6; - m->addr.ipv6.sin6_port = htons(conf->port); - memcpy(&m->addr.ipv6.sin6_addr, - &conf->in.inet_addr6, - sizeof(struct in6_addr)); - - if (setsockopt(m->fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &no, - sizeof(int)) < 0) { - debug("mcast_sock_client_create:setsockopt2"); - close(m->fd); - return -1; - } - - if (setsockopt(m->fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, - &conf->ifa.interface_addr, - sizeof(struct in_addr)) == -1) { - debug("mcast_sock_client_create:setsockopt3"); - close(m->fd); - free(m); - return -1; - } - - return 0; -} - -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)); - if (!m) - return NULL; - memset(m, 0, sizeof(struct mcast_sock)); - - if ((m->fd = socket(conf->ipproto, SOCK_DGRAM, 0)) == -1) { - debug("mcast_sock_client_create:socket"); - return NULL; - } - - switch(conf->ipproto) { - case AF_INET: - ret = __mcast_client_create_ipv4(m, conf); - break; - case AF_INET6: - ret = __mcast_client_create_ipv6(m, conf); - break; - default: - break; - } - - if (ret == -1) { - free(m); - m = NULL; - } - - return m; -} - -void mcast_client_destroy(struct mcast_sock *m) -{ - close(m->fd); - free(m); -} - -int mcast_send(struct mcast_sock *m, void *data, int size) -{ - int ret; - - ret = sendto(m->fd, - data, - size, - 0, - (struct sockaddr *) &m->addr, - sizeof(struct sockaddr)); - if (ret == -1) { - debug("mcast_sock_send"); - m->stats.error++; - return ret; - } - - m->stats.bytes += ret; - m->stats.messages++; - - return ret; -} - -int mcast_recv(struct mcast_sock *m, void *data, int size) -{ - int ret; - socklen_t sin_size = sizeof(struct sockaddr_in); - - ret = recvfrom(m->fd, - data, - size, - 0, - (struct sockaddr *)&m->addr, - &sin_size); - if (ret == -1) { - debug("mcast_sock_recv"); - m->stats.error++; - return ret; - } - - m->stats.bytes += ret; - m->stats.messages++; - - return ret; -} - -struct mcast_stats *mcast_get_stats(struct mcast_sock *m) -{ - return &m->stats; -} - -void mcast_dump_stats(int fd, struct mcast_sock *s, struct mcast_sock *r) -{ - char buf[512]; - int size; - - size = sprintf(buf, "multicast traffic:\n" - "%20llu Bytes sent " - "%20llu Bytes recv\n" - "%20llu Pckts sent " - "%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); - - send(fd, buf, size, 0); -} diff --git a/daemon/src/netlink.c b/daemon/src/netlink.c deleted file mode 100644 index 0bde632..0000000 --- a/daemon/src/netlink.c +++ /dev/null @@ -1,326 +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 "conntrackd.h" -#include -#include -#include -#include "us-conntrack.h" -#include -#include -#include "network.h" - -static int ignore_conntrack(struct nf_conntrack *ct) -{ - /* ignore a certain protocol */ - if (CONFIG(ignore_protocol)[nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)]) - 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)) { - 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)) { - debug_ct(ct, "SNAT"); - return 0; - } - - /* Ignore traffic */ - if (ignore_pool_test(STATE(ignore_pool), ct)) { - debug_ct(ct, "ignore traffic"); - return 1; - } - - return 0; -} - -static int nl_event_handler(struct nlmsghdr *nlh, - struct nfattr *nfa[], - 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. - */ - if (ignore_conntrack(ct)) - return NFCT_CB_STOP; - - switch(type) { - case NFCT_T_NEW: - STATE(mode)->event_new(ct, nlh); - break; - case NFCT_T_UPDATE: - STATE(mode)->event_upd(ct, nlh); - break; - case NFCT_T_DESTROY: - if (STATE(mode)->event_dst(ct, nlh)) - update_traffic_stats(ct); - break; - default: - dlog(STATE(log), "received unknown msg from ctnetlink\n"); - break; - } - - return NFCT_CB_STOP; -} - -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(); - if (!STATE(event)) - return -1; - - /* set up socket buffer size */ - if (CONFIG(netlink_buffer_size)) - nfnl_rcvbufsiz(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, - SO_RCVBUF, &read_size, &socklen); - - CONFIG(netlink_buffer_size) = read_size; - } - - /* ensure that maximum grown size is >= than maximum size */ - if (CONFIG(netlink_buffer_size_max_grown) < CONFIG(netlink_buffer_size)) - 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); - - return 0; -} - -static int nl_dump_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: - STATE(mode)->dump(ct, nlh); - break; - default: - dlog(STATE(log), "received unknown msg from ctnetlink"); - break; - } - return NFCT_CB_CONTINUE; -} - -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(); - 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); - - if (nl_dump_conntrack_table(STATE(dump), STATE(subsys_dump)) == -1) - return -1; - - 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) -{ - unsigned int s = CONFIG(netlink_buffer_size) * 2; - - /* already warned that we have reached the maximum buffer size */ - if (warned) - return; - - if (s > CONFIG(netlink_buffer_size_max_grown)) { - dlog(STATE(log), "maximum netlink socket buffer size reached"); - s = CONFIG(netlink_buffer_size_max_grown); - warned = 1; - } - - CONFIG(netlink_buffer_size) = nfnl_rcvbufsiz(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) -{ - 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_sync), - NFCT_Q_FLUSH, - &CONFIG(family), - &req, - sizeof(req)); - - if (nfnl_query(STATE(sync), &req.nlh) == -1) - return -1; - - return 0; -} diff --git a/daemon/src/network.c b/daemon/src/network.c deleted file mode 100644 index b9be318..0000000 --- a/daemon/src/network.c +++ /dev/null @@ -1,282 +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 "conntrackd.h" -#include "network.h" - -#if 0 -#define _TEST_DROP -#else -#undef _TEST_DROP -#endif - -static int drop = 0; /* debugging purposes */ -static unsigned int seq_set, cur_seq; - -static int send_netmsg(struct mcast_sock *m, void *data, unsigned int len) -{ - struct nlnetwork *net = data; - -#ifdef _TEST_DROP - if (++drop > 10) { - drop = 0; - printf("dropping resend (seq=%u)\n", ntohl(net->seq)); - return 0; - } -#endif - return mcast_send(m, net, 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; - - if (!seq_set) { - seq_set = 1; - cur_seq = time(NULL); - net->flags |= NET_HELLO; - } - - net->flags = htons(net->flags); - net->seq = htonl(cur_seq++); - - if (nlh_host2network(nlh) == -1) - return -1; - - net->checksum = 0; - net->checksum = ntohs(do_csum(data, len)); - - return send_netmsg(m, data, len); -} - -int mcast_resend_netmsg(struct mcast_sock *m, void *data) -{ - struct nlnetwork *net = data; - struct nlmsghdr *nlh = data + sizeof(struct nlnetwork); - unsigned int len = htonl(nlh->nlmsg_len) + sizeof(struct nlnetwork); - - net->flags = ntohs(net->flags); - - if (!seq_set) { - seq_set = 1; - cur_seq = time(NULL); - net->flags |= NET_HELLO; - } - - if (net->flags & NET_NACK || net->flags & NET_ACK) { - struct nlnetwork_ack *nack = (struct nlnetwork_ack *) net; - len = sizeof(struct nlnetwork_ack); - } - - net->flags = htons(net->flags); - net->seq = htonl(cur_seq++); - net->checksum = 0; - net->checksum = ntohs(do_csum(data, len)); - - 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); - - if (!seq_set) { - seq_set = 1; - cur_seq = time(NULL); - net->flags |= NET_HELLO; - } - - if (net->flags & NET_NACK || net->flags & NET_ACK) { - struct nlnetwork_ack *nack = (struct nlnetwork_ack *) net; - nack->from = htonl(nack->from); - nack->to = htonl(nack->to); - len = sizeof(struct nlnetwork_ack); - } - - net->flags = htons(net->flags); - net->seq = htonl(cur_seq++); - net->checksum = 0; - net->checksum = ntohs(do_csum(data, len)); - - return send_netmsg(m, data, len); -} - -static int valid_checksum(void *data, unsigned int len) -{ - struct nlnetwork *net = data; - unsigned short checksum, tmp; - - checksum = ntohs(net->checksum); - - /* no checksum, skip */ - if (!checksum) - return 1; - - net->checksum = 0; - tmp = do_csum(data, len); - - return tmp == checksum; -} - -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 nfgenmsg *nfhdr; - - ret = mcast_recv(m, net, len); - if (ret <= 0) - return ret; - - if (ret < sizeof(struct nlnetwork)) - return -1; - - if (!valid_checksum(data, ret)) - return -1; - - net->flags = ntohs(net->flags); - net->seq = ntohl(net->seq); - - if (net->flags & NET_HELLO) - STATE_SYNC(last_seq_recv) = net->seq-1; - - if (net->flags & NET_NACK || net->flags & NET_ACK) { - struct nlnetwork_ack *nack = (struct nlnetwork_ack *) net; - - if (ret < sizeof(struct nlnetwork_ack)) - return -1; - - nack->from = ntohl(nack->from); - nack->to = ntohl(nack->to); - - return ret; - } - - if (net->flags & NET_RESYNC) - return ret; - - /* 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) + sizeof(struct nlnetwork)) - return -1; - - /* this message does not come from ctnetlink */ - if (NFNL_SUBSYS_ID(ntohs(nlh->nlmsg_type)) != NFNL_SUBSYS_CTNETLINK) - 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; - - if (nlh_network2host(nlh) == -1) - return -1; - - return ret; -} - -int mcast_track_seq(u_int32_t seq, u_int32_t *exp_seq) -{ - static int seq_set = 0; - int ret = 1; - - /* netlink sequence tracking initialization */ - if (!seq_set) { - seq_set = 1; - goto out; - } - - /* fast path: we received the correct sequence */ - if (seq == STATE_SYNC(last_seq_recv)+1) - goto out; - - /* out of sequence: some messages got lost */ - if (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: - *exp_seq = STATE_SYNC(last_seq_recv)+1; - /* update expected sequence */ - STATE_SYNC(last_seq_recv) = seq; - - 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 += sizeof(struct nlnetwork); - 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/daemon/src/proxy.c b/daemon/src/proxy.c deleted file mode 100644 index b9bb04e..0000000 --- a/daemon/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/daemon/src/read_config_lex.l b/daemon/src/read_config_lex.l deleted file mode 100644 index dee90c9..0000000 --- a/daemon/src/read_config_lex.l +++ /dev/null @@ -1,125 +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. - * - * Description: configuration file syntax - */ - -#include "read_config_yy.h" -#include "conntrackd.h" -%} - -%option yylineno -%option nounput - -ws [ \t]+ -comment #.*$ -nl [\n\r] - -is_on [o|O][n|N] -is_off [o|O][f|F][f|F] -integer [0-9]+ -path \/[^\"\n ]* -ip4_end [0-9]*[0-9]+ -ip4_part [0-2]*{ip4_end} -ip4 {ip4_part}\.{ip4_part}\.{ip4_part}\.{ip4_part} -hex_255 [0-9a-fA-F]{1,4} -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-Z]* -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] - -%% -"UNIX" { return T_UNIX; } -"IPv4_address" { return T_IPV4_ADDR; } -"IPv6_address" { return T_IPV6_ADDR; } -"IPv4_interface" { return T_IPV4_IFACE; } -"IPv6_interface" { return T_IPV6_IFACE; } -"Port" { return T_PORT; } -"Multicast" { return T_MULTICAST; } -"HashSize" { return T_HASHSIZE; } -"RefreshTime" { return T_REFRESH; } -"CacheTimeout" { return T_EXPIRE; } -"CommitTimeout" { return T_TIMEOUT; } -"DelayDestroyMessages" { return T_DELAY; } -"HashLimit" { return T_HASHLIMIT; } -"Path" { return T_PATH; } -"IgnoreProtocol" { return T_IGNORE_PROTOCOL; } -"UDP" { return T_UDP; } -"ICMP" { return T_ICMP; } -"VRRP" { return T_VRRP; } -"IGMP" { return T_IGMP; } -"TCP" { return T_TCP; } -"IgnoreTrafficFor" { return T_IGNORE_TRAFFIC; } -"StripNAT" { return T_STRIP_NAT; } -"Backlog" { return T_BACKLOG; } -"Group" { return T_GROUP; } -"LogFile" { return T_LOG; } -"LockFile" { return T_LOCK; } -"General" { return T_GENERAL; } -"Sync" { return T_SYNC; } -"Stats" { return T_STATS; } -"RelaxTransitions" { return T_RELAX_TRANSITIONS; } -"SocketBufferSize" { return T_BUFFER_SIZE; } -"SocketBufferSizeMaxGrown" { return T_BUFFER_SIZE_MAX_GROWN; } -"SocketBufferSizeMaxGrowth" { return T_BUFFER_SIZE_MAX_GROWN; } -"Mode" { return T_SYNC_MODE; } -"ListenTo" { return T_LISTEN_TO; } -"Family" { return T_FAMILY; } -"ResendBufferSize" { return T_RESEND_BUFFER_SIZE; } -"Checksum" { return T_CHECKSUM; } -"ACKWindowSize" { return T_WINDOWSIZE; } -"Replicate" { return T_REPLICATE; } -"for" { return T_FOR; } -"SYN_SENT" { return T_SYN_SENT; } -"SYN_RECV" { return T_SYN_RECV; } -"ESTABLISHED" { return T_ESTABLISHED; } -"FIN_WAIT" { return T_FIN_WAIT; } -"CLOSE_WAIT" { return T_CLOSE_WAIT; } -"LAST_ACK" { return T_LAST_ACK; } -"TIME_WAIT" { return T_TIME_WAIT; } -"CLOSE" { return T_CLOSE; } -"LISTEN" { return T_LISTEN; } - -{is_on} { return T_ON; } -{is_off} { return T_OFF; } -{integer} { yylval.val = atoi(yytext); return T_NUMBER; } -{ip4} { yylval.string = strdup(yytext); return T_IP; } -{ip6} { yylval.string = strdup(yytext); return T_IP; } -{path} { yylval.string = strdup(yytext); return T_PATH_VAL; } -{persistent} { return T_PERSISTENT; } -{nack} { return T_NACK; } -{string} { yylval.string = strdup(yytext); return T_STRING; } - -{comment} ; -{ws} ; -{nl} ; - -<> { yyterminate(); } - -. { return yytext[0]; } - -%% - -int -yywrap() -{ - return 1; -} diff --git a/daemon/src/read_config_yy.y b/daemon/src/read_config_yy.y deleted file mode 100644 index 1668919..0000000 --- a/daemon/src/read_config_yy.y +++ /dev/null @@ -1,550 +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. - * - * Description: configuration file abstract grammar - */ - -#include -#include -#include -#include -#include "conntrackd.h" -#include "ignore.h" - -extern char *yytext; -extern int yylineno; - -struct ct_conf conf; -%} - -%union { - int val; - char *string; -} - -%token T_IPV4_ADDR T_IPV4_IFACE T_PORT T_HASHSIZE T_HASHLIMIT T_MULTICAST -%token T_PATH T_UNIX T_REFRESH T_IPV6_ADDR T_IPV6_IFACE -%token T_IGNORE_UDP T_IGNORE_ICMP T_IGNORE_TRAFFIC T_BACKLOG T_GROUP -%token T_LOG T_UDP T_ICMP T_IGMP T_VRRP T_TCP T_IGNORE_PROTOCOL -%token T_LOCK T_STRIP_NAT T_BUFFER_SIZE_MAX_GROWN T_EXPIRE T_TIMEOUT -%token T_GENERAL T_SYNC T_STATS T_RELAX_TRANSITIONS T_BUFFER_SIZE T_DELAY -%token T_SYNC_MODE T_LISTEN_TO T_FAMILY T_RESEND_BUFFER_SIZE -%token T_PERSISTENT T_NACK T_CHECKSUM T_WINDOWSIZE T_ON T_OFF -%token T_REPLICATE T_FOR -%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_IP T_PATH_VAL -%token T_NUMBER -%token T_STRING - -%% - -configfile : - | lines - ; - -lines : line - | lines line - ; - -line : ignore_protocol - | ignore_traffic - | strip_nat - | general - | sync - | stats - ; - -log : T_LOG T_PATH_VAL -{ - strncpy(conf.logfile, $2, FILENAME_MAXLEN); -}; - -lock : T_LOCK T_PATH_VAL -{ - strncpy(conf.lockfile, $2, FILENAME_MAXLEN); -}; - -strip_nat: T_STRIP_NAT -{ - conf.flags |= STRIP_NAT; -}; - -refreshtime : T_REFRESH T_NUMBER -{ - conf.refresh = $2; -}; - -expiretime: T_EXPIRE T_NUMBER -{ - conf.cache_timeout = $2; -}; - -timeout: T_TIMEOUT T_NUMBER -{ - conf.commit_timeout = $2; -}; - -checksum: T_CHECKSUM T_ON -{ -}; - -checksum: T_CHECKSUM T_OFF -{ - conf.flags |= DONT_CHECKSUM; -}; - -ignore_traffic : T_IGNORE_TRAFFIC '{' ignore_traffic_options '}'; - -ignore_traffic_options : - | ignore_traffic_options ignore_traffic_option; - -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 (!family) { - fprintf(stdout, "%s is not a valid IP, ignoring", $2); - return; - } - - if (!STATE(ignore_pool)) { - STATE(ignore_pool) = ignore_pool_create(family); - if (!STATE(ignore_pool)) { - fprintf(stdout, "Can't create ignore pool!\n"); - exit(EXIT_FAILURE); - } - } - - if (!ignore_pool_add(STATE(ignore_pool), &ip)) { - if (errno == EEXIST) - fprintf(stdout, "IP %s is repeated " - "in the ignore pool\n", $2); - if (errno == ENOSPC) - fprintf(stdout, "Too many IP in the ignore pool!\n"); - } -}; - -multicast_line : T_MULTICAST '{' multicast_options '}'; - -multicast_options : - | multicast_options multicast_option; - -multicast_option : T_IPV4_ADDR T_IP -{ - if (!inet_aton($2, &conf.mcast.in)) { - fprintf(stderr, "%s is not a valid IPv4 address\n"); - return; - } - - if (conf.mcast.ipproto == AF_INET6) { - fprintf(stderr, "Your multicast address is IPv4 but " - "is binded to an IPv6 interface? Surely " - "this is not what you want\n"); - return; - } - - conf.mcast.ipproto = AF_INET; -}; - -multicast_option : T_IPV6_ADDR T_IP -{ -#ifdef HAVE_INET_PTON_IPV6 - if (inet_pton(AF_INET6, $2, &conf.mcast.in) <= 0) - fprintf(stderr, "%s is not a valid IPv6 address\n", $2); -#endif - - if (conf.mcast.ipproto == AF_INET) { - fprintf(stderr, "Your multicast address is IPv6 but " - "is binded to an IPv4 interface? Surely " - "this is not what you want\n"); - return; - } - - conf.mcast.ipproto = AF_INET6; -}; - -multicast_option : T_IPV4_IFACE T_IP -{ - if (!inet_aton($2, &conf.mcast.ifa)) { - fprintf(stderr, "%s is not a valid IPv4 address\n"); - return; - } - - if (conf.mcast.ipproto == AF_INET6) { - fprintf(stderr, "Your multicast interface is IPv4 but " - "is binded to an IPv6 interface? Surely " - "this is not what you want\n"); - return; - } - - conf.mcast.ipproto = AF_INET; -}; - -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"); - return; - } - - conf.mcast.ipproto = AF_INET6; -}; - -multicast_option : T_BACKLOG T_NUMBER -{ - conf.mcast.backlog = $2; -}; - -multicast_option : T_GROUP T_NUMBER -{ - conf.mcast.port = $2; -}; - -hashsize : T_HASHSIZE T_NUMBER -{ - conf.hashsize = $2; -}; - -hashlimit: T_HASHLIMIT T_NUMBER -{ - conf.limit = $2; -}; - -unix_line: T_UNIX '{' unix_options '}'; - -unix_options: - | unix_options unix_option - ; - -unix_option : T_PATH T_PATH_VAL -{ - strcpy(conf.local.path, $2); -}; - -unix_option : T_BACKLOG T_NUMBER -{ - conf.local.backlog = $2; -}; - -ignore_protocol: T_IGNORE_PROTOCOL '{' ignore_proto_list '}'; - -ignore_proto_list: - | ignore_proto_list ignore_proto - ; - -ignore_proto: T_NUMBER -{ - if ($1 < IPPROTO_MAX) - conf.ignore_protocol[$1] = 1; - else - fprintf(stdout, "Protocol number `%d' is freak\n", $1); -}; - -ignore_proto: T_UDP -{ - conf.ignore_protocol[IPPROTO_UDP] = 1; -}; - -ignore_proto: T_ICMP -{ - conf.ignore_protocol[IPPROTO_ICMP] = 1; -}; - -ignore_proto: T_VRRP -{ - conf.ignore_protocol[IPPROTO_VRRP] = 1; -}; - -ignore_proto: T_IGMP -{ - conf.ignore_protocol[IPPROTO_IGMP] = 1; -}; - -sync: T_SYNC '{' sync_list '}'; - -sync_list: - | sync_list sync_line; - -sync_line: refreshtime - | expiretime - | timeout - | checksum - | multicast_line - | relax_transitions - | delay_destroy_msgs - | sync_mode_persistent - | sync_mode_nack - | listen_to - | state_replication - ; - -sync_mode_persistent: T_SYNC_MODE T_PERSISTENT '{' sync_mode_persistent_list '}' -{ - conf.flags |= SYNC_MODE_PERSISTENT; -}; - -sync_mode_nack: T_SYNC_MODE T_NACK '{' sync_mode_nack_list '}' -{ - conf.flags |= SYNC_MODE_NACK; -}; - -sync_mode_persistent_list: - | sync_mode_persistent_list sync_mode_persistent_line; - -sync_mode_persistent_line: refreshtime - | expiretime - | timeout - | relax_transitions - | delay_destroy_msgs - ; - -sync_mode_nack_list: - | sync_mode_nack_list sync_mode_nack_line; - -sync_mode_nack_line: resend_buffer_size - | timeout - | window_size - ; - -resend_buffer_size: T_RESEND_BUFFER_SIZE T_NUMBER -{ - conf.resend_buffer_size = $2; -}; - -window_size: T_WINDOWSIZE T_NUMBER -{ - conf.window_size = $2; -}; - -relax_transitions: T_RELAX_TRANSITIONS -{ - conf.flags |= RELAX_TRANSITIONS; -}; - -delay_destroy_msgs: T_DELAY -{ - conf.flags |= DELAY_DESTROY_MSG; -}; - -listen_to: T_LISTEN_TO T_IP -{ - union inet_address addr; - -#ifdef HAVE_INET_PTON_IPV6 - if (inet_pton(AF_INET6, $2, &addr.ipv6) <= 0) -#endif - if (inet_aton($2, &addr.ipv4) <= 0) { - fprintf(stderr, "%s is not a valid IP address\n", $2); - exit(EXIT_FAILURE); - } - - if (CONFIG(listen_to_len) == 0 || CONFIG(listen_to_len) % 16) { - CONFIG(listen_to) = realloc(CONFIG(listen_to), - sizeof(union inet_address) * - (CONFIG(listen_to_len) + 16)); - if (CONFIG(listen_to) == NULL) { - fprintf(stderr, "cannot init listen_to array\n"); - exit(EXIT_FAILURE); - } - - memset(CONFIG(listen_to) + - (CONFIG(listen_to_len) * sizeof(union inet_address)), - 0, sizeof(union inet_address) * 16); - - } -}; - -state_replication: T_REPLICATE states T_FOR state_proto; - -states: - | states state; - -state_proto: T_TCP; -state: tcp_state; - -tcp_state: T_SYN_SENT -{ - extern struct state_replication_helper tcp_state_helper; - state_helper_register(&tcp_state_helper, TCP_CONNTRACK_SYN_SENT); -}; -tcp_state: T_SYN_RECV -{ - extern struct state_replication_helper tcp_state_helper; - state_helper_register(&tcp_state_helper, TCP_CONNTRACK_SYN_RECV); -}; -tcp_state: T_ESTABLISHED -{ - extern struct state_replication_helper tcp_state_helper; - state_helper_register(&tcp_state_helper, TCP_CONNTRACK_ESTABLISHED); -}; -tcp_state: T_FIN_WAIT -{ - extern struct state_replication_helper tcp_state_helper; - state_helper_register(&tcp_state_helper, TCP_CONNTRACK_FIN_WAIT); -}; -tcp_state: T_CLOSE_WAIT -{ - extern struct state_replication_helper tcp_state_helper; - state_helper_register(&tcp_state_helper, TCP_CONNTRACK_CLOSE_WAIT); -}; -tcp_state: T_LAST_ACK -{ - extern struct state_replication_helper tcp_state_helper; - state_helper_register(&tcp_state_helper, TCP_CONNTRACK_LAST_ACK); -}; -tcp_state: T_TIME_WAIT -{ - extern struct state_replication_helper tcp_state_helper; - state_helper_register(&tcp_state_helper, TCP_CONNTRACK_TIME_WAIT); -}; -tcp_state: T_CLOSE -{ - extern struct state_replication_helper tcp_state_helper; - state_helper_register(&tcp_state_helper, TCP_CONNTRACK_CLOSE); -}; -tcp_state: T_LISTEN -{ - extern struct state_replication_helper tcp_state_helper; - state_helper_register(&tcp_state_helper, TCP_CONNTRACK_LISTEN); -}; - -general: T_GENERAL '{' general_list '}'; - -general_list: - | general_list general_line - ; - -general_line: hashsize - | hashlimit - | log - | lock - | unix_line - | netlink_buffer_size - | netlink_buffer_size_max_grown - | family - ; - -netlink_buffer_size: T_BUFFER_SIZE T_NUMBER -{ - conf.netlink_buffer_size = $2; -}; - -netlink_buffer_size_max_grown : T_BUFFER_SIZE_MAX_GROWN T_NUMBER -{ - conf.netlink_buffer_size_max_grown = $2; -}; - -family : T_FAMILY T_STRING -{ - if (strncmp($2, "IPv6", strlen("IPv6")) == 0) - conf.family = AF_INET6; - else - conf.family = AF_INET; -}; - -stats: T_SYNC '{' stats_list '}'; - -stats_list: - | stats_list stat_line - ; - -stat_line: - | - ; - -%% - -int -yyerror(char *msg) -{ - printf("Error parsing config file: "); - printf("line (%d), symbol '%s': %s\n", yylineno, yytext, msg); - exit(EXIT_FAILURE); -} - -int -init_config(char *filename) -{ - FILE *fp; - - fp = fopen(filename, "r"); - if (!fp) - return -1; - - yyrestart(fp); - yyparse(); - fclose(fp); - - /* default to IPv4 */ - if (CONFIG(family) == 0) - CONFIG(family) = AF_INET; - - /* set to default is not specified */ - if (strcmp(CONFIG(lockfile), "") == 0) - strncpy(CONFIG(lockfile), DEFAULT_LOCKFILE, FILENAME_MAXLEN); - - /* default to 180 seconds of expiration time: cache entries */ - if (CONFIG(cache_timeout) == 0) - CONFIG(cache_timeout) = 180; - - /* default to 180 seconds: committed entries */ - if (CONFIG(commit_timeout) == 0) - CONFIG(commit_timeout) = 180; - - /* default to 60 seconds of refresh time */ - if (CONFIG(refresh) == 0) - CONFIG(refresh) = 60; - - if (CONFIG(resend_buffer_size) == 0) - CONFIG(resend_buffer_size) = 262144; - - /* create empty pool */ - if (!STATE(ignore_pool)) { - STATE(ignore_pool) = ignore_pool_create(CONFIG(family)); - if (!STATE(ignore_pool)) { - fprintf(stdout, "Can't create ignore pool!\n"); - exit(EXIT_FAILURE); - } - } - - /* default to a window size of 20 packets */ - if (CONFIG(window_size) == 0) - CONFIG(window_size) = 20; - - return 0; -} diff --git a/daemon/src/run.c b/daemon/src/run.c deleted file mode 100644 index 67437d8..0000000 --- a/daemon/src/run.c +++ /dev/null @@ -1,227 +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. - * - * Description: run and init functions - */ - -#include "conntrackd.h" -#include -#include -#include "us-conntrack.h" -#include -#include - -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_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)); - STATE(mode)->kill(); - unlink(CONFIG(lockfile)); - dlog(STATE(log), "------- shutdown received ----"); - close_log(STATE(log)); - - sigprocmask(SIG_UNBLOCK, &STATE(block), NULL); - - exit(0); -} - -void local_handler(int fd, void *data) -{ - int ret; - int type; - - ret = read(fd, &type, sizeof(type)); - if (ret == -1) { - dlog(STATE(log), "can't read from unix socket\n"); - return; - } - if (ret == 0) { - debug("nothing to process\n"); - return; - } - - switch(type) { - case FLUSH_MASTER: - dlog(STATE(log), "[REQ] flushing master table"); - nl_flush_master_conntrack_table(); - return; - case RESYNC_MASTER: - dlog(STATE(log), "[REQ] resync with master table"); - nl_dump_conntrack_table(STATE(dump), STATE(subsys_dump)); - return; - } - - if (!STATE(mode)->local(fd, type, data)) - dlog(STATE(log), "[FAIL] unknown local request %d", type); -} - -int init(int mode) -{ - switch(mode) { - case STATS_MODE: - STATE(mode) = &stats_mode; - break; - case SYNC_MODE: - STATE(mode) = &sync_mode; - break; - default: - fprintf(stderr, "Unknown running mode! default " - "to synchronization mode\n"); - STATE(mode) = &sync_mode; - break; - } - - /* Initialization */ - if (STATE(mode)->init() == -1) { - dlog(STATE(log), "[FAIL] initialization failed"); - return -1; - } - - /* local UNIX socket */ - STATE(local) = local_server_create(&CONFIG(local)); - if (!STATE(local)) { - dlog(STATE(log), "[FAIL] 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?"); - return -1; - } - - if (nl_init_dump_handler() == -1) { - dlog(STATE(log), "[FAIL] can't open netlink handler! " - "no ctnetlink kernel support?"); - 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); - sigaddset(&STATE(block), SIGINT); - - if (signal(SIGINT, killer) == SIG_ERR) - return -1; - - if (signal(SIGTERM, killer) == SIG_ERR) - return -1; - - /* ignore connection reset by peer */ - if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) - return -1; - - dlog(STATE(log), "[OK] initialization completed"); - - return 0; -} - -#define POLL_NSECS 1 - -static void __run(void) -{ - int max, ret; - fd_set readfds; - struct timeval tv = { - .tv_sec = POLL_NSECS, - .tv_usec = 0 - }; - - FD_ZERO(&readfds); - FD_SET(STATE(local), &readfds); - FD_SET(nfnl_fd(STATE(event)), &readfds); - - max = MAX(STATE(local), nfnl_fd(STATE(event))); - - if (STATE(mode)->add_fds_to_set) - max = MAX(max, STATE(mode)->add_fds_to_set(&readfds)); - - ret = select(max+1, &readfds, NULL, NULL, &tv); - if (ret == -1) { - /* interrupted syscall, retry */ - if (errno == EINTR) - return; - - dlog(STATE(log), "select() failed: %s", strerror(errno)); - return; - } - - /* signals are racy */ - sigprocmask(SIG_BLOCK, &STATE(block), NULL); - - /* order received via UNIX socket */ - if (FD_ISSET(STATE(local), &readfds)) - 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 (ret == -1) { - switch(errno) { - case ENOBUFS: - /* - * It seems that ctnetlink can't back off, - * it's likely that we're losing events. - * Solution: duplicate the socket buffer - * size and resync with master conntrack table. - */ - nl_resize_socket_buffer(STATE(event)); - nl_dump_conntrack_table(STATE(sync), - STATE(subsys_sync)); - break; - case ENOENT: - /* - * We received a message from another - * netfilter subsystem that we are not - * interested in. Just ignore it. - */ - break; - default: - dlog(STATE(log), "event catch says: %s", - strerror(errno)); - break; - } - } - } - - if (STATE(mode)->step) - STATE(mode)->step(&readfds); - - sigprocmask(SIG_UNBLOCK, &STATE(block), NULL); -} - -void run(void) -{ - while(1) - __run(); -} diff --git a/daemon/src/state_helper.c b/daemon/src/state_helper.c deleted file mode 100644 index 81b0d09..0000000 --- a/daemon/src/state_helper.c +++ /dev/null @@ -1,44 +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 "conntrackd.h" -#include "state_helper.h" - -static struct state_replication_helper *helper[IPPROTO_MAX]; - -int state_helper_verdict(int type, struct nf_conntrack *ct) -{ - u_int8_t l4proto; - - if (type == NFCT_T_DESTROY) - return ST_H_REPLICATE; - - l4proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO); - if (helper[l4proto]) - return helper[l4proto]->verdict(helper[l4proto], ct); - - return ST_H_REPLICATE; -} - -void state_helper_register(struct state_replication_helper *h, int state) -{ - if (helper[h->proto] == NULL) - helper[h->proto] = h; - - helper[h->proto]->state |= (1 << state); -} diff --git a/daemon/src/state_helper_tcp.c b/daemon/src/state_helper_tcp.c deleted file mode 100644 index af714dc..0000000 --- a/daemon/src/state_helper_tcp.c +++ /dev/null @@ -1,35 +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 "conntrackd.h" -#include "state_helper.h" - -static int tcp_verdict(const struct state_replication_helper *h, - const struct nf_conntrack *ct) -{ - u_int8_t state = nfct_get_attr_u8(ct, ATTR_TCP_STATE); - if (h->state & (1 << state)) - return ST_H_REPLICATE; - - return ST_H_SKIP; -} - -struct state_replication_helper tcp_state_helper = { - .proto = IPPROTO_TCP, - .verdict = tcp_verdict, -}; diff --git a/daemon/src/stats-mode.c b/daemon/src/stats-mode.c deleted file mode 100644 index 9647bbf..0000000 --- a/daemon/src/stats-mode.c +++ /dev/null @@ -1,151 +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 "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 -}; diff --git a/daemon/src/sync-mode.c b/daemon/src/sync-mode.c deleted file mode 100644 index b32bef7..0000000 --- a/daemon/src/sync-mode.c +++ /dev/null @@ -1,416 +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 "conntrackd.h" -#include -#include -#include -#include "us-conntrack.h" -#include -#include -#include "sync.h" -#include "network.h" - -/* handler for multicast messages received */ -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; - struct us_conntrack *u = NULL; - - memset(tmp, 0, sizeof(tmp)); - - ret = mcast_recv_netmsg(m, buf, sizeof(buf)); - if (ret <= 0) { - STATE(malformed)++; - return; - } - - if (STATE_SYNC(mcast_sync)->pre_recv(net)) - return; - - if ((type = parse_network_msg(ct, nlh)) == NFCT_T_ERROR) { - STATE(malformed)++; - return; - } - - 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: -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; - } - debug_ct(ct, "can't add"); - } - break; - case NFCT_T_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: - if (cache_del(STATE_SYNC(external), ct)) - debug_ct(ct, "external destroy"); - else - debug_ct(ct, "can't destroy"); - break; - default: - debug("unknown type %d\n", type); - break; - } -} - -static int init_sync(void) -{ - int ret; - - state.sync = malloc(sizeof(struct ct_sync_state)); - if (!state.sync) { - dlog(STATE(log), "[FAIL] can't allocate memory for state sync"); - return -1; - } - memset(state.sync, 0, sizeof(struct ct_sync_state)); - - if (CONFIG(flags) & SYNC_MODE_NACK) - STATE_SYNC(mcast_sync) = &nack; - else - /* default to persistent mode */ - STATE_SYNC(mcast_sync) = ¬rack; - - if (STATE_SYNC(mcast_sync)->init) - STATE_SYNC(mcast_sync)->init(); - - STATE_SYNC(internal) = - cache_create("internal", - STATE_SYNC(mcast_sync)->internal_cache_flags, - CONFIG(family), - STATE_SYNC(mcast_sync)->internal_cache_extra); - - if (!STATE_SYNC(internal)) { - dlog(STATE(log), "[FAIL] can't allocate memory for " - "the internal cache"); - return -1; - } - - STATE_SYNC(external) = - cache_create("external", - STATE_SYNC(mcast_sync)->external_cache_flags, - CONFIG(family), - NULL); - - if (!STATE_SYNC(external)) { - dlog(STATE(log), "[FAIL] 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!"); - 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!"); - return -1; - } - - /* 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; -} - -static int add_fds_to_set_sync(fd_set *readfds) -{ - FD_SET(STATE_SYNC(mcast_server->fd), readfds); - - return STATE_SYNC(mcast_server->fd); -} - -static void step_sync(fd_set *readfds) -{ - /* multicast packet has been received */ - if (FD_ISSET(STATE_SYNC(mcast_server->fd), readfds)) - mcast_handler(); -} - -static void kill_sync() -{ - cache_destroy(STATE_SYNC(internal)); - cache_destroy(STATE_SYNC(external)); - - mcast_server_destroy(STATE_SYNC(mcast_server)); - mcast_client_destroy(STATE_SYNC(mcast_client)); - - destroy_alarm_thread(); - - if (STATE_SYNC(mcast_sync)->kill) - STATE_SYNC(mcast_sync)->kill(); -} - -static dump_stats_sync(int fd) -{ - char buf[512]; - int size; - - size = sprintf(buf, "multicast sequence tracking:\n" - "%20llu Pckts mfrm " - "%20llu Pckts lost\n\n", - STATE(malformed), - STATE_SYNC(packets_lost)); - - send(fd, buf, size, 0); -} - -/* handler for requests coming via UNIX socket */ -static int local_handler_sync(int fd, int type, void *data) -{ - int ret = 1; - - switch(type) { - case DUMP_INTERNAL: - cache_dump(STATE_SYNC(internal), fd, NFCT_O_PLAIN); - break; - case DUMP_EXTERNAL: - cache_dump(STATE_SYNC(external), fd, NFCT_O_PLAIN); - break; - case DUMP_INT_XML: - cache_dump(STATE_SYNC(internal), fd, NFCT_O_XML); - break; - case DUMP_EXT_XML: - cache_dump(STATE_SYNC(external), fd, NFCT_O_XML); - break; - case COMMIT: - dlog(STATE(log), "[REQ] commit external cache to master table"); - cache_commit(STATE_SYNC(external)); - break; - case FLUSH_CACHE: - dlog(STATE(log), "[REQ] flushing caches"); - cache_flush(STATE_SYNC(internal)); - cache_flush(STATE_SYNC(external)); - break; - case KILL: - killer(); - break; - case STATS: - cache_stats(STATE_SYNC(internal), fd); - cache_stats(STATE_SYNC(external), fd); - dump_traffic_stats(fd); - mcast_dump_stats(fd, STATE_SYNC(mcast_client), - 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(mcast_sync)->local) - ret = STATE_SYNC(mcast_sync)->local(fd, type, data); - break; - } - - return ret; -} - -static void dump_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) -{ - /* 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_update_force(STATE_SYNC(internal), ct)) - debug_ct(ct, "resync"); -} - -static void mcast_send_sync(struct nlmsghdr *nlh, - struct us_conntrack *u, - struct nf_conntrack *ct, - int type) -{ - char buf[4096]; - struct nlnetwork *net = (struct nlnetwork *) buf; - int mangled = 0; - - memset(buf, 0, sizeof(buf)); - - if (!state_helper_verdict(type, ct)) - return; - - if (!mangled) - memcpy(buf + sizeof(struct nlnetwork), nlh, nlh->nlmsg_len); - - mcast_send_netmsg(STATE_SYNC(mcast_client), net); - STATE_SYNC(mcast_sync)->post_send(net, u); -} - -static void overrun_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) -{ - struct us_conntrack *u; - - /* 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_SYNC(internal), ct)) { - if ((u = cache_update_force(STATE_SYNC(internal), ct))) { - debug_ct(ct, "overrun resync"); - mcast_send_sync(nlh, u, ct, NFCT_T_UPDATE); - } - } -} - -static void event_new_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) -{ - struct us_conntrack *u; - - /* 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); - nfct_attr_unset(ct, ATTR_TIMEOUT); -retry: - if ((u = cache_add(STATE_SYNC(internal), ct))) { - mcast_send_sync(nlh, u, ct, NFCT_T_NEW); - debug_ct(u->ct, "internal new"); - } else { - if (errno == EEXIST) { - char buf[4096]; - struct nlmsghdr *nlh = (struct nlmsghdr *) buf; - - 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_NEW); - goto retry; - } - dlog(STATE(log), "can't add to internal cache: " - "%s\n", strerror(errno)); - debug_ct(ct, "can't add"); - } -} - -static void event_update_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) -{ - struct us_conntrack *u; - - nfct_attr_unset(ct, ATTR_TIMEOUT); - - if ((u = cache_update(STATE_SYNC(internal), ct)) == NULL) { - /* - * 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) - && (u = cache_add(STATE_SYNC(internal), ct))) { - debug_ct(u->ct, "forcing internal update"); - } else { - debug_ct(ct, "can't update"); - return; - } - } - debug_ct(u->ct, "internal update"); - mcast_send_sync(nlh, u, ct, NFCT_T_UPDATE); -} - -static int event_destroy_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) -{ - nfct_attr_unset(ct, ATTR_TIMEOUT); - - if (CONFIG(flags) & DELAY_DESTROY_MSG) { - - nfct_set_attr_u32(ct, ATTR_STATUS, IPS_DYING); - - if (cache_update(STATE_SYNC(internal), ct)) { - debug_ct(ct, "delay internal destroy"); - return 1; - } else { - debug_ct(ct, "can't delay destroy!"); - return 0; - } - } else { - if (cache_del(STATE_SYNC(internal), ct)) { - mcast_send_sync(nlh, NULL, ct, NFCT_T_DESTROY); - debug_ct(ct, "internal destroy"); - } else - debug_ct(ct, "can't destroy"); - } -} - -struct ct_mode sync_mode = { - .init = init_sync, - .add_fds_to_set = add_fds_to_set_sync, - .step = step_sync, - .local = local_handler_sync, - .kill = kill_sync, - .dump = dump_sync, - .overrun = overrun_sync, - .event_new = event_new_sync, - .event_upd = event_update_sync, - .event_dst = event_destroy_sync -}; diff --git a/daemon/src/sync-nack.c b/daemon/src/sync-nack.c deleted file mode 100644 index 288dba4..0000000 --- a/daemon/src/sync-nack.c +++ /dev/null @@ -1,309 +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 -#include "conntrackd.h" -#include "sync.h" -#include "linux_list.h" -#include "us-conntrack.h" -#include "buffer.h" -#include "debug.h" -#include "network.h" -#include -#include - -#if 0 -#define dp printf -#else -#define dp -#endif - -static LIST_HEAD(queue); - -struct cache_nack { - struct list_head head; - 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); - list_add(&cn->head, &queue); -} - -static void cache_nack_update(struct us_conntrack *u, void *data) -{ - struct cache_nack *cn = data; - - if (cn->head.next != LIST_POISON1 && - cn->head.prev != LIST_POISON2) - list_del(&cn->head); - - INIT_LIST_HEAD(&cn->head); - list_add(&cn->head, &queue); -} - -static void cache_nack_destroy(struct us_conntrack *u, void *data) -{ - struct cache_nack *cn = data; - - if (cn->head.next != LIST_POISON1 && - cn->head.prev != LIST_POISON2) - list_del(&cn->head); -} - -static struct cache_extra cache_nack_extra = { - .size = sizeof(struct cache_nack), - .add = cache_nack_add, - .update = cache_nack_update, - .destroy = cache_nack_destroy -}; - -static int nack_init() -{ - STATE_SYNC(buffer) = buffer_create(CONFIG(resend_buffer_size)); - if (STATE_SYNC(buffer) == NULL) - return -1; - - return 0; -} - -static void nack_kill() -{ - buffer_destroy(STATE_SYNC(buffer)); -} - -static void mcast_send_nack(u_int32_t expt_seq, u_int32_t recv_seq) -{ - struct nlnetwork_ack nack = { - .flags = NET_NACK, - .from = expt_seq, - .to = recv_seq, - }; - - mcast_send_error(STATE_SYNC(mcast_client), &nack); - buffer_add(STATE_SYNC(buffer), &nack, sizeof(struct nlnetwork_ack)); -} - -static void mcast_send_ack(u_int32_t from, u_int32_t to) -{ - struct nlnetwork_ack ack = { - .flags = NET_ACK, - .from = from, - .to = to, - }; - - mcast_send_error(STATE_SYNC(mcast_client), &ack); - buffer_add(STATE_SYNC(buffer), &ack, sizeof(struct nlnetwork_ack)); -} - -static void mcast_send_resync() -{ - struct nlnetwork net = { - .flags = NET_RESYNC, - }; - - mcast_send_error(STATE_SYNC(mcast_client), &net); - buffer_add(STATE_SYNC(buffer), &net, sizeof(struct nlnetwork)); -} - -int nack_local(int fd, int type, void *data) -{ - int ret = 1; - - switch(type) { - case REQUEST_DUMP: - mcast_send_resync(); - dlog(STATE(log), "[REQ] request resync"); - break; - default: - ret = 0; - break; - } - - return ret; -} - -static int buffer_compare(void *data1, void *data2) -{ - struct nlnetwork *net = data1; - struct nlnetwork_ack *nack = data2; - struct nlmsghdr *nlh = data1 + sizeof(struct nlnetwork); - - unsigned old_seq = ntohl(net->seq); - - if (ntohl(net->seq) >= nack->from && ntohl(net->seq) <= 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)); - } - return 0; -} - -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) { - dp("remove from buffer (seq=%u)\n", ntohl(net->seq)); - __buffer_del(STATE_SYNC(buffer), data1); - } - return 0; -} - -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; - - u = cache_get_conntrack(STATE_SYNC(internal), cn); - - if (cn->seq >= from && cn->seq <= 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); - STATE_SYNC(mcast_sync)->post_send(net, u); - dp("(newseq=%u)\n", *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; - - u = cache_get_conntrack(STATE_SYNC(internal), cn); - if (cn->seq >= from && cn->seq <= 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); - } - } - unlock(); -} - -static int nack_pre_recv(const struct nlnetwork *net) -{ - static unsigned int window = 0; - unsigned int exp_seq; - - if (window == 0) - window = CONFIG(window_size); - - if (!mcast_track_seq(net->seq, &exp_seq)) { - dp("OOS: sending nack (seq=%u)\n", exp_seq); - mcast_send_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_ack(net->seq-CONFIG(window_size), net->seq); - } - } - - if (net->flags & NET_NACK) { - struct nlnetwork_ack *nack = (struct nlnetwork_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) { - 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; - - 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); - return 1; - } - - return 0; -} - -static void nack_post_send(const struct nlnetwork *net, struct us_conntrack *u) -{ - unsigned int size = sizeof(struct nlnetwork); - struct nlmsghdr *nlh = (struct nlmsghdr *) ((void *) net + size); - - if (NFNL_MSG_TYPE(ntohs(nlh->nlmsg_type)) == IPCTNL_MSG_CT_DELETE) { - buffer_add(STATE_SYNC(buffer), net, - ntohl(nlh->nlmsg_len) + size); - } else if (u != NULL) { - unsigned int *seq; - struct list_head *n; - struct cache_nack *cn; - - cn = (struct cache_nack *) - cache_get_extra(STATE_SYNC(internal), u); - cn->seq = ntohl(net->seq); - if (cn->head.next != LIST_POISON1 && - cn->head.prev != LIST_POISON2) - list_del(&cn->head); - - INIT_LIST_HEAD(&cn->head); - list_add(&cn->head, &queue); - } -} - -struct sync_mode nack = { - .internal_cache_flags = LIFETIME, - .external_cache_flags = LIFETIME, - .internal_cache_extra = &cache_nack_extra, - .init = nack_init, - .kill = nack_kill, - .local = nack_local, - .pre_recv = nack_pre_recv, - .post_send = nack_post_send, -}; diff --git a/daemon/src/sync-notrack.c b/daemon/src/sync-notrack.c deleted file mode 100644 index 2b5ae38..0000000 --- a/daemon/src/sync-notrack.c +++ /dev/null @@ -1,127 +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 "conntrackd.h" -#include "sync.h" -#include "network.h" -#include "us-conntrack.h" -#include "alarm.h" - -static void refresher(struct alarm_list *a, void *data) -{ - struct us_conntrack *u = data; - char buf[8192]; - int size; - - if (nfct_get_attr_u32(u->ct, ATTR_STATUS) & IPS_DYING) { - - debug_ct(u->ct, "persistence destroy"); - - 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); - } -} - -static void cache_notrack_add(struct us_conntrack *u, void *data) -{ - struct alarm_list *alarm = data; - - init_alarm(alarm); - set_alarm_expiration(alarm, (random() % conf.refresh) + 1); - set_alarm_data(alarm, u); - set_alarm_function(alarm, refresher); - add_alarm(alarm); -} - -static void cache_notrack_update(struct us_conntrack *u, void *data) -{ - struct alarm_list *alarm = data; - mod_alarm(alarm, (random() % conf.refresh) + 1); -} - -static void cache_notrack_destroy(struct us_conntrack *u, void *data) -{ - struct alarm_list *alarm = data; - del_alarm(alarm); -} - -static struct cache_extra cache_notrack_extra = { - .size = sizeof(struct alarm_list), - .add = cache_notrack_add, - .update = cache_notrack_update, - .destroy = cache_notrack_destroy -}; - -static int notrack_pre_recv(const struct nlnetwork *net) -{ - unsigned int exp_seq; - - /* - * Ignore error messages: Although this message type is not ever - * 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)) - return 1; - - /* - * Multicast sequence tracking: we keep track of multicast messages - * although we don't do any explicit message recovery. So, why do - * we do sequence tracking? Just to let know the sysadmin. - * - * Let t be 1 < t < RefreshTime. To ensure consistency, conntrackd - * retransmit every t seconds a message with the state of a certain - * entry even if such entry did not change. This mechanism also - * provides passive resynchronization, in other words, there is - * no facility to request a full synchronization from new nodes that - * just joined the cluster, instead they just get resynchronized in - * RefreshTime seconds at worst case. - */ - mcast_track_seq(net->seq, &exp_seq); - - return 0; -} - -static void notrack_post_send(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, -}; diff --git a/daemon/src/traffic_stats.c b/daemon/src/traffic_stats.c deleted file mode 100644 index b510b77..0000000 --- a/daemon/src/traffic_stats.c +++ /dev/null @@ -1,54 +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 "cache.h" -#include "hash.h" -#include "conntrackd.h" -#include -#include -#include -#include "us-conntrack.h" -#include - -void update_traffic_stats(struct nf_conntrack *ct) -{ - STATE(bytes)[NFCT_DIR_ORIGINAL] += - nfct_get_attr_u32(ct, ATTR_ORIG_COUNTER_BYTES); - STATE(bytes)[NFCT_DIR_REPLY] += - nfct_get_attr_u32(ct, ATTR_REPL_COUNTER_BYTES); - STATE(packets)[NFCT_DIR_ORIGINAL] += - nfct_get_attr_u32(ct, ATTR_ORIG_COUNTER_PACKETS); - STATE(packets)[NFCT_DIR_REPLY] += - nfct_get_attr_u32(ct, ATTR_REPL_COUNTER_PACKETS); -} - -void dump_traffic_stats(int fd) -{ - char buf[512]; - int size; - u_int64_t bytes = STATE(bytes)[NFCT_DIR_ORIGINAL] + - STATE(bytes)[NFCT_DIR_REPLY]; - u_int64_t packets = STATE(packets)[NFCT_DIR_ORIGINAL] + - 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); - - send(fd, buf, size, 0); -} diff --git a/examples/Makefile.am b/examples/Makefile.am new file mode 100644 index 0000000..be83d42 --- /dev/null +++ b/examples/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = stats sync diff --git a/examples/debian.conntrackd.init.d b/examples/debian.conntrackd.init.d new file mode 100644 index 0000000..ba847dd --- /dev/null +++ b/examples/debian.conntrackd.init.d @@ -0,0 +1,48 @@ +#!/bin/sh +# +# /etc/init.d/conntrackd +# +# Maximilian Wilhelm +# -- Mon, 06 Nov 2006 18:39:07 +0100 +# + +export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + +NAME="conntrackd" +DAEMON=`command -v conntrackd` +CONFIG="/etc/conntrack/conntrackd.conf" +PIDFILE="/var/run/${NAME}.pid" + + +# Gracefully exit if there is no daemon (debian way of life) +if [ ! -x "${DAEMON}" ]; then + exit 0 +fi + +# Check for config file +if [ ! -f /etc/conntrackd/conntrackd.conf ]; then + echo "Error: There is no config file for $NAME" >&2 + exit 1; +fi + +case "$1" in + start) + echo -n "Starting $NAME: " + start-stop-daemon --start --quiet --make-pidfile --pidfile "/var/run/${NAME}.pid" --background --exec "${DAEMON}" && echo "done." || echo "FAILED!" + ;; + stop) + echo -n "Stopping $NAME:" + start-stop-daemon --stop --quiet --oknodo --pidfile "/var/run/${NAME}.pid" && echo "done." || echo "FAILED!" + ;; + + restart) + $0 start + $0 stop + ;; + + *) + echo "Usage: /etc/init.d/conntrackd {start|stop|restart}" + exit 1 +esac + +exit 0 diff --git a/examples/stats/Makefile.am b/examples/stats/Makefile.am new file mode 100644 index 0000000..b43c3b8 --- /dev/null +++ b/examples/stats/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = conntrackd.conf diff --git a/examples/stats/conntrackd.conf b/examples/stats/conntrackd.conf new file mode 100644 index 0000000..e514ac0 --- /dev/null +++ b/examples/stats/conntrackd.conf @@ -0,0 +1,69 @@ +# +# General settings +# +General { + # + # Number of buckets in the caches: hash table + # + HashSize 8192 + + # + # Maximum number of conntracks: + # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max + # + HashLimit 65535 + + # + # Logfile + # + LogFile /var/log/conntrackd.log + + # + # Lockfile + # + LockFile /var/lock/conntrack.lock + + # + # Unix socket configuration + # + UNIX { + Path /tmp/sync.sock + Backlog 20 + } + + # + # Netlink socket buffer size + # + SocketBufferSize 262142 + + # + # Increase the socket buffer up to maximun if required + # + SocketBufferSizeMaxGrown 655355 +} + +# +# Ignore traffic for a certain set of IP's: Usually +# all the IP assigned to the firewall since local +# traffic must be ignored, just forwarded connections +# are worth to replicate +# +IgnoreTrafficFor { + IPv4_address 127.0.0.1 # loopback +} + +# +# Do not replicate certain protocol traffic +# +IgnoreProtocol { + UDP +# ICMP +# IGMP +# VRRP + # numeric numbers also valid +} + +# +# Strip NAT traffic +# +StripNAT diff --git a/examples/sync/Makefile.am b/examples/sync/Makefile.am new file mode 100644 index 0000000..28e7643 --- /dev/null +++ b/examples/sync/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = persistent nack diff --git a/examples/sync/nack/Makefile.am b/examples/sync/nack/Makefile.am new file mode 100644 index 0000000..6fd99b1 --- /dev/null +++ b/examples/sync/nack/Makefile.am @@ -0,0 +1,2 @@ +EXTRA_DIST = script_backup.sh script_master.sh +SUBDIRS = node1 node2 diff --git a/examples/sync/nack/README b/examples/sync/nack/README new file mode 100644 index 0000000..66987f7 --- /dev/null +++ b/examples/sync/nack/README @@ -0,0 +1 @@ +This directory contains the files for the NACK based protocol diff --git a/examples/sync/nack/node1/Makefile.am b/examples/sync/nack/node1/Makefile.am new file mode 100644 index 0000000..edc0ed7 --- /dev/null +++ b/examples/sync/nack/node1/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = conntrackd.conf keepalived.conf diff --git a/examples/sync/nack/node1/conntrackd.conf b/examples/sync/nack/node1/conntrackd.conf new file mode 100644 index 0000000..f24fa7e --- /dev/null +++ b/examples/sync/nack/node1/conntrackd.conf @@ -0,0 +1,125 @@ +# +# Synchronizer settings +# +Sync { + Mode NACK { + # + # Size of the buffer that hold destroy messages for + # possible resends (in bytes) + # + ResendBufferSize 262144 + + # + # Entries committed to the connection tracking table + # starts with a limited timeout of N seconds until the + # takeover process is completed. + # + CommitTimeout 180 + + # Set Acknowledgement window size + ACKWindowSize 20 + } + + # + # Multicast IP and interface where messages are + # broadcasted (dedicated link). IMPORTANT: Make sure + # that iptables accepts traffic for destination + # 225.0.0.50, eg: + # + # iptables -I INPUT -d 225.0.0.50 -j ACCEPT + # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT + # + Multicast { + IPv4_address 225.0.0.50 + IPv4_interface 192.168.100.100 # IP of dedicated link + Group 3780 + Backlog 20 + } + + # Enable/Disable message checksumming + Checksum on + + # Uncomment this if you want to replicate just certain TCP states. + # This option introduces a tradeoff in the replication: it reduces + # CPU consumption and lost messages rate at the cost of having + # backup replicas that don't contain the current state that the active + # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, + # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. + # + # Replicate ESTABLISHED TIME_WAIT for TCP +} + +# +# General settings +# +General { + # + # Number of buckets in the caches: hash table + # + HashSize 8192 + + # + # Maximum number of conntracks: + # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max + # + HashLimit 65535 + + # + # Logfile + # + LogFile /var/log/conntrackd.log + + # + # Lockfile + # + LockFile /var/lock/conntrack.lock + + # + # Unix socket configuration + # + UNIX { + Path /tmp/sync.sock + Backlog 20 + } + + # + # Netlink socket buffer size + # + SocketBufferSize 262142 + + # + # Increase the socket buffer up to maximum if required + # + SocketBufferSizeMaxGrown 655355 +} + +# +# Ignore traffic for a certain set of IP's: Usually +# all the IP assigned to the firewall since local +# traffic must be ignored, just forwarded connections +# are worth to replicate +# +IgnoreTrafficFor { + IPv4_address 127.0.0.1 # loopback + IPv4_address 192.168.0.1 + IPv4_address 192.168.1.1 + IPv4_address 192.168.100.100 # dedicated link ip + IPv4_address 192.168.0.100 # virtual IP 1 + IPv4_address 192.168.1.100 # virtual IP 2 +} + +# +# Do not replicate certain protocol traffic +# +IgnoreProtocol { + UDP + ICMP + IGMP + VRRP + # numeric numbers also valid +} + +# +# Strip NAT traffic +# +StripNAT diff --git a/examples/sync/nack/node1/keepalived.conf b/examples/sync/nack/node1/keepalived.conf new file mode 100644 index 0000000..41aa35b --- /dev/null +++ b/examples/sync/nack/node1/keepalived.conf @@ -0,0 +1,38 @@ +vrrp_sync_group G1 { # must be before vrrp_instance declaration + group { + VI_1 + VI_2 + } + notify_master /etc/conntrackd/script_master.sh + notify_backup /etc/conntrackd/script_backup.sh +} + +vrrp_instance VI_1 { + interface eth1 + state SLAVE + virtual_router_id 61 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.0.100 # default CIDR mask is /32 + } +} + +vrrp_instance VI_2 { + interface eth0 + state SLAVE + virtual_router_id 62 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.1.100 + } +} diff --git a/examples/sync/nack/node2/Makefile.am b/examples/sync/nack/node2/Makefile.am new file mode 100644 index 0000000..edc0ed7 --- /dev/null +++ b/examples/sync/nack/node2/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = conntrackd.conf keepalived.conf diff --git a/examples/sync/nack/node2/conntrackd.conf b/examples/sync/nack/node2/conntrackd.conf new file mode 100644 index 0000000..4f15773 --- /dev/null +++ b/examples/sync/nack/node2/conntrackd.conf @@ -0,0 +1,124 @@ +# +# Synchronizer settings +# +Sync { + Mode NACK { + # + # Size of the buffer that hold destroy messages for + # possible resends (in bytes) + # + ResendBufferSize 262144 + + # Entries committed to the connection tracking table + # starts with a limited timeout of N seconds until the + # takeover process is completed. + # + CommitTimeout 180 + + # Set Acknowledgement window size + ACKWindowSize 20 + } + + # + # Multicast IP and interface where messages are + # broadcasted (dedicated link). IMPORTANT: Make sure + # that iptables accepts traffic for destination + # 225.0.0.50, eg: + # + # iptables -I INPUT -d 225.0.0.50 -j ACCEPT + # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT + # + Multicast { + IPv4_address 225.0.0.50 + IPv4_interface 192.168.100.200 # IP of dedicated link + Group 3780 + Backlog 20 + } + + # Enable/Disable message checksumming + Checksum on + + # Uncomment this if you want to replicate just certain TCP states. + # This option introduces a tradeoff in the replication: it reduces + # CPU consumption and lost messages rate at the cost of having + # backup replicas that don't contain the current state that the active + # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, + # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. + # + # Replicate ESTABLISHED TIME_WAIT for TCP +} + +# +# General settings +# +General { + # + # Number of buckets in the caches: hash table + # + HashSize 8192 + + # + # Maximum number of conntracks: + # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max + # + HashLimit 65535 + + # + # Logfile + # + LogFile /var/log/conntrackd.log + + # + # Lockfile + # + LockFile /var/lock/conntrack.lock + + # + # Unix socket configuration + # + UNIX { + Path /tmp/sync.sock + Backlog 20 + } + + # + # Netlink socket buffer size + # + SocketBufferSize 262142 + + # + # Increase the socket buffer up to maximum if required + # + SocketBufferSizeMaxGrown 655355 +} + +# +# Ignore traffic for a certain set of IP's: Usually +# all the IP assigned to the firewall since local +# traffic must be ignored, just forwarded connections +# are worth to replicate +# +IgnoreTrafficFor { + IPv4_address 127.0.0.1 # loopback + IPv4_address 192.168.0.2 + IPv4_address 192.168.1.2 + IPv4_address 192.168.100.200 # dedicated link ip + IPv4_address 192.168.0.200 # virtual IP 1 + IPv4_address 192.168.1.200 # virtual IP 2 +} + +# +# Do not replicate certain protocol traffic +# +IgnoreProtocol { + UDP + ICMP + IGMP + VRRP + # numeric numbers also valid +} + +# +# Strip NAT traffic +# +StripNAT diff --git a/examples/sync/nack/node2/keepalived.conf b/examples/sync/nack/node2/keepalived.conf new file mode 100644 index 0000000..41aa35b --- /dev/null +++ b/examples/sync/nack/node2/keepalived.conf @@ -0,0 +1,38 @@ +vrrp_sync_group G1 { # must be before vrrp_instance declaration + group { + VI_1 + VI_2 + } + notify_master /etc/conntrackd/script_master.sh + notify_backup /etc/conntrackd/script_backup.sh +} + +vrrp_instance VI_1 { + interface eth1 + state SLAVE + virtual_router_id 61 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.0.100 # default CIDR mask is /32 + } +} + +vrrp_instance VI_2 { + interface eth0 + state SLAVE + virtual_router_id 62 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.1.100 + } +} diff --git a/examples/sync/nack/script_backup.sh b/examples/sync/nack/script_backup.sh new file mode 100755 index 0000000..813e375 --- /dev/null +++ b/examples/sync/nack/script_backup.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +/usr/sbin/conntrackd -n # request a resync from other nodes via multicast diff --git a/examples/sync/nack/script_master.sh b/examples/sync/nack/script_master.sh new file mode 100755 index 0000000..ff1dbc0 --- /dev/null +++ b/examples/sync/nack/script_master.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +/usr/sbin/conntrackd -c # commit the cache +/usr/sbin/conntrackd -f # flush the caches +/usr/sbin/conntrackd -R # resync with kernel conntrack table diff --git a/examples/sync/persistent/Makefile.am b/examples/sync/persistent/Makefile.am new file mode 100644 index 0000000..6fd99b1 --- /dev/null +++ b/examples/sync/persistent/Makefile.am @@ -0,0 +1,2 @@ +EXTRA_DIST = script_backup.sh script_master.sh +SUBDIRS = node1 node2 diff --git a/examples/sync/persistent/README b/examples/sync/persistent/README new file mode 100644 index 0000000..36b5989 --- /dev/null +++ b/examples/sync/persistent/README @@ -0,0 +1 @@ +This directory contains the files for the PERSISTENT based protocol diff --git a/examples/sync/persistent/node1/Makefile.am b/examples/sync/persistent/node1/Makefile.am new file mode 100644 index 0000000..edc0ed7 --- /dev/null +++ b/examples/sync/persistent/node1/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = conntrackd.conf keepalived.conf diff --git a/examples/sync/persistent/node1/conntrackd.conf b/examples/sync/persistent/node1/conntrackd.conf new file mode 100644 index 0000000..90afeb7 --- /dev/null +++ b/examples/sync/persistent/node1/conntrackd.conf @@ -0,0 +1,130 @@ +# +# Synchronizer settings +# +Sync { + Mode PERSISTENT { + # + # If a conntrack entry is not modified in <= 15 seconds, then + # a message is broadcasted. This mechanism is used to + # resynchronize nodes that just joined the multicast group + # + RefreshTime 15 + + # + # If we don't receive a notification about the state of + # an entry in the external cache after N seconds, then + # remove it. + # + CacheTimeout 180 + + # + # Entries committed to the connection tracking table + # starts with a limited timeout of N seconds until the + # takeover process is completed. + # + CommitTimeout 180 + } + + # + # Multicast IP and interface where messages are + # broadcasted (dedicated link). IMPORTANT: Make sure + # that iptables accepts traffic for destination + # 225.0.0.50, eg: + # + # iptables -I INPUT -d 225.0.0.50 -j ACCEPT + # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT + # + Multicast { + IPv4_address 225.0.0.50 + IPv4_interface 192.168.100.100 # IP of dedicated link + Group 3780 + Backlog 20 + } + + # Enable/Disable message checksumming + Checksum on + + # Uncomment this if you want to replicate just certain TCP states. + # This option introduces a tradeoff in the replication: it reduces + # CPU consumption and lost messages rate at the cost of having + # backup replicas that don't contain the current state that the active + # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, + # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. + # + # Replicate ESTABLISHED TIME_WAIT for TCP +} + +# +# General settings +# +General { + # + # Number of buckets in the caches: hash table + # + HashSize 8192 + + # + # Maximum number of conntracks: + # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max + # + HashLimit 65535 + + # + # Logfile + # + LogFile /var/log/conntrackd.log + + # + # Lockfile + # + LockFile /var/lock/conntrack.lock + + # + # Unix socket configuration + # + UNIX { + Path /tmp/sync.sock + Backlog 20 + } + + # + # Netlink socket buffer size + # + SocketBufferSize 262142 + + # + # Increase the socket buffer up to maximum if required + # + SocketBufferSizeMaxGrown 655355 +} + +# +# Ignore traffic for a certain set of IP's: Usually +# all the IP assigned to the firewall since local +# traffic must be ignored, just forwarded connections +# are worth to replicate +# +IgnoreTrafficFor { + IPv4_address 127.0.0.1 # loopback + IPv4_address 192.168.0.1 + IPv4_address 192.168.1.1 + IPv4_address 192.168.100.100 # dedicated link ip + IPv4_address 192.168.0.100 # virtual IP 1 + IPv4_address 192.168.1.100 # virtual IP 2 +} + +# +# Do not replicate certain protocol traffic +# +IgnoreProtocol { + UDP + ICMP + IGMP + VRRP + # numeric numbers also valid +} + +# +# Strip NAT traffic +# +StripNAT diff --git a/examples/sync/persistent/node1/keepalived.conf b/examples/sync/persistent/node1/keepalived.conf new file mode 100644 index 0000000..41aa35b --- /dev/null +++ b/examples/sync/persistent/node1/keepalived.conf @@ -0,0 +1,38 @@ +vrrp_sync_group G1 { # must be before vrrp_instance declaration + group { + VI_1 + VI_2 + } + notify_master /etc/conntrackd/script_master.sh + notify_backup /etc/conntrackd/script_backup.sh +} + +vrrp_instance VI_1 { + interface eth1 + state SLAVE + virtual_router_id 61 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.0.100 # default CIDR mask is /32 + } +} + +vrrp_instance VI_2 { + interface eth0 + state SLAVE + virtual_router_id 62 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.1.100 + } +} diff --git a/examples/sync/persistent/node2/Makefile.am b/examples/sync/persistent/node2/Makefile.am new file mode 100644 index 0000000..edc0ed7 --- /dev/null +++ b/examples/sync/persistent/node2/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = conntrackd.conf keepalived.conf diff --git a/examples/sync/persistent/node2/conntrackd.conf b/examples/sync/persistent/node2/conntrackd.conf new file mode 100644 index 0000000..aee4a29 --- /dev/null +++ b/examples/sync/persistent/node2/conntrackd.conf @@ -0,0 +1,130 @@ +# +# Synchronizer settings +# +Sync { + Mode PERSISTENT { + # + # If a conntrack entry is not modified in <= 15 seconds, then + # a message is broadcasted. This mechanism is used to + # resynchronize nodes that just joined the multicast group + # + RefreshTime 15 + + # + # If we don't receive a notification about the state of + # an entry in the external cache after N seconds, then + # remove it. + # + CacheTimeout 180 + + # + # Entries committed to the connection tracking table + # starts with a limited timeout of N seconds until the + # takeover process is completed. + # + CommitTimeout 180 + } + + # + # Multicast IP and interface where messages are + # broadcasted (dedicated link). IMPORTANT: Make sure + # that iptables accepts traffic for destination + # 225.0.0.50, eg: + # + # iptables -I INPUT -d 225.0.0.50 -j ACCEPT + # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT + # + Multicast { + IPv4_address 225.0.0.50 + IPv4_interface 192.168.100.200 # IP of dedicated link + Group 3780 + Backlog 20 + } + + # Enable/Disable message checksumming + Checksum on + + # Uncomment this if you want to replicate just certain TCP states. + # This option introduces a tradeoff in the replication: it reduces + # CPU consumption and lost messages rate at the cost of having + # backup replicas that don't contain the current state that the active + # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, + # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. + # + # Replicate ESTABLISHED TIME_WAIT for TCP +} + +# +# General settings +# +General { + # + # Number of buckets in the caches: hash table + # + HashSize 8192 + + # + # Maximum number of conntracks: + # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max + # + HashLimit 65535 + + # + # Logfile + # + LogFile /var/log/conntrackd.log + + # + # Lockfile + # + LockFile /var/lock/conntrack.lock + + # + # Unix socket configuration + # + UNIX { + Path /tmp/sync.sock + Backlog 20 + } + + # + # Netlink socket buffer size + # + SocketBufferSize 262142 + + # + # Increase the socket buffer up to maximum if required + # + SocketBufferSizeMaxGrown 655355 +} + +# +# Ignore traffic for a certain set of IP's: Usually +# all the IP assigned to the firewall since local +# traffic must be ignored, just forwarded connections +# are worth to replicate +# +IgnoreTrafficFor { + IPv4_address 127.0.0.1 # loopback + IPv4_address 192.168.0.2 + IPv4_address 192.168.1.2 + IPv4_address 192.168.100.200 # dedicated link ip + IPv4_address 192.168.0.200 # virtual IP 1 + IPv4_address 192.168.1.200 # virtual IP 2 +} + +# +# Do not replicate certain protocol traffic +# +IgnoreProtocol { + UDP + ICMP + IGMP + VRRP + # numeric numbers also valid +} + +# +# Strip NAT traffic +# +StripNAT diff --git a/examples/sync/persistent/node2/keepalived.conf b/examples/sync/persistent/node2/keepalived.conf new file mode 100644 index 0000000..41aa35b --- /dev/null +++ b/examples/sync/persistent/node2/keepalived.conf @@ -0,0 +1,38 @@ +vrrp_sync_group G1 { # must be before vrrp_instance declaration + group { + VI_1 + VI_2 + } + notify_master /etc/conntrackd/script_master.sh + notify_backup /etc/conntrackd/script_backup.sh +} + +vrrp_instance VI_1 { + interface eth1 + state SLAVE + virtual_router_id 61 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.0.100 # default CIDR mask is /32 + } +} + +vrrp_instance VI_2 { + interface eth0 + state SLAVE + virtual_router_id 62 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.1.100 + } +} diff --git a/examples/sync/persistent/script_backup.sh b/examples/sync/persistent/script_backup.sh new file mode 100755 index 0000000..8ea2ad8 --- /dev/null +++ b/examples/sync/persistent/script_backup.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +/usr/sbin/conntrackd -B diff --git a/examples/sync/persistent/script_master.sh b/examples/sync/persistent/script_master.sh new file mode 100755 index 0000000..70c26c9 --- /dev/null +++ b/examples/sync/persistent/script_master.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +/usr/sbin/conntrackd -c +/usr/sbin/conntrackd -R diff --git a/extensions/Makefile.am b/extensions/Makefile.am new file mode 100644 index 0000000..5366ee3 --- /dev/null +++ b/extensions/Makefile.am @@ -0,0 +1,16 @@ +include $(top_srcdir)/Make_global.am + +AM_CFLAGS=-fPIC -Wall +LIBS= + +pkglib_LTLIBRARIES = ct_proto_tcp.la ct_proto_udp.la \ + ct_proto_icmp.la ct_proto_sctp.la + +ct_proto_tcp_la_SOURCES = libct_proto_tcp.c +ct_proto_tcp_la_LDFLAGS = -module -avoid-version +ct_proto_udp_la_SOURCES = libct_proto_udp.c +ct_proto_udp_la_LDFLAGS = -module -avoid-version +ct_proto_icmp_la_SOURCES = libct_proto_icmp.c +ct_proto_icmp_la_LDFLAGS = -module -avoid-version +ct_proto_sctp_la_SOURCES = libct_proto_sctp.c +ct_proto_sctp_la_LDFLAGS = -module -avoid-version diff --git a/extensions/libct_proto_icmp.c b/extensions/libct_proto_icmp.c new file mode 100644 index 0000000..e7cb04d --- /dev/null +++ b/extensions/libct_proto_icmp.c @@ -0,0 +1,108 @@ +/* + * (C) 2005 by Pablo Neira Ayuso + * Harald Welte + * + * 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 +#include +#include +#include /* For htons */ +#include +#include +#include +#include "conntrack.h" + +static struct option opts[] = { + {"icmp-type", 1, 0, '1'}, + {"icmp-code", 1, 0, '2'}, + {"icmp-id", 1, 0, '3'}, + {0, 0, 0, 0} +}; + +static void help() +{ + fprintf(stdout, "--icmp-type icmp type\n"); + fprintf(stdout, "--icmp-code icmp code\n"); + fprintf(stdout, "--icmp-id icmp id\n"); +} + +/* Add 1; spaces filled with 0. */ +static u_int8_t invmap[] + = { [ICMP_ECHO] = ICMP_ECHOREPLY + 1, + [ICMP_ECHOREPLY] = ICMP_ECHO + 1, + [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1, + [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1, + [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1, + [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1, + [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1, + [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1}; + +static int parse(char c, char *argv[], + struct nfct_tuple *orig, + struct nfct_tuple *reply, + struct nfct_tuple *exptuple, + struct nfct_tuple *mask, + union nfct_protoinfo *proto, + unsigned int *flags) +{ + switch(c) { + case '1': + if (optarg) { + orig->l4dst.icmp.type = atoi(optarg); + reply->l4dst.icmp.type = + invmap[orig->l4dst.icmp.type] - 1; + *flags |= ICMP_TYPE; + } + break; + case '2': + if (optarg) { + orig->l4dst.icmp.code = atoi(optarg); + reply->l4dst.icmp.code = 0; + *flags |= ICMP_CODE; + } + break; + case '3': + if (optarg) { + orig->l4src.icmp.id = htons(atoi(optarg)); + reply->l4dst.icmp.id = 0; + *flags |= ICMP_ID; + } + break; + } + return 1; +} + +static int final_check(unsigned int flags, + unsigned int command, + struct nfct_tuple *orig, + struct nfct_tuple *reply) +{ + if (!(flags & ICMP_TYPE)) + return 0; + else if (!(flags & ICMP_CODE)) + return 0; + + return 1; +} + +static struct ctproto_handler icmp = { + .name = "icmp", + .protonum = IPPROTO_ICMP, + .parse_opts = parse, + .final_check = final_check, + .help = help, + .opts = opts, + .version = VERSION, +}; + +static void __attribute__ ((constructor)) init(void); + +static void init(void) +{ + register_proto(&icmp); +} diff --git a/extensions/libct_proto_icmp.man b/extensions/libct_proto_icmp.man new file mode 100644 index 0000000..3b860d0 --- /dev/null +++ b/extensions/libct_proto_icmp.man @@ -0,0 +1,10 @@ +This module matches on ICMP-specific fields. +.TP +.BI "--icmp-type " "TYPE" +ICMP Type. Has to be specified numerically. +.TP +.BI "--icmp-code " "CODE" +ICMP Code. Has to be specified numerically. +.TP +.BI "--icmp-id " "ID" +ICMP Id. Has to be specified numerically. diff --git a/extensions/libct_proto_sctp.c b/extensions/libct_proto_sctp.c new file mode 100644 index 0000000..1c8f0d1 --- /dev/null +++ b/extensions/libct_proto_sctp.c @@ -0,0 +1,164 @@ +/* + * (C) 2005 by Harald Welte + * 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. + * + */ +#include +#include +#include +#include +#include /* For htons */ +#include "conntrack.h" +#include +#include + +static struct option opts[] = { + {"orig-port-src", 1, 0, '1'}, + {"orig-port-dst", 1, 0, '2'}, + {"reply-port-src", 1, 0, '3'}, + {"reply-port-dst", 1, 0, '4'}, + {"state", 1, 0, '5'}, + {"tuple-port-src", 1, 0, '6'}, + {"tuple-port-dst", 1, 0, '7'}, + {0, 0, 0, 0} +}; + +static const char *states[] = { + "NONE", + "CLOSED", + "COOKIE_WAIT", + "COOKIE_ECHOED", + "ESTABLISHED", + "SHUTDOWN_SENT", + "SHUTDOWN_RECV", + "SHUTDOWN_ACK_SENT", +}; + +static void help() +{ + fprintf(stdout, "--orig-port-src original source port\n"); + fprintf(stdout, "--orig-port-dst original destination port\n"); + fprintf(stdout, "--reply-port-src reply source port\n"); + fprintf(stdout, "--reply-port-dst reply destination port\n"); + fprintf(stdout, "--state SCTP state, fe. ESTABLISHED\n"); + fprintf(stdout, "--tuple-port-src expectation tuple src port\n"); + fprintf(stdout, "--tuple-port-src expectation tuple dst port\n"); +} + +static int parse_options(char c, char *argv[], + struct nfct_tuple *orig, + struct nfct_tuple *reply, + struct nfct_tuple *exptuple, + struct nfct_tuple *mask, + union nfct_protoinfo *proto, + unsigned int *flags) +{ + switch(c) { + case '1': + if (optarg) { + orig->l4src.sctp.port = htons(atoi(optarg)); + *flags |= SCTP_ORIG_SPORT; + } + break; + case '2': + if (optarg) { + orig->l4dst.sctp.port = htons(atoi(optarg)); + *flags |= SCTP_ORIG_DPORT; + } + break; + case '3': + if (optarg) { + reply->l4src.sctp.port = htons(atoi(optarg)); + *flags |= SCTP_REPL_SPORT; + } + break; + case '4': + if (optarg) { + reply->l4dst.sctp.port = htons(atoi(optarg)); + *flags |= SCTP_REPL_DPORT; + } + break; + case '5': + if (optarg) { + int i; + for (i=0; i<10; i++) { + if (strcmp(optarg, states[i]) == 0) { + /* FIXME: Add state to + * nfct_protoinfo + proto->sctp.state = i; */ + break; + } + } + if (i == 10) { + printf("doh?\n"); + return 0; + } + *flags |= SCTP_STATE; + } + break; + case '6': + if (optarg) { + exptuple->l4src.sctp.port = htons(atoi(optarg)); + *flags |= SCTP_EXPTUPLE_SPORT; + } + break; + case '7': + if (optarg) { + exptuple->l4dst.sctp.port = htons(atoi(optarg)); + *flags |= SCTP_EXPTUPLE_DPORT; + } + + } + return 1; +} + +static int final_check(unsigned int flags, + unsigned int command, + struct nfct_tuple *orig, + struct nfct_tuple *reply) +{ + int ret = 0; + + if ((flags & (SCTP_ORIG_SPORT|SCTP_ORIG_DPORT)) + && !(flags & (SCTP_REPL_SPORT|SCTP_REPL_DPORT))) { + reply->l4src.sctp.port = orig->l4dst.sctp.port; + reply->l4dst.sctp.port = orig->l4src.sctp.port; + ret = 1; + } else if (!(flags & (SCTP_ORIG_SPORT|SCTP_ORIG_DPORT)) + && (flags & (SCTP_REPL_SPORT|SCTP_REPL_DPORT))) { + orig->l4src.sctp.port = reply->l4dst.sctp.port; + orig->l4dst.sctp.port = reply->l4src.sctp.port; + ret = 1; + } + if ((flags & (SCTP_ORIG_SPORT|SCTP_ORIG_DPORT)) + && ((flags & (SCTP_REPL_SPORT|SCTP_REPL_DPORT)))) + ret = 1; + + /* --state is missing and we are trying to create a conntrack */ + if (ret && (command & CT_CREATE) && (!(flags & SCTP_STATE))) + ret = 0; + + return ret; +} + +static struct ctproto_handler sctp = { + .name = "sctp", + .protonum = IPPROTO_SCTP, + .parse_opts = parse_options, + .final_check = final_check, + .help = help, + .opts = opts, + .version = VERSION, +}; + +static void __attribute__ ((constructor)) init(void); + +static void init(void) +{ + register_proto(&sctp); +} diff --git a/extensions/libct_proto_tcp.c b/extensions/libct_proto_tcp.c new file mode 100644 index 0000000..ee24206 --- /dev/null +++ b/extensions/libct_proto_tcp.c @@ -0,0 +1,180 @@ +/* + * (C) 2005 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 +#include +#include +#include +#include /* For htons */ +#include +#include + +#include "conntrack.h" + +static struct option opts[] = { + {"orig-port-src", 1, 0, '1'}, + {"orig-port-dst", 1, 0, '2'}, + {"reply-port-src", 1, 0, '3'}, + {"reply-port-dst", 1, 0, '4'}, + {"mask-port-src", 1, 0, '5'}, + {"mask-port-dst", 1, 0, '6'}, + {"state", 1, 0, '7'}, + {"tuple-port-src", 1, 0, '8'}, + {"tuple-port-dst", 1, 0, '9'}, + {0, 0, 0, 0} +}; + +static const char *states[] = { + "NONE", + "SYN_SENT", + "SYN_RECV", + "ESTABLISHED", + "FIN_WAIT", + "CLOSE_WAIT", + "LAST_ACK", + "TIME_WAIT", + "CLOSE", + "LISTEN" +}; + +static void help() +{ + fprintf(stdout, "--orig-port-src original source port\n"); + fprintf(stdout, "--orig-port-dst original destination port\n"); + fprintf(stdout, "--reply-port-src reply source port\n"); + fprintf(stdout, "--reply-port-dst reply destination port\n"); + fprintf(stdout, "--mask-port-src mask source port\n"); + fprintf(stdout, "--mask-port-dst mask destination port\n"); + fprintf(stdout, "--tuple-port-src expectation tuple src port\n"); + fprintf(stdout, "--tuple-port-src expectation tuple dst port\n"); + fprintf(stdout, "--state TCP state, fe. ESTABLISHED\n"); +} + +static int parse_options(char c, char *argv[], + struct nfct_tuple *orig, + struct nfct_tuple *reply, + struct nfct_tuple *exptuple, + struct nfct_tuple *mask, + union nfct_protoinfo *proto, + unsigned int *flags) +{ + switch(c) { + case '1': + if (optarg) { + orig->l4src.tcp.port = htons(atoi(optarg)); + *flags |= TCP_ORIG_SPORT; + } + break; + case '2': + if (optarg) { + orig->l4dst.tcp.port = htons(atoi(optarg)); + *flags |= TCP_ORIG_DPORT; + } + break; + case '3': + if (optarg) { + reply->l4src.tcp.port = htons(atoi(optarg)); + *flags |= TCP_REPL_SPORT; + } + break; + case '4': + if (optarg) { + reply->l4dst.tcp.port = htons(atoi(optarg)); + *flags |= TCP_REPL_DPORT; + } + break; + case '5': + if (optarg) { + mask->l4src.tcp.port = htons(atoi(optarg)); + *flags |= TCP_MASK_SPORT; + } + break; + case '6': + if (optarg) { + mask->l4dst.tcp.port = htons(atoi(optarg)); + *flags |= TCP_MASK_DPORT; + } + break; + case '7': + if (optarg) { + int i; + for (i=0; i<10; i++) { + if (strcmp(optarg, states[i]) == 0) { + proto->tcp.state = i; + break; + } + } + if (i == 10) { + printf("doh?\n"); + return 0; + } + *flags |= TCP_STATE; + } + break; + case '8': + if (optarg) { + exptuple->l4src.tcp.port = htons(atoi(optarg)); + *flags |= TCP_EXPTUPLE_SPORT; + } + break; + case '9': + if (optarg) { + exptuple->l4dst.tcp.port = htons(atoi(optarg)); + *flags |= TCP_EXPTUPLE_DPORT; + } + break; + } + return 1; +} + +static int final_check(unsigned int flags, + unsigned int command, + struct nfct_tuple *orig, + struct nfct_tuple *reply) +{ + int ret = 0; + + if ((flags & (TCP_ORIG_SPORT|TCP_ORIG_DPORT)) + && !(flags & (TCP_REPL_SPORT|TCP_REPL_DPORT))) { + reply->l4src.tcp.port = orig->l4dst.tcp.port; + reply->l4dst.tcp.port = orig->l4src.tcp.port; + ret = 1; + } else if (!(flags & (TCP_ORIG_SPORT|TCP_ORIG_DPORT)) + && (flags & (TCP_REPL_SPORT|TCP_REPL_DPORT))) { + orig->l4src.tcp.port = reply->l4dst.tcp.port; + orig->l4dst.tcp.port = reply->l4src.tcp.port; + ret = 1; + } + if ((flags & (TCP_ORIG_SPORT|TCP_ORIG_DPORT)) + && ((flags & (TCP_REPL_SPORT|TCP_REPL_DPORT)))) + ret = 1; + + /* --state is missing and we are trying to create a conntrack */ + if (ret && (command & CT_CREATE) && (!(flags & TCP_STATE))) + ret = 0; + + return ret; +} + +static struct ctproto_handler tcp = { + .name = "tcp", + .protonum = IPPROTO_TCP, + .parse_opts = parse_options, + .final_check = final_check, + .help = help, + .opts = opts, + .version = VERSION, +}; + +static void __attribute__ ((constructor)) init(void); + +static void init(void) +{ + register_proto(&tcp); +} diff --git a/extensions/libct_proto_tcp.man b/extensions/libct_proto_tcp.man new file mode 100644 index 0000000..41783f8 --- /dev/null +++ b/extensions/libct_proto_tcp.man @@ -0,0 +1,16 @@ +This module matches on TCP-specific fields. +.TP +.BI "--orig-port-src " "PORT" +Source port in original direction +.TP +.BI "--orig-port-dst " "PORT" +Destination port in original direction +.TP +.BI "--reply-port-src " "PORT" +Source port in reply direction +.TP +.BI "--reply-port-dst " "PORT" +Destination port in reply direction +.TP +.BI "--state " "[NONE|SYN_SENT|SYN_RECV|ESTABLISHED|FIN_WAIT|CLOSE_WAIT|LAST_ACK|TIME_WAIT|CLOSE|LISTEN]" +TCP state diff --git a/extensions/libct_proto_udp.c b/extensions/libct_proto_udp.c new file mode 100644 index 0000000..48079e0 --- /dev/null +++ b/extensions/libct_proto_udp.c @@ -0,0 +1,141 @@ +/* + * (C) 2005 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 +#include +#include +#include /* For htons */ +#include "conntrack.h" +#include +#include + +static struct option opts[] = { + {"orig-port-src", 1, 0, '1'}, + {"orig-port-dst", 1, 0, '2'}, + {"reply-port-src", 1, 0, '3'}, + {"reply-port-dst", 1, 0, '4'}, + {"mask-port-src", 1, 0, '5'}, + {"mask-port-dst", 1, 0, '6'}, + {"tuple-port-src", 1, 0, '7'}, + {"tuple-port-dst", 1, 0, '8'}, + {0, 0, 0, 0} +}; + +static void help() +{ + fprintf(stdout, "--orig-port-src original source port\n"); + fprintf(stdout, "--orig-port-dst original destination port\n"); + fprintf(stdout, "--reply-port-src reply source port\n"); + fprintf(stdout, "--reply-port-dst reply destination port\n"); + fprintf(stdout, "--mask-port-src mask source port\n"); + fprintf(stdout, "--mask-port-dst mask destination port\n"); + fprintf(stdout, "--tuple-port-src expectation tuple src port\n"); + fprintf(stdout, "--tuple-port-src expectation tuple dst port\n"); +} + +static int parse_options(char c, char *argv[], + struct nfct_tuple *orig, + struct nfct_tuple *reply, + struct nfct_tuple *exptuple, + struct nfct_tuple *mask, + union nfct_protoinfo *proto, + unsigned int *flags) +{ + switch(c) { + case '1': + if (optarg) { + orig->l4src.udp.port = htons(atoi(optarg)); + *flags |= UDP_ORIG_SPORT; + } + break; + case '2': + if (optarg) { + orig->l4dst.udp.port = htons(atoi(optarg)); + *flags |= UDP_ORIG_DPORT; + } + break; + case '3': + if (optarg) { + reply->l4src.udp.port = htons(atoi(optarg)); + *flags |= UDP_REPL_SPORT; + } + break; + case '4': + if (optarg) { + reply->l4dst.udp.port = htons(atoi(optarg)); + *flags |= UDP_REPL_DPORT; + } + break; + case '5': + if (optarg) { + mask->l4src.udp.port = htons(atoi(optarg)); + *flags |= UDP_MASK_SPORT; + } + break; + case '6': + if (optarg) { + mask->l4dst.udp.port = htons(atoi(optarg)); + *flags |= UDP_MASK_DPORT; + } + break; + case '7': + if (optarg) { + exptuple->l4src.udp.port = htons(atoi(optarg)); + *flags |= UDP_EXPTUPLE_SPORT; + } + break; + case '8': + if (optarg) { + exptuple->l4dst.udp.port = htons(atoi(optarg)); + *flags |= UDP_EXPTUPLE_DPORT; + } + + } + return 1; +} + +static int final_check(unsigned int flags, + unsigned int command, + struct nfct_tuple *orig, + struct nfct_tuple *reply) +{ + if ((flags & (UDP_ORIG_SPORT|UDP_ORIG_DPORT)) + && !(flags & (UDP_REPL_SPORT|UDP_REPL_DPORT))) { + reply->l4src.udp.port = orig->l4dst.udp.port; + reply->l4dst.udp.port = orig->l4src.udp.port; + return 1; + } else if (!(flags & (UDP_ORIG_SPORT|UDP_ORIG_DPORT)) + && (flags & (UDP_REPL_SPORT|UDP_REPL_DPORT))) { + orig->l4src.udp.port = reply->l4dst.udp.port; + orig->l4dst.udp.port = reply->l4src.udp.port; + return 1; + } + if ((flags & (UDP_ORIG_SPORT|UDP_ORIG_DPORT)) + && ((flags & (UDP_REPL_SPORT|UDP_REPL_DPORT)))) + return 1; + + return 0; +} + +static struct ctproto_handler udp = { + .name = "udp", + .protonum = IPPROTO_UDP, + .parse_opts = parse_options, + .final_check = final_check, + .help = help, + .opts = opts, + .version = VERSION, +}; + +static void __attribute__ ((constructor)) init(void); + +static void init(void) +{ + register_proto(&udp); +} diff --git a/extensions/libct_proto_udp.man b/extensions/libct_proto_udp.man new file mode 100644 index 0000000..c67fedf --- /dev/null +++ b/extensions/libct_proto_udp.man @@ -0,0 +1,13 @@ +This module matches on UDP-specific fields. +.TP +.BI "--orig-port-src " "PORT" +Source port in original direction +.TP +.BI "--orig-port-dst " "PORT" +Destination port in original direction +.TP +.BI "--reply-port-src " "PORT" +Source port in reply direction +.TP +.BI "--reply-port-dst " "PORT" +Destination port in reply direction diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 0000000..e669d73 --- /dev/null +++ b/include/Makefile.am @@ -0,0 +1,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 + diff --git a/include/alarm.h b/include/alarm.h new file mode 100644 index 0000000..93e6482 --- /dev/null +++ b/include/alarm.h @@ -0,0 +1,13 @@ +#ifndef _TIMER_H_ +#define _TIMER_H_ + +#include "linux_list.h" + +struct alarm_list { + struct list_head head; + unsigned long expires; + void *data; + void (*function)(struct alarm_list *a, void *data); +}; + +#endif diff --git a/include/buffer.h b/include/buffer.h new file mode 100644 index 0000000..8d72dfb --- /dev/null +++ b/include/buffer.h @@ -0,0 +1,32 @@ +#ifndef _BUFFER_H_ +#define _BUFFER_H_ + +#include +#include +#include +#include +#include "linux_list.h" + +struct buffer { + pthread_mutex_t lock; + size_t max_size; + size_t cur_size; + struct list_head head; +}; + +struct buffer_node { + struct list_head head; + size_t size; + char data[0]; +}; + +struct buffer *buffer_create(size_t max_size); +void buffer_destroy(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)); + +#endif diff --git a/include/cache.h b/include/cache.h new file mode 100644 index 0000000..7d9559a --- /dev/null +++ b/include/cache.h @@ -0,0 +1,92 @@ +#ifndef _CACHE_H_ +#define _CACHE_H_ + +#include +#include + +/* cache features */ +enum { + NO_FEATURES = 0, + + TIMER_FEATURE = 0, + TIMER = (1 << TIMER_FEATURE), + + LIFETIME_FEATURE = 2, + LIFETIME = (1 << LIFETIME_FEATURE), + + __CACHE_MAX_FEATURE +}; +#define CACHE_MAX_FEATURE __CACHE_MAX_FEATURE + +struct cache; +struct us_conntrack; + +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); +}; + +extern struct cache_feature lifetime_feature; +extern struct cache_feature timer_feature; + +#define CACHE_MAX_NAMELEN 32 + +struct cache { + char name[CACHE_MAX_NAMELEN]; + struct hashtable *h; + + unsigned int num_features; + struct cache_feature **features; + unsigned int feature_type[CACHE_MAX_FEATURE]; + unsigned int *feature_offset; + struct cache_extra *extra; + unsigned int extra_offset; + + /* statistics */ + 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 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); +}; + +struct nf_conntrack; + +struct cache *cache_create(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); +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_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 *); + +/* iterators */ +void cache_dump(struct cache *c, int fd, int type); +void cache_commit(struct cache *c); +void cache_flush(struct cache *c); +void cache_bulk(struct cache *c); + +#endif diff --git a/include/conntrack.h b/include/conntrack.h new file mode 100644 index 0000000..fb3b9b6 --- /dev/null +++ b/include/conntrack.h @@ -0,0 +1,160 @@ +#ifndef _CONNTRACK_H +#define _CONNTRACK_H + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#include "linux_list.h" +#include +#include + +#define PROGNAME "conntrack" + +#include +#ifndef IPPROTO_SCTP +#define IPPROTO_SCTP 132 +#endif + +enum action { + CT_NONE = 0, + + CT_LIST_BIT = 0, + CT_LIST = (1 << CT_LIST_BIT), + + CT_CREATE_BIT = 1, + CT_CREATE = (1 << CT_CREATE_BIT), + + CT_UPDATE_BIT = 2, + CT_UPDATE = (1 << CT_UPDATE_BIT), + + CT_DELETE_BIT = 3, + CT_DELETE = (1 << CT_DELETE_BIT), + + CT_GET_BIT = 4, + CT_GET = (1 << CT_GET_BIT), + + CT_FLUSH_BIT = 5, + CT_FLUSH = (1 << CT_FLUSH_BIT), + + CT_EVENT_BIT = 6, + CT_EVENT = (1 << CT_EVENT_BIT), + + CT_VERSION_BIT = 7, + CT_VERSION = (1 << CT_VERSION_BIT), + + CT_HELP_BIT = 8, + CT_HELP = (1 << CT_HELP_BIT), + + EXP_LIST_BIT = 9, + EXP_LIST = (1 << EXP_LIST_BIT), + + EXP_CREATE_BIT = 10, + EXP_CREATE = (1 << EXP_CREATE_BIT), + + EXP_DELETE_BIT = 11, + EXP_DELETE = (1 << EXP_DELETE_BIT), + + EXP_GET_BIT = 12, + EXP_GET = (1 << EXP_GET_BIT), + + EXP_FLUSH_BIT = 13, + EXP_FLUSH = (1 << EXP_FLUSH_BIT), + + EXP_EVENT_BIT = 14, + EXP_EVENT = (1 << EXP_EVENT_BIT), +}; +#define NUMBER_OF_CMD 15 + +enum options { + CT_OPT_ORIG_SRC_BIT = 0, + CT_OPT_ORIG_SRC = (1 << CT_OPT_ORIG_SRC_BIT), + + CT_OPT_ORIG_DST_BIT = 1, + CT_OPT_ORIG_DST = (1 << CT_OPT_ORIG_DST_BIT), + + CT_OPT_ORIG = (CT_OPT_ORIG_SRC | CT_OPT_ORIG_DST), + + CT_OPT_REPL_SRC_BIT = 2, + CT_OPT_REPL_SRC = (1 << CT_OPT_REPL_SRC_BIT), + + CT_OPT_REPL_DST_BIT = 3, + CT_OPT_REPL_DST = (1 << CT_OPT_REPL_DST_BIT), + + CT_OPT_REPL = (CT_OPT_REPL_SRC | CT_OPT_REPL_DST), + + CT_OPT_PROTO_BIT = 4, + CT_OPT_PROTO = (1 << CT_OPT_PROTO_BIT), + + CT_OPT_TIMEOUT_BIT = 5, + CT_OPT_TIMEOUT = (1 << CT_OPT_TIMEOUT_BIT), + + CT_OPT_STATUS_BIT = 6, + CT_OPT_STATUS = (1 << CT_OPT_STATUS_BIT), + + CT_OPT_ZERO_BIT = 7, + CT_OPT_ZERO = (1 << CT_OPT_ZERO_BIT), + + CT_OPT_EVENT_MASK_BIT = 8, + CT_OPT_EVENT_MASK = (1 << CT_OPT_EVENT_MASK_BIT), + + CT_OPT_EXP_SRC_BIT = 9, + CT_OPT_EXP_SRC = (1 << CT_OPT_EXP_SRC_BIT), + + CT_OPT_EXP_DST_BIT = 10, + CT_OPT_EXP_DST = (1 << CT_OPT_EXP_DST_BIT), + + CT_OPT_MASK_SRC_BIT = 11, + CT_OPT_MASK_SRC = (1 << CT_OPT_MASK_SRC_BIT), + + CT_OPT_MASK_DST_BIT = 12, + CT_OPT_MASK_DST = (1 << CT_OPT_MASK_DST_BIT), + + CT_OPT_NATRANGE_BIT = 13, + CT_OPT_NATRANGE = (1 << CT_OPT_NATRANGE_BIT), + + CT_OPT_MARK_BIT = 14, + CT_OPT_MARK = (1 << CT_OPT_MARK_BIT), + + CT_OPT_ID_BIT = 15, + CT_OPT_ID = (1 << CT_OPT_ID_BIT), + + CT_OPT_FAMILY_BIT = 16, + CT_OPT_FAMILY = (1 << CT_OPT_FAMILY_BIT), + + CT_OPT_MAX_BIT = CT_OPT_FAMILY_BIT +}; +#define NUMBER_OF_OPT CT_OPT_MAX_BIT+1 + +struct ctproto_handler { + struct list_head head; + + char *name; + u_int16_t protonum; + char *version; + + enum ctattr_protoinfo protoinfo_attr; + + int (*parse_opts)(char c, char *argv[], + struct nfct_tuple *orig, + struct nfct_tuple *reply, + struct nfct_tuple *exptuple, + struct nfct_tuple *mask, + union nfct_protoinfo *proto, + unsigned int *flags); + + int (*final_check)(unsigned int flags, + unsigned int command, + struct nfct_tuple *orig, + struct nfct_tuple *reply); + + void (*help)(); + + struct option *opts; + + unsigned int option_offset; +}; + +extern void register_proto(struct ctproto_handler *h); + +#endif diff --git a/include/conntrackd.h b/include/conntrackd.h new file mode 100644 index 0000000..a5f7a3a --- /dev/null +++ b/include/conntrackd.h @@ -0,0 +1,174 @@ +#ifndef _CONNTRACKD_H_ +#define _CONNTRACKD_H_ + +#include "mcast.h" +#include "local.h" + +#include +#include +#include "cache.h" +#include "debug.h" +#include +#include "state_helper.h" +#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 DEFAULT_CONFIGFILE "/etc/conntrackd/conntrackd.conf" +#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 = (1 << SYNC_MODE_PERSISTENT_BIT), + + SYNC_MODE_NACK_BIT = 4, + SYNC_MODE_NACK = (1 << SYNC_MODE_NACK_BIT), + + DONT_CHECKSUM_BIT = 5, + DONT_CHECKSUM = (1 << DONT_CHECKSUM_BIT), +}; + +/* daemon/request modes */ +#define NOT_SET 0 +#define DAEMON 1 +#define REQUEST 2 + +/* conntrackd modes */ +#define SYNC_MODE 0 +#define STATS_MODE 1 + +/* FILENAME_MAX is 4096 on my system, perhaps too much? */ +#ifndef FILENAME_MAXLEN +#define FILENAME_MAXLEN 256 +#endif + +union inet_address { + u_int32_t ipv4; + u_int32_t ipv6[4]; + u_int32_t all[4]; +}; + +#define CONFIG(x) conf.x + +struct ct_conf { + char logfile[FILENAME_MAXLEN]; + char lockfile[FILENAME_MAXLEN]; + int hashsize; /* hashtable size */ + struct mcast_conf mcast; /* multicast settings */ + struct local_conf local; /* unix socket facilities */ + int limit; + int refresh; + int cache_timeout; /* cache entries timeout */ + int commit_timeout; /* committed entries timeout */ + unsigned int netlink_buffer_size; + unsigned int netlink_buffer_size_max_grown; + unsigned char ignore_protocol[IPPROTO_MAX]; + union inet_address *listen_to; + unsigned int listen_to_len; + unsigned int flags; + int family; /* protocol family */ + unsigned int resend_buffer_size;/* NACK protocol */ + unsigned int window_size; +}; + +#define STATE(x) st.x + +struct ct_general_state { + sigset_t block; + FILE *log; + int local; + struct ct_mode *mode; + 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 */ + u_int64_t malformed; + u_int64_t bytes[NFCT_DIR_MAX]; + u_int64_t packets[NFCT_DIR_MAX]; +}; + +#define STATE_SYNC(x) state.sync->x + +struct ct_sync_state { + struct cache *internal; /* internal events cache (netlink) */ + struct cache *external; /* external events cache (mcast) */ + + struct mcast_sock *mcast_server; /* multicast socket: incoming */ + struct mcast_sock *mcast_client; /* multicast socket: outgoing */ + + struct sync_mode *mcast_sync; + struct buffer *buffer; + + u_int32_t last_seq_sent; /* last sequence number sent */ + u_int32_t last_seq_recv; /* last sequence number recv */ + u_int64_t packets_replayed; /* number of replayed packets */ + u_int64_t packets_lost; /* lost packets: sequence tracking */ +}; + +#define STATE_STATS(x) state.stats->x + +struct ct_stats_state { + struct cache *cache; /* internal events cache (netlink) */ +}; + +union ct_state { + struct ct_sync_state *sync; + struct ct_stats_state *stats; +}; + +extern struct ct_conf conf; +extern union ct_state state; +extern struct ct_general_state st; + +#ifndef IPPROTO_VRRP +#define IPPROTO_VRRP 112 +#endif + +struct ct_mode { + int (*init)(void); + int (*add_fds_to_set)(fd_set *readfds); + void (*step)(fd_set *readfds); + 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 (*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); +}; + +/* conntrackd modes */ +extern struct ct_mode sync_mode; +extern struct ct_mode stats_mode; + +#define MAX(x, y) x > y ? x : y + +#endif diff --git a/include/debug.h b/include/debug.h new file mode 100644 index 0000000..67f2c71 --- /dev/null +++ b/include/debug.h @@ -0,0 +1,53 @@ +#ifndef _DEBUG_H +#define _DEBUG_H + +#if 0 +#define debug printf +#else +#define debug +#endif + +#include +#include +#include + +static inline void debug_ct(struct nf_conntrack *ct, char *msg) +{ + 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"); +} + +#endif diff --git a/include/hash.h b/include/hash.h new file mode 100644 index 0000000..fd971e7 --- /dev/null +++ b/include/hash.h @@ -0,0 +1,47 @@ +#ifndef _NF_SET_HASH_H_ +#define _NF_SET_HASH_H_ + +#include +#include +#include "slist.h" +#include "linux_list.h" + +struct hashtable; +struct hashtable_node; + +struct hashtable { + u_int32_t hashsize; + u_int32_t limit; + u_int32_t count; + u_int32_t initval; + u_int32_t datasize; + + u_int32_t (*hash)(const void *data, struct hashtable *table); + int (*compare)(const void *data1, const void *data2); + + struct slist_head members[0]; +}; + +struct hashtable_node { + struct slist_head head; + char data[0]; +}; + +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, + u_int32_t (*hash)(const void *data, 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_test(struct hashtable *table, const void *data); +int hashtable_del(struct hashtable *table, void *data); +int hashtable_flush(struct hashtable *table); +int hashtable_iterate(struct hashtable *table, void *data, + int (*iterate)(void *data1, void *data2)); +unsigned int hashtable_counter(struct hashtable *table); + +#endif diff --git a/include/ignore.h b/include/ignore.h new file mode 100644 index 0000000..40cb02d --- /dev/null +++ b/include/ignore.h @@ -0,0 +1,12 @@ +#ifndef _IGNORE_H_ +#define _IGNORE_H_ + +struct ignore_pool { + struct hashtable *h; +}; + +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); + +#endif diff --git a/include/jhash.h b/include/jhash.h new file mode 100644 index 0000000..38b8780 --- /dev/null +++ b/include/jhash.h @@ -0,0 +1,146 @@ +#ifndef _LINUX_JHASH_H +#define _LINUX_JHASH_H + +#define u32 unsigned int +#define u8 char + +/* jhash.h: Jenkins hash support. + * + * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net) + * + * http://burtleburtle.net/bob/hash/ + * + * These are the credits from Bob's sources: + * + * lookup2.c, by Bob Jenkins, December 1996, Public Domain. + * hash(), hash2(), hash3, and mix() are externally useful functions. + * Routines to test the hash are included if SELF_TEST is defined. + * You can use this free for any purpose. It has no warranty. + * + * Copyright (C) 2003 David S. Miller (davem@redhat.com) + * + * I've modified Bob's hash to be useful in the Linux kernel, and + * any bugs present are surely my fault. -DaveM + */ + +/* NOTE: Arguments are modified. */ +#define __jhash_mix(a, b, c) \ +{ \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<<8); \ + c -= a; c -= b; c ^= (b>>13); \ + a -= b; a -= c; a ^= (c>>12); \ + b -= c; b -= a; b ^= (a<<16); \ + c -= a; c -= b; c ^= (b>>5); \ + a -= b; a -= c; a ^= (c>>3); \ + b -= c; b -= a; b ^= (a<<10); \ + c -= a; c -= b; c ^= (b>>15); \ +} + +/* The golden ration: an arbitrary value */ +#define JHASH_GOLDEN_RATIO 0x9e3779b9 + +/* The most generic version, hashes an arbitrary sequence + * of bytes. No alignment or length assumptions are made about + * the input key. + */ +static inline u32 jhash(const void *key, u32 length, u32 initval) +{ + u32 a, b, c, len; + const u8 *k = key; + + len = length; + a = b = JHASH_GOLDEN_RATIO; + c = initval; + + while (len >= 12) { + a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24)); + b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24)); + c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24)); + + __jhash_mix(a,b,c); + + k += 12; + len -= 12; + } + + c += length; + switch (len) { + case 11: c += ((u32)k[10]<<24); + case 10: c += ((u32)k[9]<<16); + case 9 : c += ((u32)k[8]<<8); + case 8 : b += ((u32)k[7]<<24); + case 7 : b += ((u32)k[6]<<16); + case 6 : b += ((u32)k[5]<<8); + case 5 : b += k[4]; + case 4 : a += ((u32)k[3]<<24); + case 3 : a += ((u32)k[2]<<16); + case 2 : a += ((u32)k[1]<<8); + case 1 : a += k[0]; + }; + + __jhash_mix(a,b,c); + + return c; +} + +/* A special optimized version that handles 1 or more of u32s. + * The length parameter here is the number of u32s in the key. + */ +static inline u32 jhash2(u32 *k, u32 length, u32 initval) +{ + u32 a, b, c, len; + + a = b = JHASH_GOLDEN_RATIO; + c = initval; + len = length; + + while (len >= 3) { + a += k[0]; + b += k[1]; + c += k[2]; + __jhash_mix(a, b, c); + k += 3; len -= 3; + } + + c += length * 4; + + switch (len) { + case 2 : b += k[1]; + case 1 : a += k[0]; + }; + + __jhash_mix(a,b,c); + + return c; +} + + +/* A special ultra-optimized versions that knows they are hashing exactly + * 3, 2 or 1 word(s). + * + * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally + * done at the end is not done here. + */ +static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval) +{ + a += JHASH_GOLDEN_RATIO; + b += JHASH_GOLDEN_RATIO; + c += initval; + + __jhash_mix(a, b, c); + + return c; +} + +static inline u32 jhash_2words(u32 a, u32 b, u32 initval) +{ + return jhash_3words(a, b, 0, initval); +} + +static inline u32 jhash_1word(u32 a, u32 initval) +{ + return jhash_3words(a, 0, 0, initval); +} + +#endif /* _LINUX_JHASH_H */ diff --git a/include/linux_list.h b/include/linux_list.h new file mode 100644 index 0000000..57b56d7 --- /dev/null +++ b/include/linux_list.h @@ -0,0 +1,725 @@ +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H + +#undef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +/** + * container_of - cast a member of a structure out to the containing structure + * + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +/* + * Check at compile time that something is of a particular type. + * Always evaluates to 1 so you may use it easily in comparisons. + */ +#define typecheck(type,x) \ +({ type __dummy; \ + typeof(x) __dummy2; \ + (void)(&__dummy == &__dummy2); \ + 1; \ +}) + +#define prefetch(x) 1 + +/* empty define to make this work in userspace -HW */ +#ifndef smp_wmb +#define smp_wmb() +#endif + +/* + * These are non-NULL pointers that will result in page faults + * under normal circumstances, used to verify that nobody uses + * non-initialized list entries. + */ +#define LIST_POISON1 ((void *) 0x00100100) +#define LIST_POISON2 ((void *) 0x00200200) + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add_rcu(struct list_head * new, + struct list_head * prev, struct list_head * next) +{ + new->next = next; + new->prev = prev; + smp_wmb(); + next->prev = new; + prev->next = new; +} + +/** + * list_add_rcu - add a new entry to rcu-protected list + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as list_add_rcu() + * or list_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * list_for_each_entry_rcu(). + */ +static inline void list_add_rcu(struct list_head *new, struct list_head *head) +{ + __list_add_rcu(new, head, head->next); +} + +/** + * list_add_tail_rcu - add a new entry to rcu-protected list + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as list_add_tail_rcu() + * or list_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * list_for_each_entry_rcu(). + */ +static inline void list_add_tail_rcu(struct list_head *new, + struct list_head *head) +{ + __list_add_rcu(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} + +/** + * list_del_rcu - deletes entry from list without re-initialization + * @entry: the element to delete from the list. + * + * Note: list_empty on entry does not return true after this, + * the entry is in an undefined state. It is useful for RCU based + * lockfree traversal. + * + * In particular, it means that we can not poison the forward + * pointers that may still be used for walking the list. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as list_del_rcu() + * or list_add_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * list_for_each_entry_rcu(). + * + * Note that the caller is not permitted to immediately free + * the newly deleted entry. Instead, either synchronize_kernel() + * or call_rcu() must be used to defer freeing until an RCU + * grace period has elapsed. + */ +static inline void list_del_rcu(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->prev = LIST_POISON2; +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_empty_careful - tests whether a list is + * empty _and_ checks that no other CPU might be + * in the process of still modifying either member + * + * NOTE: using list_empty_careful() without synchronization + * can only be safe if the only activity that can happen + * to the list entry is list_del_init(). Eg. it cannot be used + * if another CPU could re-list_add() it. + * + * @head: the list to test. + */ +static inline int list_empty_careful(const struct list_head *head) +{ + struct list_head *next = head->next; + return (next == head) && (next == head->prev); +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, prefetch(pos->next)) + +/** + * __list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This variant differs from list_for_each() in that it's the + * simplest possible list iteration code, no prefetching is done. + * Use this for code that knows the list to be very short (empty + * or 1 entry) most of the time. + */ +#define __list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ + pos = pos->prev, prefetch(pos->prev)) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member), \ + prefetch(pos->member.prev); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member), \ + prefetch(pos->member.prev)) + +/** + * list_prepare_entry - prepare a pos entry for use as a start point in + * list_for_each_entry_continue + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the list_struct within the struct. + */ +#define list_prepare_entry(pos, head, member) \ + ((pos) ? : list_entry(head, typeof(*pos), member)) + +/** + * list_for_each_entry_continue - iterate over list of given type + * continuing after existing point + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_rcu - iterate over an rcu-protected list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_rcu(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next)) + +#define __list_for_each_rcu(pos, head) \ + for (pos = (head)->next; pos != (head); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0;})) + +/** + * list_for_each_safe_rcu - iterate over an rcu-protected list safe + * against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_safe_rcu(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next) + +/** + * list_for_each_entry_rcu - iterate over rcu list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_entry_rcu(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + ({ smp_read_barrier_depends(); 0;}), \ + prefetch(pos->member.next)) + + +/** + * list_for_each_continue_rcu - iterate over an rcu-protected list + * continuing after existing point. + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_continue_rcu(pos, head) \ + for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \ + (pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next)) + +/* + * Double linked lists with a single pointer list head. + * Mostly useful for hash tables where the two pointer list head is + * too wasteful. + * You lose the ability to access the tail in O(1). + */ + +struct hlist_head { + struct hlist_node *first; +}; + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +#define HLIST_HEAD_INIT { .first = NULL } +#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } +#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) +#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL) + +static inline int hlist_unhashed(const struct hlist_node *h) +{ + return !h->pprev; +} + +static inline int hlist_empty(const struct hlist_head *h) +{ + return !h->first; +} + +static inline void __hlist_del(struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + *pprev = next; + if (next) + next->pprev = pprev; +} + +static inline void hlist_del(struct hlist_node *n) +{ + __hlist_del(n); + n->next = LIST_POISON1; + n->pprev = LIST_POISON2; +} + +/** + * hlist_del_rcu - deletes entry from hash list without re-initialization + * @n: the element to delete from the hash list. + * + * Note: list_unhashed() on entry does not return true after this, + * the entry is in an undefined state. It is useful for RCU based + * lockfree traversal. + * + * In particular, it means that we can not poison the forward + * pointers that may still be used for walking the hash list. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as hlist_add_head_rcu() + * or hlist_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * hlist_for_each_entry(). + */ +static inline void hlist_del_rcu(struct hlist_node *n) +{ + __hlist_del(n); + n->pprev = LIST_POISON2; +} + +static inline void hlist_del_init(struct hlist_node *n) +{ + if (n->pprev) { + __hlist_del(n); + INIT_HLIST_NODE(n); + } +} + +#define hlist_del_rcu_init hlist_del_init + +static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + if (first) + first->pprev = &n->next; + h->first = n; + n->pprev = &h->first; +} + + +/** + * hlist_add_head_rcu - adds the specified element to the specified hlist, + * while permitting racing traversals. + * @n: the element to add to the hash list. + * @h: the list to add to. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as hlist_add_head_rcu() + * or hlist_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * hlist_for_each_entry(), but only if smp_read_barrier_depends() + * is used to prevent memory-consistency problems on Alpha CPUs. + * Regardless of the type of CPU, the list-traversal primitive + * must be guarded by rcu_read_lock(). + * + * OK, so why don't we have an hlist_for_each_entry_rcu()??? + */ +static inline void hlist_add_head_rcu(struct hlist_node *n, + struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + n->pprev = &h->first; + smp_wmb(); + if (first) + first->pprev = &n->next; + h->first = n; +} + +/* next must be != NULL */ +static inline void hlist_add_before(struct hlist_node *n, + struct hlist_node *next) +{ + n->pprev = next->pprev; + n->next = next; + next->pprev = &n->next; + *(n->pprev) = n; +} + +static inline void hlist_add_after(struct hlist_node *n, + struct hlist_node *next) +{ + next->next = n->next; + n->next = next; + next->pprev = &n->next; + + if(next->next) + next->next->pprev = &next->next; +} + +#define hlist_entry(ptr, type, member) container_of(ptr,type,member) + +#define hlist_for_each(pos, head) \ + for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \ + pos = pos->next) + +#define hlist_for_each_safe(pos, n, head) \ + for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ + pos = n) + +/** + * hlist_for_each_entry - iterate over list of given type + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry(tpos, pos, head, member) \ + for (pos = (head)->first; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_continue - iterate over a hlist continuing after existing point + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_continue(tpos, pos, member) \ + for (pos = (pos)->next; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_from - iterate over a hlist continuing from existing point + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_from(tpos, pos, member) \ + for (; pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @n: another &struct hlist_node to use as temporary storage + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ + for (pos = (head)->first; \ + pos && ({ n = pos->next; 1; }) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = n) + +/** + * hlist_for_each_entry_rcu - iterate over rcu list of given type + * @pos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as hlist_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define hlist_for_each_entry_rcu(tpos, pos, head, member) \ + for (pos = (head)->first; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0; }) ) + +#endif diff --git a/include/local.h b/include/local.h new file mode 100644 index 0000000..350b8bf --- /dev/null +++ b/include/local.h @@ -0,0 +1,29 @@ +#ifndef _LOCAL_SOCKET_H_ +#define _LOCAL_SOCKET_H_ + +#include + +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX 108 +#endif + +struct local_conf { + int backlog; + int reuseaddr; + char path[UNIX_PATH_MAX]; +}; + +/* local server */ +int local_server_create(struct local_conf *conf); +void local_server_destroy(int fd); +int do_local_server_step(int fd, void *data, + void (*process)(int fd, void *data)); + +/* local client */ +int local_client_create(struct local_conf *conf); +void local_client_destroy(int fd); +int do_local_client_step(int fd, void (*process)(char *buf)); +int do_local_request(int, struct local_conf *,void (*step)(char *buf)); +void local_step(char *buf); + +#endif diff --git a/include/log.h b/include/log.h new file mode 100644 index 0000000..9ecff30 --- /dev/null +++ b/include/log.h @@ -0,0 +1,10 @@ +#ifndef _LOG_H_ +#define _LOG_H_ + +#include + +FILE *init_log(char *filename); +void dlog(FILE *fd, char *format, ...); +void close_log(FILE *fd); + +#endif diff --git a/include/mcast.h b/include/mcast.h new file mode 100644 index 0000000..0f3e3cd --- /dev/null +++ b/include/mcast.h @@ -0,0 +1,48 @@ +#ifndef _MCAST_H_ +#define _MCAST_H_ + +#include + +struct mcast_conf { + int ipproto; + int backlog; + int reuseaddr; + unsigned short port; + union { + struct in_addr inet_addr; + struct in6_addr inet_addr6; + } in; + union { + struct in_addr interface_addr; + struct in6_addr interface_addr6; + } ifa; +}; + +struct mcast_stats { + u_int64_t bytes; + u_int64_t messages; + u_int64_t error; +}; + +struct mcast_sock { + int fd; + union { + struct sockaddr_in ipv4; + struct sockaddr_in6 ipv6; + } addr; + struct mcast_stats stats; +}; + +struct mcast_sock *mcast_server_create(struct mcast_conf *conf); +void mcast_server_destroy(struct mcast_sock *m); + +struct mcast_sock *mcast_client_create(struct mcast_conf *conf); +void mcast_client_destroy(struct mcast_sock *m); + +int mcast_send(struct mcast_sock *m, void *data, int size); +int mcast_recv(struct mcast_sock *m, void *data, int size); + +struct mcast_stats *mcast_get_stats(struct mcast_sock *m); +void mcast_dump_stats(int fd, struct mcast_sock *s, struct mcast_sock *r); + +#endif diff --git a/include/network.h b/include/network.h new file mode 100644 index 0000000..dab50db --- /dev/null +++ b/include/network.h @@ -0,0 +1,34 @@ +#ifndef _NETWORK_H_ +#define _NETWORK_H_ + +#include + +struct nlnetwork { + u_int16_t flags; + u_int16_t checksum; + u_int32_t seq; +}; + +struct nlnetwork_ack { + u_int16_t flags; + u_int16_t checksum; + u_int32_t seq; + u_int32_t from; + u_int32_t to; +}; + +enum { + NET_HELLO_BIT = 0, + NET_HELLO = (1 << NET_HELLO_BIT), + + NET_RESYNC_BIT = 1, + NET_RESYNC = (1 << NET_RESYNC_BIT), + + NET_NACK_BIT = 2, + NET_NACK = (1 << NET_NACK_BIT), + + NET_ACK_BIT = 3, + NET_ACK = (1 << NET_ACK_BIT), +}; + +#endif diff --git a/include/slist.h b/include/slist.h new file mode 100644 index 0000000..ab7fa34 --- /dev/null +++ b/include/slist.h @@ -0,0 +1,41 @@ +#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 && ({ prefetch(pos.next); 1; }); \ + 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/state_helper.h b/include/state_helper.h new file mode 100644 index 0000000..1ed0b79 --- /dev/null +++ b/include/state_helper.h @@ -0,0 +1,20 @@ +#ifndef _STATE_HELPER_H_ +#define _STATE_HELPER_H_ + +enum { + ST_H_SKIP, + ST_H_REPLICATE +}; + +struct state_replication_helper { + u_int8_t proto; + unsigned int state; + + int (*verdict)(const struct state_replication_helper *h, + const struct nf_conntrack *ct); +}; + +int state_helper_verdict(int type, struct nf_conntrack *ct); +void state_helper_register(struct state_replication_helper *h, int state); + +#endif diff --git a/include/sync.h b/include/sync.h new file mode 100644 index 0000000..7756c87 --- /dev/null +++ b/include/sync.h @@ -0,0 +1,23 @@ +#ifndef _SYNC_HOOKS_H_ +#define _SYNC_HOOKS_H_ + +struct nlnetwork; +struct us_conntrack; + +struct sync_mode { + int internal_cache_flags; + int external_cache_flags; + struct cache_extra *internal_cache_extra; + struct cache_extra *external_cache_extra; + + int (*init)(void); + void (*kill)(void); + int (*local)(int fd, int type, void *data); + int (*pre_recv)(const struct nlnetwork *net); + void (*post_send)(const struct nlnetwork *net, struct us_conntrack *u); +}; + +extern struct sync_mode notrack; +extern struct sync_mode nack; + +#endif diff --git a/include/us-conntrack.h b/include/us-conntrack.h new file mode 100644 index 0000000..3d71e22 --- /dev/null +++ b/include/us-conntrack.h @@ -0,0 +1,13 @@ +#ifndef _US_CONNTRACK_H_ +#define _US_CONNTRACK_H_ + +#include + +/* be careful, do not modify the layout */ +struct us_conntrack { + struct nf_conntrack *ct; + struct cache *cache; /* add new attributes here */ + char data[0]; +}; + +#endif diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..381f8ac --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,26 @@ +include $(top_srcdir)/Make_global.am + +YACC=@YACC@ -d + +CLEANFILES = read_config_yy.c read_config_lex.c + +sbin_PROGRAMS = conntrack conntrackd + +conntrack_SOURCES = conntrack.c +conntrack_LDFLAGS = -rdynamic + +conntrackd_SOURCES = alarm.c main.c run.c hash.c buffer.c \ + local.c log.c mcast.c netlink.c proxy.c lock.c \ + ignore_pool.c \ + cache.c cache_iterators.c \ + cache_lifetime.c cache_timer.c \ + sync-mode.c sync-notrack.c sync-nack.c \ + traffic_stats.c stats-mode.c \ + network.c checksum.c \ + state_helper.c state_helper_tcp.c \ + read_config_yy.y read_config_lex.l + +conntrackd_LDFLAGS = $(all_libraries) -lnfnetlink -lnetfilter_conntrack \ + -lpthread + +EXTRA_DIST = read_config_yy.h diff --git a/src/alarm.c b/src/alarm.c new file mode 100644 index 0000000..1a465c2 --- /dev/null +++ b/src/alarm.c @@ -0,0 +1,141 @@ +/* + * (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 +#include "linux_list.h" +#include "conntrackd.h" +#include "alarm.h" +#include "jhash.h" +#include +#include +#include + +/* alarm cascade */ +#define ALARM_CASCADE_SIZE 10 +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)); +} + +void destroy_alarm(struct alarm_list *t) +{ + free(t); +} + +void set_alarm_expiration(struct alarm_list *t, unsigned long expires) +{ + t->expires = expires; +} + +void set_alarm_function(struct alarm_list *t, + void (*fcn)(struct alarm_list *a, void *data)) +{ + t->function = fcn; +} + +void set_alarm_data(struct alarm_list *t, void *data) +{ + t->data = data; +} + +void init_alarm(struct alarm_list *t) +{ + INIT_LIST_HEAD(&t->head); + + t->expires = 0; + t->data = 0; + t->function = NULL; +} + +void add_alarm(struct alarm_list *alarm) +{ + unsigned int pos = jhash(alarm, sizeof(alarm), 0) % ALARM_CASCADE_SIZE; + + list_add(&alarm->head, &alarm_cascade[pos]); +} + +void del_alarm(struct alarm_list *alarm) +{ + list_del(&alarm->head); +} + +int mod_alarm(struct alarm_list *alarm, unsigned long expires) +{ + alarm->expires = expires; + return 0; +} + +void __run_alarms() +{ + 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; + + t->expires--; + 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 i; + + alarm_cascade = malloc(sizeof(struct list_head) * ALARM_CASCADE_SIZE); + if (alarm_cascade == NULL) + return -1; + + for (i=0; i + * + * 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" + +struct buffer *buffer_create(size_t max_size) +{ + struct buffer *b; + + b = malloc(sizeof(struct buffer)); + if (b == NULL) + return NULL; + memset(b, 0, sizeof(struct buffer)); + + b->max_size = max_size; + INIT_LIST_HEAD(&b->head); + pthread_mutex_init(&b->lock, NULL); + + return b; +} + +void buffer_destroy(struct buffer *b) +{ + struct list_head *i, *tmp; + struct buffer_node *node; + + pthread_mutex_lock(&b->lock); + 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); +} + +static struct buffer_node *buffer_node_create(const void *data, size_t size) +{ + struct buffer_node *n; + + n = malloc(sizeof(struct buffer_node) + size); + if (n == NULL) + return NULL; + + INIT_LIST_HEAD(&n->head); + n->size = size; + memcpy(n->data, data, size); + + return n; +} + +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; + ret = -1; + goto err; + } + +retry: + /* buffer is full: kill the oldest entry */ + if (b->cur_size + size > b->max_size) { + n = (struct buffer_node *) b->head.prev; + list_del(b->head.prev); + b->cur_size -= n->size; + free(n); + goto retry; + } + + n = buffer_node_create(data, size); + if (n == NULL) { + ret = -1; + goto err; + } + + list_add(&n->head, &b->head); + b->cur_size += size; + +err: + pthread_mutex_unlock(&b->lock); + return ret; +} + +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; + 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)) +{ + 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); +} diff --git a/src/cache.c b/src/cache.c new file mode 100644 index 0000000..6f7442b --- /dev/null +++ b/src/cache.c @@ -0,0 +1,446 @@ +/* + * (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 "jhash.h" +#include "hash.h" +#include "conntrackd.h" +#include +#include +#include "us-conntrack.h" +#include "cache.h" +#include "debug.h" + +static u_int32_t hash(const void *data, 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(u_int32_t), + ((nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16) | + (nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)))); + + b = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV4_DST), sizeof(u_int32_t), + ((nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16) | + (nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)))); + + return jhash_2words(a, b, 0) % table->hashsize; +} + +static u_int32_t hash6(const void *data, 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(u_int32_t), + ((nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16) | + (nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)))); + + b = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV6_DST), sizeof(u_int32_t), + ((nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16) | + (nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)))); + + return jhash_2words(a, b, 0) % table->hashsize; +} + +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) == + 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 compare(const void *data1, const void *data2) +{ + 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) == + 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 void *data1, const void *data2) +{ + 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)); +} + +struct cache_feature *cache_feature[CACHE_MAX_FEATURE] = { + [TIMER_FEATURE] = &timer_feature, + [LIFETIME_FEATURE] = &lifetime_feature, +}; + +struct cache *cache_create(char *name, + unsigned int features, + u_int8_t proto, + struct cache_extra *extra) +{ + size_t size = sizeof(struct us_conntrack); + int i, j = 0; + struct cache *c; + struct cache_feature *feature_array[CACHE_MAX_FEATURE] = {}; + unsigned int feature_offset[CACHE_MAX_FEATURE] = {}; + unsigned int feature_type[CACHE_MAX_FEATURE] = {}; + + c = malloc(sizeof(struct cache)); + if (!c) + return NULL; + memset(c, 0, sizeof(struct cache)); + + strcpy(c->name, name); + + for (i = 0; i < CACHE_MAX_FEATURE; i++) { + if ((1 << i) & features) { + feature_array[j] = cache_feature[i]; + feature_offset[j] = size; + feature_type[i] = j; + size += cache_feature[i]->size; + j++; + } + } + + memcpy(c->feature_type, feature_type, sizeof(feature_type)); + + c->features = malloc(sizeof(struct cache_feature) * j); + if (!c->features) { + free(c); + return NULL; + } + memcpy(c->features, feature_array, sizeof(struct cache_feature) * j); + c->num_features = j; + + c->extra_offset = size; + c->extra = extra; + if (extra) + size += extra->size; + + c->feature_offset = malloc(sizeof(unsigned int) * j); + if (!c->feature_offset) { + free(c->features); + free(c); + return NULL; + } + 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; + } + + if (!c->h) { + free(c->features); + free(c->feature_offset); + free(c); + return NULL; + } + + return c; +} + +void cache_destroy(struct cache *c) +{ + lock(); + hashtable_destroy(c->h); + unlock(); + free(c->features); + free(c->feature_offset); + free(c); +} + +static struct us_conntrack *__add(struct cache *c, struct nf_conntrack *ct) +{ + int i; + size_t size = c->h->datasize; + char buf[size]; + struct us_conntrack *u = (struct us_conntrack *) buf; + struct nf_conntrack *newct; + + memset(u, 0, size); + + u->cache = c; + if ((u->ct = newct = nfct_new()) == NULL) { + errno = ENOMEM; + return 0; + } + memcpy(u->ct, ct, nfct_sizeof(ct)); + + u = hashtable_add(c->h, u); + if (u) { + void *data = u->data; + + for (i = 0; i < c->num_features; i++) { + c->features[i]->add(u, data); + data += c->features[i]->size; + } + + if (c->extra) + c->extra->add(u, ((void *) u) + c->extra_offset); + + return u; + } + free(newct); + + return NULL; +} + +struct us_conntrack *__cache_add(struct cache *c, struct nf_conntrack *ct) +{ + struct us_conntrack *u; + + u = __add(c, ct); + if (u) { + c->add_ok++; + return u; + } + c->add_fail++; + + 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; + char buf[size]; + struct us_conntrack *u = (struct us_conntrack *) buf; + + u->ct = ct; + + u = (struct us_conntrack *) hashtable_test(c->h, u); + if (u) { + int i; + void *data = u->data; + + for (i = 0; i < c->num_features; i++) { + c->features[i]->update(u, data); + data += c->features[i]->size; + } + + if (c->extra) + c->extra->update(u, ((void *) u) + c->extra_offset); + + 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)); + + return u; + } + return NULL; +} + +struct us_conntrack *__cache_update(struct cache *c, struct nf_conntrack *ct) +{ + struct us_conntrack *u; + + u = __update(c, ct); + if (u) { + c->upd_ok++; + return u; + } + c->upd_fail++; + + return NULL; +} + +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; +} + +struct us_conntrack *cache_update_force(struct cache *c, + struct nf_conntrack *ct) +{ + 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; +} + +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; + + lock(); + ret = hashtable_test(c->h, u); + unlock(); + + return ret != NULL; +} + +static int __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; + + u = (struct us_conntrack *) hashtable_test(c->h, u); + if (u) { + int i; + void *data = u->data; + struct nf_conntrack *p = u->ct; + + for (i = 0; i < c->num_features; i++) { + c->features[i]->destroy(u, data); + data += c->features[i]->size; + } + + if (c->extra) + c->extra->destroy(u, ((void *) u) + c->extra_offset); + + hashtable_del(c->h, u); + free(p); + return 1; + } + return 0; +} + +int __cache_del(struct cache *c, struct nf_conntrack *ct) +{ + if (__del(c, ct)) { + c->del_ok++; + return 1; + } + c->del_fail++; + + 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; +} + +void *cache_get_extra(struct cache *c, void *data) +{ + return data + c->extra_offset; +} + +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" + "connections updated:\t\t%12u\tfailed:\t%12u\n" + "connections destroyed:\t\t%12u\tfailed:\t%12u\n\n", + c->name, + hashtable_counter(c->h), + c->add_ok, + c->add_fail, + c->upd_ok, + c->upd_fail, + c->del_ok, + c->del_fail); + unlock(); + send(fd, buf, size, 0); +} diff --git a/src/cache_iterators.c b/src/cache_iterators.c new file mode 100644 index 0000000..5d5d22b --- /dev/null +++ b/src/cache_iterators.c @@ -0,0 +1,229 @@ +/* + * (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 "jhash.h" +#include "hash.h" +#include "conntrackd.h" +#include +#include +#include "us-conntrack.h" +#include "debug.h" + +struct __dump_container { + int fd; + int type; +}; + +static int do_dump(void *data1, void *data2) +{ + char buf[1024]; + int size; + struct __dump_container *container = data1; + struct us_conntrack *u = data2; + void *data = u->data; + int i; + + memset(buf, 0, sizeof(buf)); + size = nfct_snprintf(buf, + sizeof(buf), + u->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; + } + } + 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 + }; + + lock(); + hashtable_iterate(c->h, (void *) &tmp, do_dump); + unlock(); +} + +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; + + 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); + + /* + * Set a reduced timeout for candidate-to-be-committed + * conntracks that live in the external cache + */ + nfct_set_attr_u32(ct, ATTR_TIMEOUT, CONFIG(commit_timeout)); + + ret = nfct_build_query(STATE(subsys_sync), + NFCT_Q_CREATE, + ct, + nlh, + sizeof(buf)); + + free(ct); + + if (ret == -1) { + /* XXX: Please cleanup this debug crap, default in logfile */ + debug("--- failed to build: %s --- \n", strerror(errno)); + return 0; + } + + ret = nfnl_query(STATE(sync), nlh); + if (ret == -1) { + switch(errno) { + case EEXIST: + c->commit_exist++; + break; + default: + 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 */ + return 0; +} + +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; + + lock(); + hashtable_iterate(c->h, c, do_commit); + unlock(); + + /* 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; + + /* log results */ + dlog(STATE(log), "Committed %u new entries", commit_ok); + + if (commit_exist) + dlog(STATE(log), "%u entries ignored, " + "already exist", commit_exist); + if (commit_fail) + dlog(STATE(log), "%u entries can't be " + "committed", commit_fail); +} + +static int do_flush(void *data1, void *data2) +{ + struct cache *c = data1; + struct us_conntrack *u = data2; + void *data = u->data; + int i; + + for (i = 0; i < c->num_features; i++) { + c->features[i]->destroy(u, data); + data += c->features[i]->size; + } + free(u->ct); + + return 0; +} + +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; + char buf[4096]; + struct nlnetwork *net = (struct nlnetwork *) buf; + + ret = build_network_msg(NFCT_Q_UPDATE, + STATE(subsys_sync), + u->ct, + buf, + sizeof(buf)); + if (ret == -1) + debug_ct(u->ct, "failed to build"); + + mcast_send_netmsg(STATE_SYNC(mcast_client), net); + STATE_SYNC(mcast_sync)->post_send(net, 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_lifetime.c b/src/cache_lifetime.c new file mode 100644 index 0000000..ae54df2 --- /dev/null +++ b/src/cache_lifetime.c @@ -0,0 +1,65 @@ +/* + * (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 "conntrackd.h" +#include "us-conntrack.h" +#include "cache.h" +#include "alarm.h" + +static void lifetime_add(struct us_conntrack *u, void *data) +{ + long *lifetime = data; + struct timeval tv; + + gettimeofday(&tv, NULL); + + *lifetime = tv.tv_sec; +} + +static void lifetime_update(struct us_conntrack *u, void *data) +{ +} + +static void lifetime_destroy(struct us_conntrack *u, void *data) +{ +} + +static int lifetime_dump(struct us_conntrack *u, + 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/cache_timer.c b/src/cache_timer.c new file mode 100644 index 0000000..213b59a --- /dev/null +++ b/src/cache_timer.c @@ -0,0 +1,72 @@ +/* + * (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 "conntrackd.h" +#include "us-conntrack.h" +#include "cache.h" +#include "alarm.h" + +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); +} + +static void timer_add(struct us_conntrack *u, void *data) +{ + struct alarm_list *alarm = data; + + init_alarm(alarm); + set_alarm_expiration(alarm, CONFIG(cache_timeout)); + set_alarm_data(alarm, u); + set_alarm_function(alarm, timeout); + add_alarm(alarm); +} + +static void timer_update(struct us_conntrack *u, void *data) +{ + struct alarm_list *alarm = data; + mod_alarm(alarm, CONFIG(cache_timeout)); +} + +static void timer_destroy(struct us_conntrack *u, void *data) +{ + struct alarm_list *alarm = data; + del_alarm(alarm); +} + +static int timer_dump(struct us_conntrack *u, void *data, char *buf, int type) +{ + struct alarm_list *alarm = data; + + if (type == NFCT_O_XML) + return 0; + + return sprintf(buf, " [expires in %ds]", alarm->expires); +} + +struct cache_feature timer_feature = { + .size = sizeof(struct alarm_list), + .add = timer_add, + .update = timer_update, + .destroy = timer_destroy, + .dump = timer_dump +}; diff --git a/src/checksum.c b/src/checksum.c new file mode 100644 index 0000000..41866ff --- /dev/null +++ b/src/checksum.c @@ -0,0 +1,32 @@ +/* + * Extracted from RFC 1071 with some minor changes to fix compilation on GCC, + * this can probably be improved + * --pablo 11/feb/07 + */ + +#include + +unsigned short do_csum(const void *addr, unsigned int count) +{ + unsigned int sum = 0; + + /* checksumming disabled, just skip */ + if (CONFIG(flags) & DONT_CHECKSUM) + return 0; + + while(count > 1) { + /* This is the inner loop */ + sum += *((unsigned short *) addr++); + count -= 2; + } + + /* Add left-over byte, if any */ + if(count > 0) + sum += *((unsigned char *) addr); + + /* Fold 32-bit sum to 16 bits */ + while (sum>>16) + sum = (sum & 0xffff) + (sum >> 16); + + return ~sum; +} diff --git a/src/conntrack.c b/src/conntrack.c new file mode 100644 index 0000000..30fbf69 --- /dev/null +++ b/src/conntrack.c @@ -0,0 +1,1131 @@ +/* + * (C) 2005 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. + * + * Note: + * Yes, portions of this code has been stolen from iptables ;) + * Special thanks to the the Netfilter Core Team. + * Thanks to Javier de Miguel Rodriguez + * for introducing me to advanced firewalling stuff. + * + * --pablo 13/04/2005 + * + * 2005-04-16 Harald Welte : + * Add support for conntrack accounting and conntrack mark + * 2005-06-23 Harald Welte : + * Add support for expect creation + * 2005-09-24 Harald Welte : + * Remove remaints of "-A" + * + */ +#include +#include +#include +#include +#include +#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'}; + +static const char cmd_need_param[NUMBER_OF_CMD] += { 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2 }; + +static const char optflags[NUMBER_OF_OPT] += {'s','d','r','q','p','t','u','z','e','[',']','{','}','a','m','i','f'}; + +static struct option original_opts[] = { + {"dump", 2, 0, 'L'}, + {"create", 1, 0, 'I'}, + {"delete", 1, 0, 'D'}, + {"update", 1, 0, 'U'}, + {"get", 1, 0, 'G'}, + {"flush", 1, 0, 'F'}, + {"event", 1, 0, 'E'}, + {"version", 0, 0, 'V'}, + {"help", 0, 0, 'h'}, + {"orig-src", 1, 0, 's'}, + {"orig-dst", 1, 0, 'd'}, + {"reply-src", 1, 0, 'r'}, + {"reply-dst", 1, 0, 'q'}, + {"protonum", 1, 0, 'p'}, + {"timeout", 1, 0, 't'}, + {"status", 1, 0, 'u'}, + {"zero", 0, 0, 'z'}, + {"event-mask", 1, 0, 'e'}, + {"tuple-src", 1, 0, '['}, + {"tuple-dst", 1, 0, ']'}, + {"mask-src", 1, 0, '{'}, + {"mask-dst", 1, 0, '}'}, + {"nat-range", 1, 0, 'a'}, + {"mark", 1, 0, 'm'}, + {"id", 2, 0, 'i'}, + {"family", 1, 0, 'f'}, + {0, 0, 0, 0} +}; + +#define OPTION_OFFSET 256 + +static struct nfct_handle *cth; +static struct option *opts = original_opts; +static unsigned int global_option_offset = 0; + +/* Table of legal combinations of commands and options. If any of the + * given commands make an option legal, that option is legal (applies to + * CMD_LIST and CMD_ZERO only). + * Key: + * 0 illegal + * 1 compulsory + * 2 optional + */ + +static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = +/* Well, it's better than "Re: Linux vs FreeBSD" */ +{ + /* s d r q p t u z e x y k l a m i f*/ +/*CT_LIST*/ {2,2,2,2,2,0,0,2,0,0,0,0,0,0,2,2,2}, +/*CT_CREATE*/ {2,2,2,2,1,1,1,0,0,0,0,0,0,2,2,0,0}, +/*CT_UPDATE*/ {2,2,2,2,1,2,2,0,0,0,0,0,0,0,2,2,0}, +/*CT_DELETE*/ {2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,0}, +/*CT_GET*/ {2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,2,0}, +/*CT_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*CT_EVENT*/ {2,2,2,2,2,0,0,0,2,0,0,0,0,0,2,0,0}, +/*VERSION*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*HELP*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_LIST*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2}, +/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0}, +/*EXP_DELETE*/{1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_GET*/ {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +}; + +static char *lib_dir = CONNTRACK_LIB_DIR; + +static LIST_HEAD(proto_list); + +void register_proto(struct ctproto_handler *h) +{ + if (strcmp(h->version, VERSION) != 0) { + fprintf(stderr, "plugin `%s': version %s (I'm %s)\n", + h->name, h->version, VERSION); + exit(1); + } + list_add(&h->head, &proto_list); +} + +static struct ctproto_handler *findproto(char *name) +{ + struct list_head *i; + struct ctproto_handler *cur = NULL, *handler = NULL; + + if (!name) + return handler; + + lib_dir = getenv("CONNTRACK_LIB_DIR"); + if (!lib_dir) + lib_dir = CONNTRACK_LIB_DIR; + + list_for_each(i, &proto_list) { + cur = (struct ctproto_handler *) i; + if (strcmp(cur->name, name) == 0) { + handler = cur; + break; + } + } + + if (!handler) { + char path[sizeof("ct_proto_.so") + + strlen(name) + strlen(lib_dir)]; + sprintf(path, "%s/ct_proto_%s.so", lib_dir, name); + if (dlopen(path, RTLD_NOW)) + handler = findproto(name); + else + fprintf(stderr, "%s\n", dlerror()); + } + + return handler; +} + +enum exittype { + OTHER_PROBLEM = 1, + PARAMETER_PROBLEM, + VERSION_PROBLEM +}; + +void extension_help(struct ctproto_handler *h) +{ + fprintf(stdout, "\n"); + fprintf(stdout, "Proto `%s' help:\n", h->name); + h->help(); +} + +void +exit_tryhelp(int status) +{ + fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n", + PROGNAME, PROGNAME); + exit(status); +} + +static void +exit_error(enum exittype status, char *msg, ...) +{ + va_list args; + + /* On error paths, make sure that we don't leak the memory + * reserved during options merging */ + if (opts != original_opts) { + free(opts); + opts = original_opts; + global_option_offset = 0; + } + va_start(args, msg); + fprintf(stderr,"%s v%s: ", PROGNAME, VERSION); + vfprintf(stderr, msg, args); + va_end(args); + fprintf(stderr, "\n"); + if (status == PARAMETER_PROBLEM) + exit_tryhelp(status); + exit(status); +} + +static void +generic_cmd_check(int command, int options) +{ + int i; + + for (i = 0; i < NUMBER_OF_CMD; i++) { + if (!(command & (1< illegal, 1 => legal, 0 => undecided. */ + + for (j = 0; j < NUMBER_OF_CMD; j++) { + if (!(command & (1<size; i++) + if (strncasecmp(str, p->parameter[i], strlen) == 0) { + *value |= p->value[i]; + ret = 1; + break; + } + + return ret; +} + +static void +parse_parameter(const char *arg, unsigned int *status, int parse_type) +{ + const char *comma; + + while ((comma = strchr(arg, ',')) != NULL) { + if (comma == arg + || !do_parse_parameter(arg, comma-arg, status, parse_type)) + exit_error(PARAMETER_PROBLEM,"Bad parameter `%s'", arg); + arg = comma+1; + } + + if (strlen(arg) == 0 + || !do_parse_parameter(arg, strlen(arg), status, parse_type)) + exit_error(PARAMETER_PROBLEM, "Bad parameter `%s'", arg); +} + +static void +add_command(unsigned int *cmd, const int newcmd, const int othercmds) +{ + if (*cmd & (~othercmds)) + exit_error(PARAMETER_PROBLEM, "Invalid commands combination\n"); + *cmd |= newcmd; +} + +unsigned int check_type(int argc, char *argv[]) +{ + char *table = NULL; + + /* Nasty bug or feature in getopt_long ? + * It seems that it behaves badly with optional arguments. + * Fortunately, I just stole the fix from iptables ;) */ + if (optarg) + return 0; + else if (optind < argc && argv[optind][0] != '-' + && argv[optind][0] != '!') + table = argv[optind++]; + + if (!table) + return 0; + + if (strncmp("expect", table, 6) == 0) + return 1; + else if (strncmp("conntrack", table, 9) == 0) + return 0; + else + exit_error(PARAMETER_PROBLEM, "unknown type `%s'\n", table); + + return 0; +} + +static void set_family(int *family, int new) +{ + if (*family == AF_UNSPEC) + *family = new; + else if (*family != new) + exit_error(PARAMETER_PROBLEM, "mismatched address family\n"); +} + +struct addr_parse { + struct in_addr addr; + struct in6_addr addr6; + unsigned int family; +}; + +int __parse_inetaddr(const char *cp, struct addr_parse *parse) +{ + if (inet_aton(cp, &parse->addr)) + return AF_INET; +#ifdef HAVE_INET_PTON_IPV6 + else if (inet_pton(AF_INET6, cp, &parse->addr6) > 0) + return AF_INET6; +#endif + + exit_error(PARAMETER_PROBLEM, "Invalid IP address `%s'.", cp); +} + +int parse_inetaddr(const char *cp, union nfct_address *address) +{ + struct addr_parse parse; + int ret; + + if ((ret = __parse_inetaddr(cp, &parse)) == AF_INET) + address->v4 = parse.addr.s_addr; + else if (ret == AF_INET6) + memcpy(address->v6, &parse.addr6, sizeof(parse.addr6)); + + return ret; +} + +/* Shamelessly stolen from libipt_DNAT ;). Ranges expected in network order. */ +static void +nat_parse(char *arg, int portok, struct nfct_nat *range) +{ + char *colon, *dash, *error; + struct addr_parse parse; + + memset(range, 0, sizeof(range)); + colon = strchr(arg, ':'); + + if (colon) { + int port; + + if (!portok) + exit_error(PARAMETER_PROBLEM, + "Need TCP or UDP with port specification"); + + port = atoi(colon+1); + if (port == 0 || port > 65535) + exit_error(PARAMETER_PROBLEM, + "Port `%s' not valid\n", colon+1); + + error = strchr(colon+1, ':'); + if (error) + exit_error(PARAMETER_PROBLEM, + "Invalid port:port syntax - use dash\n"); + + dash = strchr(colon, '-'); + if (!dash) { + range->l4min.tcp.port + = range->l4max.tcp.port + = htons(port); + } else { + int maxport; + + maxport = atoi(dash + 1); + if (maxport == 0 || maxport > 65535) + exit_error(PARAMETER_PROBLEM, + "Port `%s' not valid\n", dash+1); + if (maxport < port) + /* People are stupid. */ + exit_error(PARAMETER_PROBLEM, + "Port range `%s' funky\n", colon+1); + range->l4min.tcp.port = htons(port); + range->l4max.tcp.port = htons(maxport); + } + /* Starts with a colon? No IP info... */ + if (colon == arg) + return; + *colon = '\0'; + } + + dash = strchr(arg, '-'); + if (colon && dash && dash > colon) + dash = NULL; + + if (dash) + *dash = '\0'; + + if (__parse_inetaddr(arg, &parse) != AF_INET) + return; + + range->min_ip = parse.addr.s_addr; + if (dash) { + if (__parse_inetaddr(dash+1, &parse) != AF_INET) + return; + range->max_ip = parse.addr.s_addr; + } else + range->max_ip = parse.addr.s_addr; +} + +static void event_sighandler(int s) +{ + fprintf(stdout, "Now closing conntrack event dumping...\n"); + nfct_close(cth); + exit(0); +} + +static const char usage_commands[] = + "Commands:\n" + " -L [table] [options]\t\tList conntrack or expectation table\n" + " -G [table] parameters\t\tGet conntrack or expectation\n" + " -D [table] parameters\t\tDelete conntrack or expectation\n" + " -I [table] parameters\t\tCreate a conntrack or expectation\n" + " -U [table] parameters\t\tUpdate a conntrack\n" + " -E [table] [options]\t\tShow events\n" + " -F [table]\t\t\tFlush table\n"; + +static const char usage_tables[] = + "Tables: conntrack, expect\n"; + +static const char usage_conntrack_parameters[] = + "Conntrack parameters and options:\n" + " -a, --nat-range min_ip[-max_ip]\tNAT ip range\n" + " -m, --mark mark\t\t\tSet mark\n" + " -e, --event-mask eventmask\t\tEvent mask, eg. NEW,DESTROY\n" + " -z, --zero \t\t\t\tZero counters while listing\n" + ; + +static const char usage_expectation_parameters[] = + "Expectation parameters and options:\n" + " --tuple-src ip\tSource address in expect tuple\n" + " --tuple-dst ip\tDestination address in expect tuple\n" + " --mask-src ip\t\tSource mask address\n" + " --mask-dst ip\t\tDestination mask address\n"; + +static const char usage_parameters[] = + "Common parameters and options:\n" + " -s, --orig-src ip\t\tSource address from original direction\n" + " -d, --orig-dst ip\t\tDestination address from original direction\n" + " -r, --reply-src ip\t\tSource addres from reply direction\n" + " -q, --reply-dst ip\t\tDestination address from reply direction\n" + " -p, --protonum proto\t\tLayer 4 Protocol, eg. 'tcp'\n" + " -f, --family proto\t\tLayer 3 Protocol, eg. 'ipv6'\n" + " -t, --timeout timeout\t\tSet timeout\n" + " -u, --status status\t\tSet status, eg. ASSURED\n" + " -i, --id [id]\t\t\tShow or set conntrack ID\n" + ; + + +void usage(char *prog) { + fprintf(stdout, "Tool to manipulate conntrack and expectations. Version %s\n", VERSION); + fprintf(stdout, "Usage: %s [commands] [options]\n", prog); + + fprintf(stdout, "\n%s", usage_commands); + fprintf(stdout, "\n%s", usage_tables); + fprintf(stdout, "\n%s", usage_conntrack_parameters); + fprintf(stdout, "\n%s", usage_expectation_parameters); + fprintf(stdout, "\n%s", usage_parameters); +} + +#define CT_COMPARISON (CT_OPT_PROTO | CT_OPT_ORIG | CT_OPT_REPL | CT_OPT_MARK) + +static struct nfct_tuple orig, reply, mask; +static struct nfct_tuple exptuple; +static struct ctproto_handler *h; +static union nfct_protoinfo proto; +static struct nfct_nat range; +static struct nfct_conntrack *ct; +static struct nfct_expect *exp; +static unsigned long timeout; +static unsigned int status; +static unsigned int mark; +static unsigned int id = NFCT_ANY_ID; +static struct nfct_conntrack_compare cmp; + +int main(int argc, char *argv[]) +{ + int c; + unsigned int command = 0, options = 0; + unsigned int type = 0, event_mask = 0; + unsigned int l3flags = 0, l4flags = 0, metaflags = 0; + int res = 0; + int family = AF_UNSPEC; + struct nfct_conntrack_compare *pcmp; + + while ((c = getopt_long(argc, argv, + "L::I::U::D::G::E::F::hVs:d:r:q:p:t:u:e:a:z[:]:{:}:m:i::f:", + opts, NULL)) != -1) { + switch(c) { + case 'L': + type = check_type(argc, argv); + if (type == 0) + add_command(&command, CT_LIST, CT_NONE); + else if (type == 1) + add_command(&command, EXP_LIST, CT_NONE); + break; + case 'I': + type = check_type(argc, argv); + if (type == 0) + add_command(&command, CT_CREATE, CT_NONE); + else if (type == 1) + add_command(&command, EXP_CREATE, CT_NONE); + break; + case 'U': + type = check_type(argc, argv); + if (type == 0) + add_command(&command, CT_UPDATE, CT_NONE); + else + exit_error(PARAMETER_PROBLEM, "Can't update " + "expectations"); + break; + case 'D': + type = check_type(argc, argv); + if (type == 0) + add_command(&command, CT_DELETE, CT_NONE); + else if (type == 1) + add_command(&command, EXP_DELETE, CT_NONE); + break; + case 'G': + type = check_type(argc, argv); + if (type == 0) + add_command(&command, CT_GET, CT_NONE); + else if (type == 1) + add_command(&command, EXP_GET, CT_NONE); + break; + case 'F': + type = check_type(argc, argv); + if (type == 0) + add_command(&command, CT_FLUSH, CT_NONE); + else if (type == 1) + add_command(&command, EXP_FLUSH, CT_NONE); + break; + case 'E': + type = check_type(argc, argv); + if (type == 0) + add_command(&command, CT_EVENT, CT_NONE); + else if (type == 1) + add_command(&command, EXP_EVENT, CT_NONE); + break; + case 'V': + add_command(&command, CT_VERSION, CT_NONE); + break; + case 'h': + add_command(&command, CT_HELP, CT_NONE); + break; + case 's': + options |= CT_OPT_ORIG_SRC; + if (optarg) { + orig.l3protonum = + parse_inetaddr(optarg, &orig.src); + set_family(&family, orig.l3protonum); + if (orig.l3protonum == AF_INET) + l3flags |= IPV4_ORIG_SRC; + else if (orig.l3protonum == AF_INET6) + l3flags |= IPV6_ORIG_SRC; + } + break; + case 'd': + options |= CT_OPT_ORIG_DST; + if (optarg) { + orig.l3protonum = + parse_inetaddr(optarg, &orig.dst); + set_family(&family, orig.l3protonum); + if (orig.l3protonum == AF_INET) + l3flags |= IPV4_ORIG_DST; + else if (orig.l3protonum == AF_INET6) + l3flags |= IPV6_ORIG_DST; + } + break; + case 'r': + options |= CT_OPT_REPL_SRC; + if (optarg) { + reply.l3protonum = + parse_inetaddr(optarg, &reply.src); + set_family(&family, reply.l3protonum); + if (orig.l3protonum == AF_INET) + l3flags |= IPV4_REPL_SRC; + else if (orig.l3protonum == AF_INET6) + l3flags |= IPV6_REPL_SRC; + } + break; + case 'q': + options |= CT_OPT_REPL_DST; + if (optarg) { + reply.l3protonum = + parse_inetaddr(optarg, &reply.dst); + set_family(&family, reply.l3protonum); + if (orig.l3protonum == AF_INET) + l3flags |= IPV4_REPL_DST; + else if (orig.l3protonum == AF_INET6) + l3flags |= IPV6_REPL_DST; + } + break; + case 'p': + options |= CT_OPT_PROTO; + h = findproto(optarg); + if (!h) + exit_error(PARAMETER_PROBLEM, "proto needed\n"); + orig.protonum = h->protonum; + reply.protonum = h->protonum; + exptuple.protonum = h->protonum; + mask.protonum = h->protonum; + opts = merge_options(opts, h->opts, + &h->option_offset); + break; + case 't': + options |= CT_OPT_TIMEOUT; + if (optarg) + timeout = atol(optarg); + break; + case 'u': { + if (!optarg) + continue; + + options |= CT_OPT_STATUS; + parse_parameter(optarg, &status, PARSE_STATUS); + break; + } + case 'e': + options |= CT_OPT_EVENT_MASK; + parse_parameter(optarg, &event_mask, PARSE_EVENT); + break; + case 'z': + options |= CT_OPT_ZERO; + break; + case '{': + options |= CT_OPT_MASK_SRC; + if (optarg) { + mask.l3protonum = + parse_inetaddr(optarg, &mask.src); + set_family(&family, mask.l3protonum); + } + break; + case '}': + options |= CT_OPT_MASK_DST; + if (optarg) { + mask.l3protonum = + parse_inetaddr(optarg, &mask.dst); + set_family(&family, mask.l3protonum); + } + break; + case '[': + options |= CT_OPT_EXP_SRC; + if (optarg) { + exptuple.l3protonum = + parse_inetaddr(optarg, &exptuple.src); + set_family(&family, exptuple.l3protonum); + } + break; + case ']': + options |= CT_OPT_EXP_DST; + if (optarg) { + exptuple.l3protonum = + parse_inetaddr(optarg, &exptuple.dst); + set_family(&family, exptuple.l3protonum); + } + break; + case 'a': + options |= CT_OPT_NATRANGE; + set_family(&family, AF_INET); + nat_parse(optarg, 1, &range); + break; + case 'm': + options |= CT_OPT_MARK; + mark = atol(optarg); + metaflags |= NFCT_MARK; + break; + case 'i': { + char *s = NULL; + options |= CT_OPT_ID; + if (optarg) + break; + else if (optind < argc && argv[optind][0] != '-' + && argv[optind][0] != '!') + s = argv[optind++]; + + if (s) + id = atol(s); + break; + } + case 'f': + options |= CT_OPT_FAMILY; + if (strncmp(optarg, "ipv4", strlen("ipv4")) == 0) + set_family(&family, AF_INET); + else if (strncmp(optarg, "ipv6", strlen("ipv6")) == 0) + set_family(&family, AF_INET6); + else + exit_error(PARAMETER_PROBLEM, "Unknown " + "protocol family\n"); + break; + default: + if (h && h->parse_opts + &&!h->parse_opts(c - h->option_offset, argv, &orig, + &reply, &exptuple, &mask, &proto, + &l4flags)) + exit_error(PARAMETER_PROBLEM, "parse error\n"); + + /* Unknown argument... */ + if (!h) { + usage(argv[0]); + exit_error(PARAMETER_PROBLEM, "Missing " + "arguments...\n"); + } + break; + } + } + + /* default family */ + if (family == AF_UNSPEC) + family = AF_INET; + + generic_cmd_check(command, options); + generic_opt_check(command, options); + + if (!(command & CT_HELP) + && h && h->final_check + && !h->final_check(l4flags, command, &orig, &reply)) { + usage(argv[0]); + extension_help(h); + exit_error(PARAMETER_PROBLEM, "Missing protocol arguments!\n"); + } + + switch(command) { + + case CT_LIST: + cth = nfct_open(CONNTRACK, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + + if (options & CT_COMPARISON) { + + if (options & CT_OPT_ZERO) + exit_error(PARAMETER_PROBLEM, "Can't use -z " + "with filtering parameters"); + + ct = nfct_conntrack_alloc(&orig, &reply, timeout, + &proto, status, mark, id, + NULL); + if (!ct) + exit_error(OTHER_PROBLEM, "Not enough memory"); + + cmp.ct = ct; + cmp.flags = metaflags; + cmp.l3flags = l3flags; + cmp.l4flags = l4flags; + pcmp = &cmp; + } + + if (options & CT_OPT_ID) + nfct_register_callback(cth, + nfct_default_conntrack_display_id, + (void *) pcmp); + else + nfct_register_callback(cth, + nfct_default_conntrack_display, + (void *) pcmp); + + if (options & CT_OPT_ZERO) + res = + nfct_dump_conntrack_table_reset_counters(cth, family); + else + res = nfct_dump_conntrack_table(cth, family); + nfct_close(cth); + break; + + case EXP_LIST: + cth = nfct_open(EXPECT, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + if (options & CT_OPT_ID) + nfct_register_callback(cth, + nfct_default_expect_display_id, + NULL); + else + nfct_register_callback(cth, + nfct_default_expect_display, + NULL); + res = nfct_dump_expect_list(cth, family); + nfct_close(cth); + break; + + case CT_CREATE: + if ((options & CT_OPT_ORIG) + && !(options & CT_OPT_REPL)) { + reply.l3protonum = orig.l3protonum; + memcpy(&reply.src, &orig.dst, sizeof(reply.src)); + memcpy(&reply.dst, &orig.src, sizeof(reply.dst)); + } else if (!(options & CT_OPT_ORIG) + && (options & CT_OPT_REPL)) { + orig.l3protonum = reply.l3protonum; + memcpy(&orig.src, &reply.dst, sizeof(orig.src)); + memcpy(&orig.dst, &reply.src, sizeof(orig.dst)); + } + if (options & CT_OPT_NATRANGE) + ct = nfct_conntrack_alloc(&orig, &reply, timeout, + &proto, status, mark, id, + &range); + else + ct = nfct_conntrack_alloc(&orig, &reply, timeout, + &proto, status, mark, id, + NULL); + if (!ct) + exit_error(OTHER_PROBLEM, "Not Enough memory"); + + cth = nfct_open(CONNTRACK, 0); + if (!cth) { + nfct_conntrack_free(ct); + exit_error(OTHER_PROBLEM, "Can't open handler"); + } + res = nfct_create_conntrack(cth, ct); + nfct_close(cth); + nfct_conntrack_free(ct); + break; + + case EXP_CREATE: + if (options & CT_OPT_ORIG) + exp = nfct_expect_alloc(&orig, &exptuple, + &mask, timeout, id); + else if (options & CT_OPT_REPL) + exp = nfct_expect_alloc(&reply, &exptuple, + &mask, timeout, id); + if (!exp) + exit_error(OTHER_PROBLEM, "Not enough memory"); + + cth = nfct_open(EXPECT, 0); + if (!cth) { + nfct_expect_free(exp); + exit_error(OTHER_PROBLEM, "Can't open handler"); + } + res = nfct_create_expectation(cth, exp); + nfct_expect_free(exp); + nfct_close(cth); + break; + + case CT_UPDATE: + if ((options & CT_OPT_ORIG) + && !(options & CT_OPT_REPL)) { + reply.l3protonum = orig.l3protonum; + memcpy(&reply.src, &orig.dst, sizeof(reply.src)); + memcpy(&reply.dst, &orig.src, sizeof(reply.dst)); + } else if (!(options & CT_OPT_ORIG) + && (options & CT_OPT_REPL)) { + orig.l3protonum = reply.l3protonum; + memcpy(&orig.src, &reply.dst, sizeof(orig.src)); + memcpy(&orig.dst, &reply.src, sizeof(orig.dst)); + } + ct = nfct_conntrack_alloc(&orig, &reply, timeout, + &proto, status, mark, id, + NULL); + if (!ct) + exit_error(OTHER_PROBLEM, "Not enough memory"); + + cth = nfct_open(CONNTRACK, 0); + if (!cth) { + nfct_conntrack_free(ct); + exit_error(OTHER_PROBLEM, "Can't open handler"); + } + res = nfct_update_conntrack(cth, ct); + nfct_conntrack_free(ct); + nfct_close(cth); + break; + + case CT_DELETE: + if (!(options & CT_OPT_ORIG) && !(options & CT_OPT_REPL)) + exit_error(PARAMETER_PROBLEM, "Can't kill conntracks " + "just by its ID"); + cth = nfct_open(CONNTRACK, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + if (options & CT_OPT_ORIG) + res = nfct_delete_conntrack(cth, &orig, + NFCT_DIR_ORIGINAL, + id); + else if (options & CT_OPT_REPL) + res = nfct_delete_conntrack(cth, &reply, + NFCT_DIR_REPLY, + id); + nfct_close(cth); + break; + + case EXP_DELETE: + cth = nfct_open(EXPECT, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + if (options & CT_OPT_ORIG) + res = nfct_delete_expectation(cth, &orig, id); + else if (options & CT_OPT_REPL) + res = nfct_delete_expectation(cth, &reply, id); + nfct_close(cth); + break; + + case CT_GET: + cth = nfct_open(CONNTRACK, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + nfct_register_callback(cth, nfct_default_conntrack_display, + NULL); + if (options & CT_OPT_ORIG) + res = nfct_get_conntrack(cth, &orig, + NFCT_DIR_ORIGINAL, id); + else if (options & CT_OPT_REPL) + res = nfct_get_conntrack(cth, &reply, + NFCT_DIR_REPLY, id); + nfct_close(cth); + break; + + case EXP_GET: + cth = nfct_open(EXPECT, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + nfct_register_callback(cth, nfct_default_expect_display, + NULL); + if (options & CT_OPT_ORIG) + res = nfct_get_expectation(cth, &orig, id); + else if (options & CT_OPT_REPL) + res = nfct_get_expectation(cth, &reply, id); + nfct_close(cth); + break; + + case CT_FLUSH: + cth = nfct_open(CONNTRACK, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + res = nfct_flush_conntrack_table(cth, AF_INET); + nfct_close(cth); + break; + + case EXP_FLUSH: + cth = nfct_open(EXPECT, 0); + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + res = nfct_flush_expectation_table(cth, AF_INET); + nfct_close(cth); + break; + + case CT_EVENT: + if (options & CT_OPT_EVENT_MASK) + cth = nfct_open(CONNTRACK, event_mask); + else + cth = nfct_open(CONNTRACK, NFCT_ALL_CT_GROUPS); + + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + signal(SIGINT, event_sighandler); + + if (options & CT_COMPARISON) { + ct = nfct_conntrack_alloc(&orig, &reply, timeout, + &proto, status, mark, id, + NULL); + if (!ct) + exit_error(OTHER_PROBLEM, "Not enough memory"); + + cmp.ct = ct; + cmp.flags = metaflags; + cmp.l3flags = l3flags; + cmp.l4flags = l4flags; + pcmp = &cmp; + } + + nfct_register_callback(cth, + nfct_default_conntrack_event_display, + (void *) pcmp); + res = nfct_event_conntrack(cth); + nfct_close(cth); + break; + + case EXP_EVENT: + cth = nfct_open(EXPECT, NF_NETLINK_CONNTRACK_EXP_NEW); + if (!cth) + exit_error(OTHER_PROBLEM, "Can't open handler"); + signal(SIGINT, event_sighandler); + nfct_register_callback(cth, nfct_default_expect_display, + NULL); + res = nfct_event_expectation(cth); + nfct_close(cth); + break; + + case CT_VERSION: + fprintf(stdout, "%s v%s\n", PROGNAME, VERSION); + break; + case CT_HELP: + usage(argv[0]); + if (options & CT_OPT_PROTO) + extension_help(h); + break; + default: + usage(argv[0]); + break; + } + + if (opts != original_opts) { + free(opts); + opts = original_opts; + global_option_offset = 0; + } + + if (res < 0) { + fprintf(stderr, "Operation failed: %s\n", err2str(res, command)); + exit(OTHER_PROBLEM); + } + + return 0; +} diff --git a/src/hash.c b/src/hash.c new file mode 100644 index 0000000..274a140 --- /dev/null +++ b/src/hash.c @@ -0,0 +1,199 @@ +/* + * (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. + * + * Description: generic hash table implementation + */ + +#include +#include +#include +#include +#include +#include "slist.h" +#include "hash.h" + + +struct hashtable_node *hashtable_alloc_node(int datasize, void *data) +{ + struct hashtable_node *n; + int size = sizeof(struct hashtable_node) + datasize; + + n = malloc(size); + if (!n) + return NULL; + memset(n, 0, size); + 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, + u_int32_t (*hash)(const void *data, struct hashtable *table), + int (*compare)(const void *data1, const void *data2)) +{ + int i; + struct hashtable *h; + struct hashtype *t; + int size = sizeof(struct hashtable) + + hashsize * sizeof(struct slist_head); + + h = (struct hashtable *) malloc(size); + if (!h) { + errno = ENOMEM; + return NULL; + } + + memset(h, 0, size); + for (i=0; imembers[i]); + + h->hashsize = hashsize; + h->limit = limit; + h->datasize = datasize; + h->hash = hash; + h->compare = compare; + + return h; +} + +void hashtable_destroy(struct hashtable *h) +{ + hashtable_flush(h); + free(h); +} + +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) { + 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; +} + +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); + + slist_for_each(e, &table->members[id]) { + n = slist_entry(e, struct hashtable_node, head); + if (table->compare(n->data, data)) + return n->data; + } + + errno = ENOENT; + return NULL; +} + +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); + + 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; + } + } + errno = ENOENT; + return -1; +} + +int hashtable_flush(struct hashtable *table) +{ + int i; + struct slist_head *e, *next, *prev; + 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); + } + + table->count = 0; + + return 0; +} + +int hashtable_iterate(struct hashtable *table, void *data, + int (*iterate)(void *data1, void *data2)) +{ + int i; + struct slist_head *e, *next, *prev; + 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) + return -1; + } + } + return 0; +} + +unsigned int hashtable_counter(struct hashtable *table) +{ + return table->count; +} diff --git a/src/ignore_pool.c b/src/ignore_pool.c new file mode 100644 index 0000000..5946617 --- /dev/null +++ b/src/ignore_pool.c @@ -0,0 +1,136 @@ +/* + * (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 "jhash.h" +#include "hash.h" +#include "conntrackd.h" +#include "ignore.h" +#include "debug.h" +#include + +#define IGNORE_POOL_SIZE 32 +#define IGNORE_POOL_LIMIT 1024 + +static u_int32_t hash(const void *data, struct hashtable *table) +{ + const u_int32_t *ip = data; + + return jhash_1word(*ip, 0) % table->hashsize; +} + +static u_int32_t hash6(const void *data, struct hashtable *table) +{ + return jhash(data, sizeof(u_int32_t)*4, 0) % table->hashsize; +} + +static int compare(const void *data1, const void *data2) +{ + const u_int32_t *ip1 = data1; + const u_int32_t *ip2 = data2; + + return *ip1 == *ip2; +} + +static int compare6(const void *data1, const void *data2) +{ + return memcmp(data1, data2, sizeof(u_int32_t)*4) == 0; +} + +struct ignore_pool *ignore_pool_create(u_int8_t proto) +{ + int i, j = 0; + struct ignore_pool *ip; + + ip = malloc(sizeof(struct ignore_pool)); + if (!ip) + 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(u_int32_t), + hash, + compare); + break; + case AF_INET6: + ip->h = hashtable_create(IGNORE_POOL_SIZE, + IGNORE_POOL_LIMIT, + sizeof(u_int32_t)*4, + hash6, + compare6); + break; + } + + if (!ip->h) { + free(ip); + return NULL; + } + + return ip; +} + +void ignore_pool_destroy(struct ignore_pool *ip) +{ + hashtable_destroy(ip->h); + free(ip); +} + +int ignore_pool_add(struct ignore_pool *ip, void *data) +{ + if (!hashtable_add(ip->h, data)) + return 0; + + return 1; +} + +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)) || + hashtable_test(ip->h, nfct_get_attr(ct, ATTR_REPL_IPV4_SRC)) || + 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) +{ + 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))); +} + +int ignore_pool_test(struct ignore_pool *ip, struct nf_conntrack *ct) +{ + int ret; + + switch(nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO)) { + case AF_INET: + ret = __ignore_pool_test_ipv4(ip, ct); + break; + case AF_INET6: + ret = __ignore_pool_test_ipv6(ip, ct); + break; + default: + dlog(STATE(log), "unknown conntrack layer 3 protocol?"); + break; + } + + return ret; +} diff --git a/src/local.c b/src/local.c new file mode 100644 index 0000000..eef70ad --- /dev/null +++ b/src/local.c @@ -0,0 +1,159 @@ +/* + * (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. + * + * Description: UNIX sockets library + */ + +#include +#include +#include +#include +#include "debug.h" + +#include "local.h" + +int local_server_create(struct local_conf *conf) +{ + int fd; + int len; + struct sockaddr_un local; + + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + debug("local_server_create:socket"); + return -1; + } + + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &conf->reuseaddr, + sizeof(conf->reuseaddr)) == -1) { + debug("local_server_create:setsockopt"); + close(fd); + return -1; + } + + local.sun_family = AF_UNIX; + strcpy(local.sun_path, conf->path); + len = strlen(local.sun_path) + sizeof(local.sun_family); + 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; + } + + return fd; +} + +void local_server_destroy(int fd) +{ + close(fd); +} + +int do_local_server_step(int fd, void *data, + void (*process)(int fd, void *data)) +{ + int rfd; + 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"); + return -1; + } + + process(rfd, data); + close(rfd); + + return 0; +} + +int local_client_create(struct local_conf *conf) +{ + int len; + struct sockaddr_un local; + int fd; + + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) + return -1; + + local.sun_family = AF_UNIX; + strcpy(local.sun_path, conf->path); + len = strlen(local.sun_path) + sizeof(local.sun_family); + + if (connect(fd, (struct sockaddr *) &local, len) == -1) { + close(fd); + debug("local_client_create: connect: "); + return -1; + } + + return fd; +} + +void local_client_destroy(int fd) +{ + close(fd); +} + +int do_local_client_step(int fd, void (*process)(char *buf)) +{ + int numbytes; + char buf[1024]; + + memset(buf, 0, sizeof(buf)); + while ((numbytes = recv(fd, buf, sizeof(buf)-1, 0)) > 0) { + buf[sizeof(buf)-1] = '\0'; + if (process) + process(buf); + memset(buf, 0, sizeof(buf)); + } + + return 0; +} + +void local_step(char *buf) +{ + printf(buf); +} + +int do_local_request(int request, + struct local_conf *conf, + void (*step)(char *buf)) +{ + int fd, ret; + + fd = local_client_create(conf); + if (fd == -1) + return -1; + + ret = send(fd, &request, sizeof(int), 0); + if (ret == -1) { + debug("send:"); + return -1; + } + + do_local_client_step(fd, step); + + local_client_destroy(fd); + + return 0; +} diff --git a/src/lock.c b/src/lock.c new file mode 100644 index 0000000..cd68baf --- /dev/null +++ b/src/lock.c @@ -0,0 +1,32 @@ +/* + * (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/log.c b/src/log.c new file mode 100644 index 0000000..88cadea --- /dev/null +++ b/src/log.c @@ -0,0 +1,57 @@ +/* + * (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. + * + * Description: Logging support for the conntrack daemon + */ + +#include +#include +#include +#include + +FILE *init_log(char *filename) +{ + FILE *fd; + + fd = fopen(filename, "a+"); + if (fd == NULL) { + fprintf(stderr, "can't open log file `%s'\n", filename); + return NULL; + } + + 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 close_log(FILE *fd) +{ + fclose(fd); +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..1c75970 --- /dev/null +++ b/src/main.c @@ -0,0 +1,302 @@ +/* + * (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 "conntrackd.h" +#include "log.h" +#include +#include +#include +#include +#include +#include +#include "hash.h" +#include "jhash.h" + +struct ct_general_state st; +union ct_state state; + +static const char usage_daemon_commands[] = + "Daemon mode commands:\n" + " -d [options]\t\tRun in daemon mode\n" + " -S [options]\t\tRun in statistics mode\n"; + +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, flush kernel conntrack table\n" + " -i, display content of the internal cache\n" + " -e, display the content of the external cache\n" + " -k, kill conntrack daemon\n" + " -s, dump statistics\n" + " -R, resync with kernel conntrack table\n" + " -n, request resync with other node (only NACK mode)\n" + " -x, dump cache in XML format (requires -i or -e)"; + +static const char usage_options[] = + "Options:\n" + " -C [configfile], configuration file path\n"; + +void show_usage(char *progname) +{ + fprintf(stdout, "Connection tracking userspace daemon v%s\n", VERSION); + fprintf(stdout, "Usage: %s [commands] [options]\n\n", progname); + fprintf(stdout, "%s\n", usage_daemon_commands); + fprintf(stdout, "%s\n", usage_client_commands); + fprintf(stdout, "%s\n", usage_options); +} + +/* These live in run.c */ +int init(int); +void run(void); + +void set_operation_mode(int *current, int want, char *argv[]) +{ + if (*current == NOT_SET) { + *current = want; + return; + } + if (*current != want) { + show_usage(argv[0]); + fprintf(stderr, "\nError: Invalid parameters\n"); + exit(EXIT_FAILURE); + } +} + +static int check_capabilities(void) +{ + int ret; + cap_user_header_t hcap; + cap_user_data_t dcap; + + hcap = malloc(sizeof(cap_user_header_t)); + if (!hcap) + return -1; + + hcap->version = _LINUX_CAPABILITY_VERSION; + hcap->pid = getpid(); + + dcap = malloc(sizeof(cap_user_data_t)); + if (!dcap) { + free(hcap); + return -1; + } + + if (capget(hcap, dcap) == -1) { + free(hcap); + free(dcap); + return -1; + } + + ret = dcap->permitted & (1 << CAP_NET_ADMIN); + + free(hcap); + free(dcap); + + return ret; +} + +int main(int argc, char *argv[]) +{ + int ret, i, config_set = 0, action; + char config_file[PATH_MAX]; + int type = 0, mode = 0; + struct utsname u; + int version, major, minor; + + /* Check kernel version: it must be >= 2.6.18 */ + if (uname(&u) == -1) { + fprintf(stderr, "Can't retrieve kernel version via uname()\n"); + exit(EXIT_FAILURE); + } + sscanf(u.release, "%d.%d.%d", &version, &major, &minor); + if (version < 2 && major < 6) { + fprintf(stderr, "Linux kernel version must be >= 2.6.18\n"); + exit(EXIT_FAILURE); + } + + if (major == 6 && minor < 18) { + fprintf(stderr, "Linux kernel version must be >= 2.6.18\n"); + exit(EXIT_FAILURE); + } + + ret = check_capabilities(); + switch (ret) { + case -1: + fprintf(stderr, "Can't get capabilities\n"); + exit(EXIT_FAILURE); + break; + case 0: + fprintf(stderr, "You require CAP_NET_ADMIN in order " + "to run conntrackd\n"); + exit(EXIT_FAILURE); + break; + default: + break; + } + + for (i=1; i= PATH_MAX){ + config_file[PATH_MAX-1]='\0'; + fprintf(stderr, "Path to config file " + "to long. Cutting it " + "down to %d characters", + PATH_MAX); + } + config_set = 1; + break; + } + show_usage(argv[0]); + fprintf(stderr, "Missing config filename\n"); + break; + case 'F': + set_operation_mode(&type, REQUEST, argv); + action = FLUSH_MASTER; + case 'f': + set_operation_mode(&type, REQUEST, argv); + action = FLUSH_CACHE; + break; + case 'R': + set_operation_mode(&type, REQUEST, argv); + action = RESYNC_MASTER; + break; + case 'B': + set_operation_mode(&type, REQUEST, argv); + action = SEND_BULK; + break; + case 'k': + set_operation_mode(&type, REQUEST, argv); + action = KILL; + break; + case 's': + set_operation_mode(&type, REQUEST, argv); + action = STATS; + break; + case 'S': + set_operation_mode(&mode, STATS_MODE, argv); + break; + case 'n': + set_operation_mode(&type, REQUEST, argv); + action = REQUEST_DUMP; + break; + case 'x': + if (action == DUMP_INTERNAL) + action = DUMP_INT_XML; + else if (action == DUMP_EXTERNAL) + action = DUMP_EXT_XML; + else { + show_usage(argv[0]); + fprintf(stderr, "Error: Invalid parameters\n"); + exit(EXIT_FAILURE); + + } + break; + default: + show_usage(argv[0]); + fprintf(stderr, "Unknown option: %s\n", argv[i]); + return 0; + break; + } + } + + if (config_set == 0) + strcpy(config_file, DEFAULT_CONFIGFILE); + + if ((ret = init_config(config_file)) == -1) { + fprintf(stderr, "can't open config file `%s'\n", config_file); + exit(EXIT_FAILURE); + } + + /* + * Setting up logfile + */ + STATE(log) = init_log(CONFIG(logfile)); + if (!STATE(log)) { + fprintf(stdout, "can't open logfile `%s\n'", CONFIG(logfile)); + exit(EXIT_FAILURE); + } + + if (type == REQUEST) { + if (do_local_request(action, &conf.local, local_step) == -1) + fprintf(stderr, "can't connect: is conntrackd " + "running? appropiate permissions?\n"); + exit(EXIT_SUCCESS); + } + + /* + * lock file + */ + if ((ret = open(CONFIG(lockfile), O_CREAT | O_EXCL | O_TRUNC)) == -1) { + fprintf(stderr, "lockfile `%s' exists, perhaps conntrackd " + "already running?\n", CONFIG(lockfile)); + exit(EXIT_FAILURE); + } + close(ret); + + /* Daemonize conntrackd */ + if (type == DAEMON) { + pid_t pid; + + if ((pid = fork()) == -1) { + dlog(STATE(log), "fork() failed: " + "%s", strerror(errno)); + exit(EXIT_FAILURE); + } else if (pid) + exit(EXIT_SUCCESS); + + dlog(STATE(log), "--- starting in daemon mode ---"); + } else + dlog(STATE(log), "--- starting in console mode ---"); + + /* + * initialization process + */ + + if (init(mode) == -1) { + close_log(STATE(log)); + fprintf(stderr, "ERROR: conntrackd cannot start, please " + "check the logfile for more info\n"); + unlink(CONFIG(lockfile)); + exit(EXIT_FAILURE); + } + + /* + * run main process + */ + run(); +} diff --git a/src/mcast.c b/src/mcast.c new file mode 100644 index 0000000..9904544 --- /dev/null +++ b/src/mcast.c @@ -0,0 +1,287 @@ +/* + * (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. + * + * Description: multicast socket library + */ +#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) +{ + int yes = 1; + union { + struct ip_mreq ipv4; + struct ipv6_mreq ipv6; + } mreq; + struct mcast_sock *m; + + m = (struct mcast_sock *) malloc(sizeof(struct mcast_sock)); + if (!m) + return NULL; + memset(m, 0, sizeof(struct mcast_sock)); + + switch(conf->ipproto) { + case AF_INET: + mreq.ipv4.imr_multiaddr.s_addr = conf->in.inet_addr.s_addr; + mreq.ipv4.imr_interface.s_addr =conf->ifa.interface_addr.s_addr; + + 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); + break; + + case AF_INET6: + memcpy(&mreq.ipv6.ipv6mr_multiaddr, &conf->in.inet_addr6, + sizeof(u_int32_t) * 4); + memcpy(&mreq.ipv6.ipv6mr_interface, &conf->ifa.interface_addr6, + sizeof(u_int32_t) * 4); + + m->addr.ipv6.sin6_family = AF_INET6; + m->addr.ipv6.sin6_port = htons(conf->port); + m->addr.ipv6.sin6_addr = in6addr_any; + break; + } + + if ((m->fd = socket(conf->ipproto, SOCK_DGRAM, 0)) == -1) { + debug("mcast_sock_server_create:socket"); + free(m); + return NULL; + } + + 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; + } + + if (bind(m->fd, (struct sockaddr *) &m->addr, + sizeof(struct sockaddr)) == -1) { + debug("mcast_sock_server_create:bind"); + close(m->fd); + free(m); + return NULL; + } + + + switch(conf->ipproto) { + 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; + } + break; + 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; + } + break; + } + + return m; +} + +void mcast_server_destroy(struct mcast_sock *m) +{ + close(m->fd); + free(m); +} + +static int +__mcast_client_create_ipv4(struct mcast_sock *m, struct mcast_conf *conf) +{ + int no = 0; + + m->addr.ipv4.sin_family = AF_INET; + m->addr.ipv4.sin_port = htons(conf->port); + m->addr.ipv4.sin_addr = conf->in.inet_addr; + + if (setsockopt(m->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &no, + sizeof(int)) < 0) { + debug("mcast_sock_client_create:setsockopt2"); + close(m->fd); + return -1; + } + + 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); + free(m); + return -1; + } + + return 0; +} + +static int +__mcast_client_create_ipv6(struct mcast_sock *m, struct mcast_conf *conf) +{ + int no = 0; + + m->addr.ipv6.sin6_family = AF_INET6; + m->addr.ipv6.sin6_port = htons(conf->port); + memcpy(&m->addr.ipv6.sin6_addr, + &conf->in.inet_addr6, + sizeof(struct in6_addr)); + + if (setsockopt(m->fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &no, + sizeof(int)) < 0) { + debug("mcast_sock_client_create:setsockopt2"); + close(m->fd); + return -1; + } + + if (setsockopt(m->fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, + &conf->ifa.interface_addr, + sizeof(struct in_addr)) == -1) { + debug("mcast_sock_client_create:setsockopt3"); + close(m->fd); + free(m); + return -1; + } + + return 0; +} + +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)); + if (!m) + return NULL; + memset(m, 0, sizeof(struct mcast_sock)); + + if ((m->fd = socket(conf->ipproto, SOCK_DGRAM, 0)) == -1) { + debug("mcast_sock_client_create:socket"); + return NULL; + } + + switch(conf->ipproto) { + case AF_INET: + ret = __mcast_client_create_ipv4(m, conf); + break; + case AF_INET6: + ret = __mcast_client_create_ipv6(m, conf); + break; + default: + break; + } + + if (ret == -1) { + free(m); + m = NULL; + } + + return m; +} + +void mcast_client_destroy(struct mcast_sock *m) +{ + close(m->fd); + free(m); +} + +int mcast_send(struct mcast_sock *m, void *data, int size) +{ + int ret; + + ret = sendto(m->fd, + data, + size, + 0, + (struct sockaddr *) &m->addr, + sizeof(struct sockaddr)); + if (ret == -1) { + debug("mcast_sock_send"); + m->stats.error++; + return ret; + } + + m->stats.bytes += ret; + m->stats.messages++; + + return ret; +} + +int mcast_recv(struct mcast_sock *m, void *data, int size) +{ + int ret; + socklen_t sin_size = sizeof(struct sockaddr_in); + + ret = recvfrom(m->fd, + data, + size, + 0, + (struct sockaddr *)&m->addr, + &sin_size); + if (ret == -1) { + debug("mcast_sock_recv"); + m->stats.error++; + return ret; + } + + m->stats.bytes += ret; + m->stats.messages++; + + return ret; +} + +struct mcast_stats *mcast_get_stats(struct mcast_sock *m) +{ + return &m->stats; +} + +void mcast_dump_stats(int fd, struct mcast_sock *s, struct mcast_sock *r) +{ + char buf[512]; + int size; + + size = sprintf(buf, "multicast traffic:\n" + "%20llu Bytes sent " + "%20llu Bytes recv\n" + "%20llu Pckts sent " + "%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); + + send(fd, buf, size, 0); +} diff --git a/src/netlink.c b/src/netlink.c new file mode 100644 index 0000000..0bde632 --- /dev/null +++ b/src/netlink.c @@ -0,0 +1,326 @@ +/* + * (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 "conntrackd.h" +#include +#include +#include +#include "us-conntrack.h" +#include +#include +#include "network.h" + +static int ignore_conntrack(struct nf_conntrack *ct) +{ + /* ignore a certain protocol */ + if (CONFIG(ignore_protocol)[nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)]) + 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)) { + 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)) { + debug_ct(ct, "SNAT"); + return 0; + } + + /* Ignore traffic */ + if (ignore_pool_test(STATE(ignore_pool), ct)) { + debug_ct(ct, "ignore traffic"); + return 1; + } + + return 0; +} + +static int nl_event_handler(struct nlmsghdr *nlh, + struct nfattr *nfa[], + 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. + */ + if (ignore_conntrack(ct)) + return NFCT_CB_STOP; + + switch(type) { + case NFCT_T_NEW: + STATE(mode)->event_new(ct, nlh); + break; + case NFCT_T_UPDATE: + STATE(mode)->event_upd(ct, nlh); + break; + case NFCT_T_DESTROY: + if (STATE(mode)->event_dst(ct, nlh)) + update_traffic_stats(ct); + break; + default: + dlog(STATE(log), "received unknown msg from ctnetlink\n"); + break; + } + + return NFCT_CB_STOP; +} + +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(); + if (!STATE(event)) + return -1; + + /* set up socket buffer size */ + if (CONFIG(netlink_buffer_size)) + nfnl_rcvbufsiz(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, + SO_RCVBUF, &read_size, &socklen); + + CONFIG(netlink_buffer_size) = read_size; + } + + /* ensure that maximum grown size is >= than maximum size */ + if (CONFIG(netlink_buffer_size_max_grown) < CONFIG(netlink_buffer_size)) + 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); + + return 0; +} + +static int nl_dump_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: + STATE(mode)->dump(ct, nlh); + break; + default: + dlog(STATE(log), "received unknown msg from ctnetlink"); + break; + } + return NFCT_CB_CONTINUE; +} + +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(); + 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); + + if (nl_dump_conntrack_table(STATE(dump), STATE(subsys_dump)) == -1) + return -1; + + 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) +{ + unsigned int s = CONFIG(netlink_buffer_size) * 2; + + /* already warned that we have reached the maximum buffer size */ + if (warned) + return; + + if (s > CONFIG(netlink_buffer_size_max_grown)) { + dlog(STATE(log), "maximum netlink socket buffer size reached"); + s = CONFIG(netlink_buffer_size_max_grown); + warned = 1; + } + + CONFIG(netlink_buffer_size) = nfnl_rcvbufsiz(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) +{ + 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_sync), + NFCT_Q_FLUSH, + &CONFIG(family), + &req, + sizeof(req)); + + if (nfnl_query(STATE(sync), &req.nlh) == -1) + return -1; + + return 0; +} diff --git a/src/network.c b/src/network.c new file mode 100644 index 0000000..b9be318 --- /dev/null +++ b/src/network.c @@ -0,0 +1,282 @@ +/* + * (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 "conntrackd.h" +#include "network.h" + +#if 0 +#define _TEST_DROP +#else +#undef _TEST_DROP +#endif + +static int drop = 0; /* debugging purposes */ +static unsigned int seq_set, cur_seq; + +static int send_netmsg(struct mcast_sock *m, void *data, unsigned int len) +{ + struct nlnetwork *net = data; + +#ifdef _TEST_DROP + if (++drop > 10) { + drop = 0; + printf("dropping resend (seq=%u)\n", ntohl(net->seq)); + return 0; + } +#endif + return mcast_send(m, net, 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; + + if (!seq_set) { + seq_set = 1; + cur_seq = time(NULL); + net->flags |= NET_HELLO; + } + + net->flags = htons(net->flags); + net->seq = htonl(cur_seq++); + + if (nlh_host2network(nlh) == -1) + return -1; + + net->checksum = 0; + net->checksum = ntohs(do_csum(data, len)); + + return send_netmsg(m, data, len); +} + +int mcast_resend_netmsg(struct mcast_sock *m, void *data) +{ + struct nlnetwork *net = data; + struct nlmsghdr *nlh = data + sizeof(struct nlnetwork); + unsigned int len = htonl(nlh->nlmsg_len) + sizeof(struct nlnetwork); + + net->flags = ntohs(net->flags); + + if (!seq_set) { + seq_set = 1; + cur_seq = time(NULL); + net->flags |= NET_HELLO; + } + + if (net->flags & NET_NACK || net->flags & NET_ACK) { + struct nlnetwork_ack *nack = (struct nlnetwork_ack *) net; + len = sizeof(struct nlnetwork_ack); + } + + net->flags = htons(net->flags); + net->seq = htonl(cur_seq++); + net->checksum = 0; + net->checksum = ntohs(do_csum(data, len)); + + 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); + + if (!seq_set) { + seq_set = 1; + cur_seq = time(NULL); + net->flags |= NET_HELLO; + } + + if (net->flags & NET_NACK || net->flags & NET_ACK) { + struct nlnetwork_ack *nack = (struct nlnetwork_ack *) net; + nack->from = htonl(nack->from); + nack->to = htonl(nack->to); + len = sizeof(struct nlnetwork_ack); + } + + net->flags = htons(net->flags); + net->seq = htonl(cur_seq++); + net->checksum = 0; + net->checksum = ntohs(do_csum(data, len)); + + return send_netmsg(m, data, len); +} + +static int valid_checksum(void *data, unsigned int len) +{ + struct nlnetwork *net = data; + unsigned short checksum, tmp; + + checksum = ntohs(net->checksum); + + /* no checksum, skip */ + if (!checksum) + return 1; + + net->checksum = 0; + tmp = do_csum(data, len); + + return tmp == checksum; +} + +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 nfgenmsg *nfhdr; + + ret = mcast_recv(m, net, len); + if (ret <= 0) + return ret; + + if (ret < sizeof(struct nlnetwork)) + return -1; + + if (!valid_checksum(data, ret)) + return -1; + + net->flags = ntohs(net->flags); + net->seq = ntohl(net->seq); + + if (net->flags & NET_HELLO) + STATE_SYNC(last_seq_recv) = net->seq-1; + + if (net->flags & NET_NACK || net->flags & NET_ACK) { + struct nlnetwork_ack *nack = (struct nlnetwork_ack *) net; + + if (ret < sizeof(struct nlnetwork_ack)) + return -1; + + nack->from = ntohl(nack->from); + nack->to = ntohl(nack->to); + + return ret; + } + + if (net->flags & NET_RESYNC) + return ret; + + /* 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) + sizeof(struct nlnetwork)) + return -1; + + /* this message does not come from ctnetlink */ + if (NFNL_SUBSYS_ID(ntohs(nlh->nlmsg_type)) != NFNL_SUBSYS_CTNETLINK) + 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; + + if (nlh_network2host(nlh) == -1) + return -1; + + return ret; +} + +int mcast_track_seq(u_int32_t seq, u_int32_t *exp_seq) +{ + static int seq_set = 0; + int ret = 1; + + /* netlink sequence tracking initialization */ + if (!seq_set) { + seq_set = 1; + goto out; + } + + /* fast path: we received the correct sequence */ + if (seq == STATE_SYNC(last_seq_recv)+1) + goto out; + + /* out of sequence: some messages got lost */ + if (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: + *exp_seq = STATE_SYNC(last_seq_recv)+1; + /* update expected sequence */ + STATE_SYNC(last_seq_recv) = seq; + + 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 += sizeof(struct nlnetwork); + 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/proxy.c b/src/proxy.c new file mode 100644 index 0000000..b9bb04e --- /dev/null +++ b/src/proxy.c @@ -0,0 +1,124 @@ +/* + * (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/read_config_lex.l b/src/read_config_lex.l new file mode 100644 index 0000000..dee90c9 --- /dev/null +++ b/src/read_config_lex.l @@ -0,0 +1,125 @@ +%{ +/* + * (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. + * + * Description: configuration file syntax + */ + +#include "read_config_yy.h" +#include "conntrackd.h" +%} + +%option yylineno +%option nounput + +ws [ \t]+ +comment #.*$ +nl [\n\r] + +is_on [o|O][n|N] +is_off [o|O][f|F][f|F] +integer [0-9]+ +path \/[^\"\n ]* +ip4_end [0-9]*[0-9]+ +ip4_part [0-2]*{ip4_end} +ip4 {ip4_part}\.{ip4_part}\.{ip4_part}\.{ip4_part} +hex_255 [0-9a-fA-F]{1,4} +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-Z]* +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] + +%% +"UNIX" { return T_UNIX; } +"IPv4_address" { return T_IPV4_ADDR; } +"IPv6_address" { return T_IPV6_ADDR; } +"IPv4_interface" { return T_IPV4_IFACE; } +"IPv6_interface" { return T_IPV6_IFACE; } +"Port" { return T_PORT; } +"Multicast" { return T_MULTICAST; } +"HashSize" { return T_HASHSIZE; } +"RefreshTime" { return T_REFRESH; } +"CacheTimeout" { return T_EXPIRE; } +"CommitTimeout" { return T_TIMEOUT; } +"DelayDestroyMessages" { return T_DELAY; } +"HashLimit" { return T_HASHLIMIT; } +"Path" { return T_PATH; } +"IgnoreProtocol" { return T_IGNORE_PROTOCOL; } +"UDP" { return T_UDP; } +"ICMP" { return T_ICMP; } +"VRRP" { return T_VRRP; } +"IGMP" { return T_IGMP; } +"TCP" { return T_TCP; } +"IgnoreTrafficFor" { return T_IGNORE_TRAFFIC; } +"StripNAT" { return T_STRIP_NAT; } +"Backlog" { return T_BACKLOG; } +"Group" { return T_GROUP; } +"LogFile" { return T_LOG; } +"LockFile" { return T_LOCK; } +"General" { return T_GENERAL; } +"Sync" { return T_SYNC; } +"Stats" { return T_STATS; } +"RelaxTransitions" { return T_RELAX_TRANSITIONS; } +"SocketBufferSize" { return T_BUFFER_SIZE; } +"SocketBufferSizeMaxGrown" { return T_BUFFER_SIZE_MAX_GROWN; } +"SocketBufferSizeMaxGrowth" { return T_BUFFER_SIZE_MAX_GROWN; } +"Mode" { return T_SYNC_MODE; } +"ListenTo" { return T_LISTEN_TO; } +"Family" { return T_FAMILY; } +"ResendBufferSize" { return T_RESEND_BUFFER_SIZE; } +"Checksum" { return T_CHECKSUM; } +"ACKWindowSize" { return T_WINDOWSIZE; } +"Replicate" { return T_REPLICATE; } +"for" { return T_FOR; } +"SYN_SENT" { return T_SYN_SENT; } +"SYN_RECV" { return T_SYN_RECV; } +"ESTABLISHED" { return T_ESTABLISHED; } +"FIN_WAIT" { return T_FIN_WAIT; } +"CLOSE_WAIT" { return T_CLOSE_WAIT; } +"LAST_ACK" { return T_LAST_ACK; } +"TIME_WAIT" { return T_TIME_WAIT; } +"CLOSE" { return T_CLOSE; } +"LISTEN" { return T_LISTEN; } + +{is_on} { return T_ON; } +{is_off} { return T_OFF; } +{integer} { yylval.val = atoi(yytext); return T_NUMBER; } +{ip4} { yylval.string = strdup(yytext); return T_IP; } +{ip6} { yylval.string = strdup(yytext); return T_IP; } +{path} { yylval.string = strdup(yytext); return T_PATH_VAL; } +{persistent} { return T_PERSISTENT; } +{nack} { return T_NACK; } +{string} { yylval.string = strdup(yytext); return T_STRING; } + +{comment} ; +{ws} ; +{nl} ; + +<> { yyterminate(); } + +. { return yytext[0]; } + +%% + +int +yywrap() +{ + return 1; +} diff --git a/src/read_config_yy.y b/src/read_config_yy.y new file mode 100644 index 0000000..1668919 --- /dev/null +++ b/src/read_config_yy.y @@ -0,0 +1,550 @@ +%{ +/* + * (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. + * + * Description: configuration file abstract grammar + */ + +#include +#include +#include +#include +#include "conntrackd.h" +#include "ignore.h" + +extern char *yytext; +extern int yylineno; + +struct ct_conf conf; +%} + +%union { + int val; + char *string; +} + +%token T_IPV4_ADDR T_IPV4_IFACE T_PORT T_HASHSIZE T_HASHLIMIT T_MULTICAST +%token T_PATH T_UNIX T_REFRESH T_IPV6_ADDR T_IPV6_IFACE +%token T_IGNORE_UDP T_IGNORE_ICMP T_IGNORE_TRAFFIC T_BACKLOG T_GROUP +%token T_LOG T_UDP T_ICMP T_IGMP T_VRRP T_TCP T_IGNORE_PROTOCOL +%token T_LOCK T_STRIP_NAT T_BUFFER_SIZE_MAX_GROWN T_EXPIRE T_TIMEOUT +%token T_GENERAL T_SYNC T_STATS T_RELAX_TRANSITIONS T_BUFFER_SIZE T_DELAY +%token T_SYNC_MODE T_LISTEN_TO T_FAMILY T_RESEND_BUFFER_SIZE +%token T_PERSISTENT T_NACK T_CHECKSUM T_WINDOWSIZE T_ON T_OFF +%token T_REPLICATE T_FOR +%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_IP T_PATH_VAL +%token T_NUMBER +%token T_STRING + +%% + +configfile : + | lines + ; + +lines : line + | lines line + ; + +line : ignore_protocol + | ignore_traffic + | strip_nat + | general + | sync + | stats + ; + +log : T_LOG T_PATH_VAL +{ + strncpy(conf.logfile, $2, FILENAME_MAXLEN); +}; + +lock : T_LOCK T_PATH_VAL +{ + strncpy(conf.lockfile, $2, FILENAME_MAXLEN); +}; + +strip_nat: T_STRIP_NAT +{ + conf.flags |= STRIP_NAT; +}; + +refreshtime : T_REFRESH T_NUMBER +{ + conf.refresh = $2; +}; + +expiretime: T_EXPIRE T_NUMBER +{ + conf.cache_timeout = $2; +}; + +timeout: T_TIMEOUT T_NUMBER +{ + conf.commit_timeout = $2; +}; + +checksum: T_CHECKSUM T_ON +{ +}; + +checksum: T_CHECKSUM T_OFF +{ + conf.flags |= DONT_CHECKSUM; +}; + +ignore_traffic : T_IGNORE_TRAFFIC '{' ignore_traffic_options '}'; + +ignore_traffic_options : + | ignore_traffic_options ignore_traffic_option; + +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 (!family) { + fprintf(stdout, "%s is not a valid IP, ignoring", $2); + return; + } + + if (!STATE(ignore_pool)) { + STATE(ignore_pool) = ignore_pool_create(family); + if (!STATE(ignore_pool)) { + fprintf(stdout, "Can't create ignore pool!\n"); + exit(EXIT_FAILURE); + } + } + + if (!ignore_pool_add(STATE(ignore_pool), &ip)) { + if (errno == EEXIST) + fprintf(stdout, "IP %s is repeated " + "in the ignore pool\n", $2); + if (errno == ENOSPC) + fprintf(stdout, "Too many IP in the ignore pool!\n"); + } +}; + +multicast_line : T_MULTICAST '{' multicast_options '}'; + +multicast_options : + | multicast_options multicast_option; + +multicast_option : T_IPV4_ADDR T_IP +{ + if (!inet_aton($2, &conf.mcast.in)) { + fprintf(stderr, "%s is not a valid IPv4 address\n"); + return; + } + + if (conf.mcast.ipproto == AF_INET6) { + fprintf(stderr, "Your multicast address is IPv4 but " + "is binded to an IPv6 interface? Surely " + "this is not what you want\n"); + return; + } + + conf.mcast.ipproto = AF_INET; +}; + +multicast_option : T_IPV6_ADDR T_IP +{ +#ifdef HAVE_INET_PTON_IPV6 + if (inet_pton(AF_INET6, $2, &conf.mcast.in) <= 0) + fprintf(stderr, "%s is not a valid IPv6 address\n", $2); +#endif + + if (conf.mcast.ipproto == AF_INET) { + fprintf(stderr, "Your multicast address is IPv6 but " + "is binded to an IPv4 interface? Surely " + "this is not what you want\n"); + return; + } + + conf.mcast.ipproto = AF_INET6; +}; + +multicast_option : T_IPV4_IFACE T_IP +{ + if (!inet_aton($2, &conf.mcast.ifa)) { + fprintf(stderr, "%s is not a valid IPv4 address\n"); + return; + } + + if (conf.mcast.ipproto == AF_INET6) { + fprintf(stderr, "Your multicast interface is IPv4 but " + "is binded to an IPv6 interface? Surely " + "this is not what you want\n"); + return; + } + + conf.mcast.ipproto = AF_INET; +}; + +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"); + return; + } + + conf.mcast.ipproto = AF_INET6; +}; + +multicast_option : T_BACKLOG T_NUMBER +{ + conf.mcast.backlog = $2; +}; + +multicast_option : T_GROUP T_NUMBER +{ + conf.mcast.port = $2; +}; + +hashsize : T_HASHSIZE T_NUMBER +{ + conf.hashsize = $2; +}; + +hashlimit: T_HASHLIMIT T_NUMBER +{ + conf.limit = $2; +}; + +unix_line: T_UNIX '{' unix_options '}'; + +unix_options: + | unix_options unix_option + ; + +unix_option : T_PATH T_PATH_VAL +{ + strcpy(conf.local.path, $2); +}; + +unix_option : T_BACKLOG T_NUMBER +{ + conf.local.backlog = $2; +}; + +ignore_protocol: T_IGNORE_PROTOCOL '{' ignore_proto_list '}'; + +ignore_proto_list: + | ignore_proto_list ignore_proto + ; + +ignore_proto: T_NUMBER +{ + if ($1 < IPPROTO_MAX) + conf.ignore_protocol[$1] = 1; + else + fprintf(stdout, "Protocol number `%d' is freak\n", $1); +}; + +ignore_proto: T_UDP +{ + conf.ignore_protocol[IPPROTO_UDP] = 1; +}; + +ignore_proto: T_ICMP +{ + conf.ignore_protocol[IPPROTO_ICMP] = 1; +}; + +ignore_proto: T_VRRP +{ + conf.ignore_protocol[IPPROTO_VRRP] = 1; +}; + +ignore_proto: T_IGMP +{ + conf.ignore_protocol[IPPROTO_IGMP] = 1; +}; + +sync: T_SYNC '{' sync_list '}'; + +sync_list: + | sync_list sync_line; + +sync_line: refreshtime + | expiretime + | timeout + | checksum + | multicast_line + | relax_transitions + | delay_destroy_msgs + | sync_mode_persistent + | sync_mode_nack + | listen_to + | state_replication + ; + +sync_mode_persistent: T_SYNC_MODE T_PERSISTENT '{' sync_mode_persistent_list '}' +{ + conf.flags |= SYNC_MODE_PERSISTENT; +}; + +sync_mode_nack: T_SYNC_MODE T_NACK '{' sync_mode_nack_list '}' +{ + conf.flags |= SYNC_MODE_NACK; +}; + +sync_mode_persistent_list: + | sync_mode_persistent_list sync_mode_persistent_line; + +sync_mode_persistent_line: refreshtime + | expiretime + | timeout + | relax_transitions + | delay_destroy_msgs + ; + +sync_mode_nack_list: + | sync_mode_nack_list sync_mode_nack_line; + +sync_mode_nack_line: resend_buffer_size + | timeout + | window_size + ; + +resend_buffer_size: T_RESEND_BUFFER_SIZE T_NUMBER +{ + conf.resend_buffer_size = $2; +}; + +window_size: T_WINDOWSIZE T_NUMBER +{ + conf.window_size = $2; +}; + +relax_transitions: T_RELAX_TRANSITIONS +{ + conf.flags |= RELAX_TRANSITIONS; +}; + +delay_destroy_msgs: T_DELAY +{ + conf.flags |= DELAY_DESTROY_MSG; +}; + +listen_to: T_LISTEN_TO T_IP +{ + union inet_address addr; + +#ifdef HAVE_INET_PTON_IPV6 + if (inet_pton(AF_INET6, $2, &addr.ipv6) <= 0) +#endif + if (inet_aton($2, &addr.ipv4) <= 0) { + fprintf(stderr, "%s is not a valid IP address\n", $2); + exit(EXIT_FAILURE); + } + + if (CONFIG(listen_to_len) == 0 || CONFIG(listen_to_len) % 16) { + CONFIG(listen_to) = realloc(CONFIG(listen_to), + sizeof(union inet_address) * + (CONFIG(listen_to_len) + 16)); + if (CONFIG(listen_to) == NULL) { + fprintf(stderr, "cannot init listen_to array\n"); + exit(EXIT_FAILURE); + } + + memset(CONFIG(listen_to) + + (CONFIG(listen_to_len) * sizeof(union inet_address)), + 0, sizeof(union inet_address) * 16); + + } +}; + +state_replication: T_REPLICATE states T_FOR state_proto; + +states: + | states state; + +state_proto: T_TCP; +state: tcp_state; + +tcp_state: T_SYN_SENT +{ + extern struct state_replication_helper tcp_state_helper; + state_helper_register(&tcp_state_helper, TCP_CONNTRACK_SYN_SENT); +}; +tcp_state: T_SYN_RECV +{ + extern struct state_replication_helper tcp_state_helper; + state_helper_register(&tcp_state_helper, TCP_CONNTRACK_SYN_RECV); +}; +tcp_state: T_ESTABLISHED +{ + extern struct state_replication_helper tcp_state_helper; + state_helper_register(&tcp_state_helper, TCP_CONNTRACK_ESTABLISHED); +}; +tcp_state: T_FIN_WAIT +{ + extern struct state_replication_helper tcp_state_helper; + state_helper_register(&tcp_state_helper, TCP_CONNTRACK_FIN_WAIT); +}; +tcp_state: T_CLOSE_WAIT +{ + extern struct state_replication_helper tcp_state_helper; + state_helper_register(&tcp_state_helper, TCP_CONNTRACK_CLOSE_WAIT); +}; +tcp_state: T_LAST_ACK +{ + extern struct state_replication_helper tcp_state_helper; + state_helper_register(&tcp_state_helper, TCP_CONNTRACK_LAST_ACK); +}; +tcp_state: T_TIME_WAIT +{ + extern struct state_replication_helper tcp_state_helper; + state_helper_register(&tcp_state_helper, TCP_CONNTRACK_TIME_WAIT); +}; +tcp_state: T_CLOSE +{ + extern struct state_replication_helper tcp_state_helper; + state_helper_register(&tcp_state_helper, TCP_CONNTRACK_CLOSE); +}; +tcp_state: T_LISTEN +{ + extern struct state_replication_helper tcp_state_helper; + state_helper_register(&tcp_state_helper, TCP_CONNTRACK_LISTEN); +}; + +general: T_GENERAL '{' general_list '}'; + +general_list: + | general_list general_line + ; + +general_line: hashsize + | hashlimit + | log + | lock + | unix_line + | netlink_buffer_size + | netlink_buffer_size_max_grown + | family + ; + +netlink_buffer_size: T_BUFFER_SIZE T_NUMBER +{ + conf.netlink_buffer_size = $2; +}; + +netlink_buffer_size_max_grown : T_BUFFER_SIZE_MAX_GROWN T_NUMBER +{ + conf.netlink_buffer_size_max_grown = $2; +}; + +family : T_FAMILY T_STRING +{ + if (strncmp($2, "IPv6", strlen("IPv6")) == 0) + conf.family = AF_INET6; + else + conf.family = AF_INET; +}; + +stats: T_SYNC '{' stats_list '}'; + +stats_list: + | stats_list stat_line + ; + +stat_line: + | + ; + +%% + +int +yyerror(char *msg) +{ + printf("Error parsing config file: "); + printf("line (%d), symbol '%s': %s\n", yylineno, yytext, msg); + exit(EXIT_FAILURE); +} + +int +init_config(char *filename) +{ + FILE *fp; + + fp = fopen(filename, "r"); + if (!fp) + return -1; + + yyrestart(fp); + yyparse(); + fclose(fp); + + /* default to IPv4 */ + if (CONFIG(family) == 0) + CONFIG(family) = AF_INET; + + /* set to default is not specified */ + if (strcmp(CONFIG(lockfile), "") == 0) + strncpy(CONFIG(lockfile), DEFAULT_LOCKFILE, FILENAME_MAXLEN); + + /* default to 180 seconds of expiration time: cache entries */ + if (CONFIG(cache_timeout) == 0) + CONFIG(cache_timeout) = 180; + + /* default to 180 seconds: committed entries */ + if (CONFIG(commit_timeout) == 0) + CONFIG(commit_timeout) = 180; + + /* default to 60 seconds of refresh time */ + if (CONFIG(refresh) == 0) + CONFIG(refresh) = 60; + + if (CONFIG(resend_buffer_size) == 0) + CONFIG(resend_buffer_size) = 262144; + + /* create empty pool */ + if (!STATE(ignore_pool)) { + STATE(ignore_pool) = ignore_pool_create(CONFIG(family)); + if (!STATE(ignore_pool)) { + fprintf(stdout, "Can't create ignore pool!\n"); + exit(EXIT_FAILURE); + } + } + + /* default to a window size of 20 packets */ + if (CONFIG(window_size) == 0) + CONFIG(window_size) = 20; + + return 0; +} diff --git a/src/run.c b/src/run.c new file mode 100644 index 0000000..67437d8 --- /dev/null +++ b/src/run.c @@ -0,0 +1,227 @@ +/* + * (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. + * + * Description: run and init functions + */ + +#include "conntrackd.h" +#include +#include +#include "us-conntrack.h" +#include +#include + +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_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)); + STATE(mode)->kill(); + unlink(CONFIG(lockfile)); + dlog(STATE(log), "------- shutdown received ----"); + close_log(STATE(log)); + + sigprocmask(SIG_UNBLOCK, &STATE(block), NULL); + + exit(0); +} + +void local_handler(int fd, void *data) +{ + int ret; + int type; + + ret = read(fd, &type, sizeof(type)); + if (ret == -1) { + dlog(STATE(log), "can't read from unix socket\n"); + return; + } + if (ret == 0) { + debug("nothing to process\n"); + return; + } + + switch(type) { + case FLUSH_MASTER: + dlog(STATE(log), "[REQ] flushing master table"); + nl_flush_master_conntrack_table(); + return; + case RESYNC_MASTER: + dlog(STATE(log), "[REQ] resync with master table"); + nl_dump_conntrack_table(STATE(dump), STATE(subsys_dump)); + return; + } + + if (!STATE(mode)->local(fd, type, data)) + dlog(STATE(log), "[FAIL] unknown local request %d", type); +} + +int init(int mode) +{ + switch(mode) { + case STATS_MODE: + STATE(mode) = &stats_mode; + break; + case SYNC_MODE: + STATE(mode) = &sync_mode; + break; + default: + fprintf(stderr, "Unknown running mode! default " + "to synchronization mode\n"); + STATE(mode) = &sync_mode; + break; + } + + /* Initialization */ + if (STATE(mode)->init() == -1) { + dlog(STATE(log), "[FAIL] initialization failed"); + return -1; + } + + /* local UNIX socket */ + STATE(local) = local_server_create(&CONFIG(local)); + if (!STATE(local)) { + dlog(STATE(log), "[FAIL] 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?"); + return -1; + } + + if (nl_init_dump_handler() == -1) { + dlog(STATE(log), "[FAIL] can't open netlink handler! " + "no ctnetlink kernel support?"); + 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); + sigaddset(&STATE(block), SIGINT); + + if (signal(SIGINT, killer) == SIG_ERR) + return -1; + + if (signal(SIGTERM, killer) == SIG_ERR) + return -1; + + /* ignore connection reset by peer */ + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) + return -1; + + dlog(STATE(log), "[OK] initialization completed"); + + return 0; +} + +#define POLL_NSECS 1 + +static void __run(void) +{ + int max, ret; + fd_set readfds; + struct timeval tv = { + .tv_sec = POLL_NSECS, + .tv_usec = 0 + }; + + FD_ZERO(&readfds); + FD_SET(STATE(local), &readfds); + FD_SET(nfnl_fd(STATE(event)), &readfds); + + max = MAX(STATE(local), nfnl_fd(STATE(event))); + + if (STATE(mode)->add_fds_to_set) + max = MAX(max, STATE(mode)->add_fds_to_set(&readfds)); + + ret = select(max+1, &readfds, NULL, NULL, &tv); + if (ret == -1) { + /* interrupted syscall, retry */ + if (errno == EINTR) + return; + + dlog(STATE(log), "select() failed: %s", strerror(errno)); + return; + } + + /* signals are racy */ + sigprocmask(SIG_BLOCK, &STATE(block), NULL); + + /* order received via UNIX socket */ + if (FD_ISSET(STATE(local), &readfds)) + 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 (ret == -1) { + switch(errno) { + case ENOBUFS: + /* + * It seems that ctnetlink can't back off, + * it's likely that we're losing events. + * Solution: duplicate the socket buffer + * size and resync with master conntrack table. + */ + nl_resize_socket_buffer(STATE(event)); + nl_dump_conntrack_table(STATE(sync), + STATE(subsys_sync)); + break; + case ENOENT: + /* + * We received a message from another + * netfilter subsystem that we are not + * interested in. Just ignore it. + */ + break; + default: + dlog(STATE(log), "event catch says: %s", + strerror(errno)); + break; + } + } + } + + if (STATE(mode)->step) + STATE(mode)->step(&readfds); + + sigprocmask(SIG_UNBLOCK, &STATE(block), NULL); +} + +void run(void) +{ + while(1) + __run(); +} diff --git a/src/state_helper.c b/src/state_helper.c new file mode 100644 index 0000000..81b0d09 --- /dev/null +++ b/src/state_helper.c @@ -0,0 +1,44 @@ +/* + * (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 "conntrackd.h" +#include "state_helper.h" + +static struct state_replication_helper *helper[IPPROTO_MAX]; + +int state_helper_verdict(int type, struct nf_conntrack *ct) +{ + u_int8_t l4proto; + + if (type == NFCT_T_DESTROY) + return ST_H_REPLICATE; + + l4proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO); + if (helper[l4proto]) + return helper[l4proto]->verdict(helper[l4proto], ct); + + return ST_H_REPLICATE; +} + +void state_helper_register(struct state_replication_helper *h, int state) +{ + if (helper[h->proto] == NULL) + helper[h->proto] = h; + + helper[h->proto]->state |= (1 << state); +} diff --git a/src/state_helper_tcp.c b/src/state_helper_tcp.c new file mode 100644 index 0000000..af714dc --- /dev/null +++ b/src/state_helper_tcp.c @@ -0,0 +1,35 @@ +/* + * (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 "conntrackd.h" +#include "state_helper.h" + +static int tcp_verdict(const struct state_replication_helper *h, + const struct nf_conntrack *ct) +{ + u_int8_t state = nfct_get_attr_u8(ct, ATTR_TCP_STATE); + if (h->state & (1 << state)) + return ST_H_REPLICATE; + + return ST_H_SKIP; +} + +struct state_replication_helper tcp_state_helper = { + .proto = IPPROTO_TCP, + .verdict = tcp_verdict, +}; 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 +}; diff --git a/src/sync-mode.c b/src/sync-mode.c new file mode 100644 index 0000000..b32bef7 --- /dev/null +++ b/src/sync-mode.c @@ -0,0 +1,416 @@ +/* + * (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 +#include "sync.h" +#include "network.h" + +/* handler for multicast messages received */ +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; + struct us_conntrack *u = NULL; + + memset(tmp, 0, sizeof(tmp)); + + ret = mcast_recv_netmsg(m, buf, sizeof(buf)); + if (ret <= 0) { + STATE(malformed)++; + return; + } + + if (STATE_SYNC(mcast_sync)->pre_recv(net)) + return; + + if ((type = parse_network_msg(ct, nlh)) == NFCT_T_ERROR) { + STATE(malformed)++; + return; + } + + 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: +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; + } + debug_ct(ct, "can't add"); + } + break; + case NFCT_T_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: + if (cache_del(STATE_SYNC(external), ct)) + debug_ct(ct, "external destroy"); + else + debug_ct(ct, "can't destroy"); + break; + default: + debug("unknown type %d\n", type); + break; + } +} + +static int init_sync(void) +{ + int ret; + + state.sync = malloc(sizeof(struct ct_sync_state)); + if (!state.sync) { + dlog(STATE(log), "[FAIL] can't allocate memory for state sync"); + return -1; + } + memset(state.sync, 0, sizeof(struct ct_sync_state)); + + if (CONFIG(flags) & SYNC_MODE_NACK) + STATE_SYNC(mcast_sync) = &nack; + else + /* default to persistent mode */ + STATE_SYNC(mcast_sync) = ¬rack; + + if (STATE_SYNC(mcast_sync)->init) + STATE_SYNC(mcast_sync)->init(); + + STATE_SYNC(internal) = + cache_create("internal", + STATE_SYNC(mcast_sync)->internal_cache_flags, + CONFIG(family), + STATE_SYNC(mcast_sync)->internal_cache_extra); + + if (!STATE_SYNC(internal)) { + dlog(STATE(log), "[FAIL] can't allocate memory for " + "the internal cache"); + return -1; + } + + STATE_SYNC(external) = + cache_create("external", + STATE_SYNC(mcast_sync)->external_cache_flags, + CONFIG(family), + NULL); + + if (!STATE_SYNC(external)) { + dlog(STATE(log), "[FAIL] 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!"); + 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!"); + return -1; + } + + /* 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; +} + +static int add_fds_to_set_sync(fd_set *readfds) +{ + FD_SET(STATE_SYNC(mcast_server->fd), readfds); + + return STATE_SYNC(mcast_server->fd); +} + +static void step_sync(fd_set *readfds) +{ + /* multicast packet has been received */ + if (FD_ISSET(STATE_SYNC(mcast_server->fd), readfds)) + mcast_handler(); +} + +static void kill_sync() +{ + cache_destroy(STATE_SYNC(internal)); + cache_destroy(STATE_SYNC(external)); + + mcast_server_destroy(STATE_SYNC(mcast_server)); + mcast_client_destroy(STATE_SYNC(mcast_client)); + + destroy_alarm_thread(); + + if (STATE_SYNC(mcast_sync)->kill) + STATE_SYNC(mcast_sync)->kill(); +} + +static dump_stats_sync(int fd) +{ + char buf[512]; + int size; + + size = sprintf(buf, "multicast sequence tracking:\n" + "%20llu Pckts mfrm " + "%20llu Pckts lost\n\n", + STATE(malformed), + STATE_SYNC(packets_lost)); + + send(fd, buf, size, 0); +} + +/* handler for requests coming via UNIX socket */ +static int local_handler_sync(int fd, int type, void *data) +{ + int ret = 1; + + switch(type) { + case DUMP_INTERNAL: + cache_dump(STATE_SYNC(internal), fd, NFCT_O_PLAIN); + break; + case DUMP_EXTERNAL: + cache_dump(STATE_SYNC(external), fd, NFCT_O_PLAIN); + break; + case DUMP_INT_XML: + cache_dump(STATE_SYNC(internal), fd, NFCT_O_XML); + break; + case DUMP_EXT_XML: + cache_dump(STATE_SYNC(external), fd, NFCT_O_XML); + break; + case COMMIT: + dlog(STATE(log), "[REQ] commit external cache to master table"); + cache_commit(STATE_SYNC(external)); + break; + case FLUSH_CACHE: + dlog(STATE(log), "[REQ] flushing caches"); + cache_flush(STATE_SYNC(internal)); + cache_flush(STATE_SYNC(external)); + break; + case KILL: + killer(); + break; + case STATS: + cache_stats(STATE_SYNC(internal), fd); + cache_stats(STATE_SYNC(external), fd); + dump_traffic_stats(fd); + mcast_dump_stats(fd, STATE_SYNC(mcast_client), + 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(mcast_sync)->local) + ret = STATE_SYNC(mcast_sync)->local(fd, type, data); + break; + } + + return ret; +} + +static void dump_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) +{ + /* 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_update_force(STATE_SYNC(internal), ct)) + debug_ct(ct, "resync"); +} + +static void mcast_send_sync(struct nlmsghdr *nlh, + struct us_conntrack *u, + struct nf_conntrack *ct, + int type) +{ + char buf[4096]; + struct nlnetwork *net = (struct nlnetwork *) buf; + int mangled = 0; + + memset(buf, 0, sizeof(buf)); + + if (!state_helper_verdict(type, ct)) + return; + + if (!mangled) + memcpy(buf + sizeof(struct nlnetwork), nlh, nlh->nlmsg_len); + + mcast_send_netmsg(STATE_SYNC(mcast_client), net); + STATE_SYNC(mcast_sync)->post_send(net, u); +} + +static void overrun_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) +{ + struct us_conntrack *u; + + /* 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_SYNC(internal), ct)) { + if ((u = cache_update_force(STATE_SYNC(internal), ct))) { + debug_ct(ct, "overrun resync"); + mcast_send_sync(nlh, u, ct, NFCT_T_UPDATE); + } + } +} + +static void event_new_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) +{ + struct us_conntrack *u; + + /* 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); + nfct_attr_unset(ct, ATTR_TIMEOUT); +retry: + if ((u = cache_add(STATE_SYNC(internal), ct))) { + mcast_send_sync(nlh, u, ct, NFCT_T_NEW); + debug_ct(u->ct, "internal new"); + } else { + if (errno == EEXIST) { + char buf[4096]; + struct nlmsghdr *nlh = (struct nlmsghdr *) buf; + + 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_NEW); + goto retry; + } + dlog(STATE(log), "can't add to internal cache: " + "%s\n", strerror(errno)); + debug_ct(ct, "can't add"); + } +} + +static void event_update_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) +{ + struct us_conntrack *u; + + nfct_attr_unset(ct, ATTR_TIMEOUT); + + if ((u = cache_update(STATE_SYNC(internal), ct)) == NULL) { + /* + * 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) + && (u = cache_add(STATE_SYNC(internal), ct))) { + debug_ct(u->ct, "forcing internal update"); + } else { + debug_ct(ct, "can't update"); + return; + } + } + debug_ct(u->ct, "internal update"); + mcast_send_sync(nlh, u, ct, NFCT_T_UPDATE); +} + +static int event_destroy_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) +{ + nfct_attr_unset(ct, ATTR_TIMEOUT); + + if (CONFIG(flags) & DELAY_DESTROY_MSG) { + + nfct_set_attr_u32(ct, ATTR_STATUS, IPS_DYING); + + if (cache_update(STATE_SYNC(internal), ct)) { + debug_ct(ct, "delay internal destroy"); + return 1; + } else { + debug_ct(ct, "can't delay destroy!"); + return 0; + } + } else { + if (cache_del(STATE_SYNC(internal), ct)) { + mcast_send_sync(nlh, NULL, ct, NFCT_T_DESTROY); + debug_ct(ct, "internal destroy"); + } else + debug_ct(ct, "can't destroy"); + } +} + +struct ct_mode sync_mode = { + .init = init_sync, + .add_fds_to_set = add_fds_to_set_sync, + .step = step_sync, + .local = local_handler_sync, + .kill = kill_sync, + .dump = dump_sync, + .overrun = overrun_sync, + .event_new = event_new_sync, + .event_upd = event_update_sync, + .event_dst = event_destroy_sync +}; diff --git a/src/sync-nack.c b/src/sync-nack.c new file mode 100644 index 0000000..288dba4 --- /dev/null +++ b/src/sync-nack.c @@ -0,0 +1,309 @@ +/* + * (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 "conntrackd.h" +#include "sync.h" +#include "linux_list.h" +#include "us-conntrack.h" +#include "buffer.h" +#include "debug.h" +#include "network.h" +#include +#include + +#if 0 +#define dp printf +#else +#define dp +#endif + +static LIST_HEAD(queue); + +struct cache_nack { + struct list_head head; + 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); + list_add(&cn->head, &queue); +} + +static void cache_nack_update(struct us_conntrack *u, void *data) +{ + struct cache_nack *cn = data; + + if (cn->head.next != LIST_POISON1 && + cn->head.prev != LIST_POISON2) + list_del(&cn->head); + + INIT_LIST_HEAD(&cn->head); + list_add(&cn->head, &queue); +} + +static void cache_nack_destroy(struct us_conntrack *u, void *data) +{ + struct cache_nack *cn = data; + + if (cn->head.next != LIST_POISON1 && + cn->head.prev != LIST_POISON2) + list_del(&cn->head); +} + +static struct cache_extra cache_nack_extra = { + .size = sizeof(struct cache_nack), + .add = cache_nack_add, + .update = cache_nack_update, + .destroy = cache_nack_destroy +}; + +static int nack_init() +{ + STATE_SYNC(buffer) = buffer_create(CONFIG(resend_buffer_size)); + if (STATE_SYNC(buffer) == NULL) + return -1; + + return 0; +} + +static void nack_kill() +{ + buffer_destroy(STATE_SYNC(buffer)); +} + +static void mcast_send_nack(u_int32_t expt_seq, u_int32_t recv_seq) +{ + struct nlnetwork_ack nack = { + .flags = NET_NACK, + .from = expt_seq, + .to = recv_seq, + }; + + mcast_send_error(STATE_SYNC(mcast_client), &nack); + buffer_add(STATE_SYNC(buffer), &nack, sizeof(struct nlnetwork_ack)); +} + +static void mcast_send_ack(u_int32_t from, u_int32_t to) +{ + struct nlnetwork_ack ack = { + .flags = NET_ACK, + .from = from, + .to = to, + }; + + mcast_send_error(STATE_SYNC(mcast_client), &ack); + buffer_add(STATE_SYNC(buffer), &ack, sizeof(struct nlnetwork_ack)); +} + +static void mcast_send_resync() +{ + struct nlnetwork net = { + .flags = NET_RESYNC, + }; + + mcast_send_error(STATE_SYNC(mcast_client), &net); + buffer_add(STATE_SYNC(buffer), &net, sizeof(struct nlnetwork)); +} + +int nack_local(int fd, int type, void *data) +{ + int ret = 1; + + switch(type) { + case REQUEST_DUMP: + mcast_send_resync(); + dlog(STATE(log), "[REQ] request resync"); + break; + default: + ret = 0; + break; + } + + return ret; +} + +static int buffer_compare(void *data1, void *data2) +{ + struct nlnetwork *net = data1; + struct nlnetwork_ack *nack = data2; + struct nlmsghdr *nlh = data1 + sizeof(struct nlnetwork); + + unsigned old_seq = ntohl(net->seq); + + if (ntohl(net->seq) >= nack->from && ntohl(net->seq) <= 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)); + } + return 0; +} + +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) { + dp("remove from buffer (seq=%u)\n", ntohl(net->seq)); + __buffer_del(STATE_SYNC(buffer), data1); + } + return 0; +} + +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; + + u = cache_get_conntrack(STATE_SYNC(internal), cn); + + if (cn->seq >= from && cn->seq <= 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); + STATE_SYNC(mcast_sync)->post_send(net, u); + dp("(newseq=%u)\n", *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; + + u = cache_get_conntrack(STATE_SYNC(internal), cn); + if (cn->seq >= from && cn->seq <= 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); + } + } + unlock(); +} + +static int nack_pre_recv(const struct nlnetwork *net) +{ + static unsigned int window = 0; + unsigned int exp_seq; + + if (window == 0) + window = CONFIG(window_size); + + if (!mcast_track_seq(net->seq, &exp_seq)) { + dp("OOS: sending nack (seq=%u)\n", exp_seq); + mcast_send_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_ack(net->seq-CONFIG(window_size), net->seq); + } + } + + if (net->flags & NET_NACK) { + struct nlnetwork_ack *nack = (struct nlnetwork_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) { + 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; + + 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); + return 1; + } + + return 0; +} + +static void nack_post_send(const struct nlnetwork *net, struct us_conntrack *u) +{ + unsigned int size = sizeof(struct nlnetwork); + struct nlmsghdr *nlh = (struct nlmsghdr *) ((void *) net + size); + + if (NFNL_MSG_TYPE(ntohs(nlh->nlmsg_type)) == IPCTNL_MSG_CT_DELETE) { + buffer_add(STATE_SYNC(buffer), net, + ntohl(nlh->nlmsg_len) + size); + } else if (u != NULL) { + unsigned int *seq; + struct list_head *n; + struct cache_nack *cn; + + cn = (struct cache_nack *) + cache_get_extra(STATE_SYNC(internal), u); + cn->seq = ntohl(net->seq); + if (cn->head.next != LIST_POISON1 && + cn->head.prev != LIST_POISON2) + list_del(&cn->head); + + INIT_LIST_HEAD(&cn->head); + list_add(&cn->head, &queue); + } +} + +struct sync_mode nack = { + .internal_cache_flags = LIFETIME, + .external_cache_flags = LIFETIME, + .internal_cache_extra = &cache_nack_extra, + .init = nack_init, + .kill = nack_kill, + .local = nack_local, + .pre_recv = nack_pre_recv, + .post_send = nack_post_send, +}; diff --git a/src/sync-notrack.c b/src/sync-notrack.c new file mode 100644 index 0000000..2b5ae38 --- /dev/null +++ b/src/sync-notrack.c @@ -0,0 +1,127 @@ +/* + * (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 "conntrackd.h" +#include "sync.h" +#include "network.h" +#include "us-conntrack.h" +#include "alarm.h" + +static void refresher(struct alarm_list *a, void *data) +{ + struct us_conntrack *u = data; + char buf[8192]; + int size; + + if (nfct_get_attr_u32(u->ct, ATTR_STATUS) & IPS_DYING) { + + debug_ct(u->ct, "persistence destroy"); + + 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); + } +} + +static void cache_notrack_add(struct us_conntrack *u, void *data) +{ + struct alarm_list *alarm = data; + + init_alarm(alarm); + set_alarm_expiration(alarm, (random() % conf.refresh) + 1); + set_alarm_data(alarm, u); + set_alarm_function(alarm, refresher); + add_alarm(alarm); +} + +static void cache_notrack_update(struct us_conntrack *u, void *data) +{ + struct alarm_list *alarm = data; + mod_alarm(alarm, (random() % conf.refresh) + 1); +} + +static void cache_notrack_destroy(struct us_conntrack *u, void *data) +{ + struct alarm_list *alarm = data; + del_alarm(alarm); +} + +static struct cache_extra cache_notrack_extra = { + .size = sizeof(struct alarm_list), + .add = cache_notrack_add, + .update = cache_notrack_update, + .destroy = cache_notrack_destroy +}; + +static int notrack_pre_recv(const struct nlnetwork *net) +{ + unsigned int exp_seq; + + /* + * Ignore error messages: Although this message type is not ever + * 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)) + return 1; + + /* + * Multicast sequence tracking: we keep track of multicast messages + * although we don't do any explicit message recovery. So, why do + * we do sequence tracking? Just to let know the sysadmin. + * + * Let t be 1 < t < RefreshTime. To ensure consistency, conntrackd + * retransmit every t seconds a message with the state of a certain + * entry even if such entry did not change. This mechanism also + * provides passive resynchronization, in other words, there is + * no facility to request a full synchronization from new nodes that + * just joined the cluster, instead they just get resynchronized in + * RefreshTime seconds at worst case. + */ + mcast_track_seq(net->seq, &exp_seq); + + return 0; +} + +static void notrack_post_send(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, +}; diff --git a/src/traffic_stats.c b/src/traffic_stats.c new file mode 100644 index 0000000..b510b77 --- /dev/null +++ b/src/traffic_stats.c @@ -0,0 +1,54 @@ +/* + * (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 "cache.h" +#include "hash.h" +#include "conntrackd.h" +#include +#include +#include +#include "us-conntrack.h" +#include + +void update_traffic_stats(struct nf_conntrack *ct) +{ + STATE(bytes)[NFCT_DIR_ORIGINAL] += + nfct_get_attr_u32(ct, ATTR_ORIG_COUNTER_BYTES); + STATE(bytes)[NFCT_DIR_REPLY] += + nfct_get_attr_u32(ct, ATTR_REPL_COUNTER_BYTES); + STATE(packets)[NFCT_DIR_ORIGINAL] += + nfct_get_attr_u32(ct, ATTR_ORIG_COUNTER_PACKETS); + STATE(packets)[NFCT_DIR_REPLY] += + nfct_get_attr_u32(ct, ATTR_REPL_COUNTER_PACKETS); +} + +void dump_traffic_stats(int fd) +{ + char buf[512]; + int size; + u_int64_t bytes = STATE(bytes)[NFCT_DIR_ORIGINAL] + + STATE(bytes)[NFCT_DIR_REPLY]; + u_int64_t packets = STATE(packets)[NFCT_DIR_ORIGINAL] + + 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); + + send(fd, buf, size, 0); +} diff --git a/test.sh b/test.sh new file mode 100644 index 0000000..4694236 --- /dev/null +++ b/test.sh @@ -0,0 +1,110 @@ +CONNTRACK=conntrack + +SRC=1.1.1.1 +DST=2.2.2.2 +SPORT=2005 +DPORT=21 + +case $1 in + dump) + echo "Dumping conntrack table" + $CONNTRACK -L + ;; + flush) + echo "Flushing conntrack table" + $CONNTRACK -F + ;; + new) + echo "creating a new conntrack" + $CONNTRACK -I --orig-src $SRC --orig-dst $DST \ + --reply-src $DST --reply-dst $SRC -p tcp \ + --orig-port-src $SPORT --orig-port-dst $DPORT \ + --reply-port-src $DPORT --reply-port-dst $SPORT \ + --state LISTEN -u SEEN_REPLY -t 50 + ;; + new-simple) + echo "creating a new conntrack (simplified)" + $CONNTRACK -I --orig-src $SRC --orig-dst $DST \ + -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \ + --state LISTEN -u SEEN_REPLY -t 50 + ;; + new-nat) + echo "creating a new conntrack (NAT)" + $CONNTRACK -I --orig-src $SRC --orig-dst $DST \ + -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \ + --state LISTEN -u SEEN_REPLY,SRC_NAT -t 50 -a 8.8.8.8 + ;; + get) + echo "getting a conntrack" + $CONNTRACK -G --orig-src $SRC --orig-dst $DST \ + -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \ + --reply-port-src $DPORT --reply-port-dst $SPORT + ;; + change) + echo "change a conntrack" + $CONNTRACK -U --orig-src $SRC --orig-dst $DST \ + --reply-src $DST --reply-dst $SRC -p tcp \ + --orig-port-src $SPORT --orig-port-dst $DPORT \ + --reply-port-src $DPORT --reply-port-dst $SPORT \ + --state TIME_WAIT -u ASSURED,SEEN_REPLY -t 500 + ;; + delete) + $CONNTRACK -D --orig-src $SRC --orig-dst $DST \ + -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT + ;; + output) + proc=$(cat /proc/net/ip_conntrack | wc -l) + netl=$($CONNTRACK -L | wc -l) + count=$(cat /proc/sys/net/ipv4/netfilter/ip_conntrack_count) + if [ $proc -ne $netl ]; then + echo "proc is $proc and netl is $netl and count is $count" + else + if [ $proc -ne $count ]; then + echo "proc is $proc and netl is $netl and count is $count" + else + echo "now $proc" + fi + fi + ;; + dump-expect) + $CONNTRACK -L expect + ;; + flush-expect) + $CONNTRACK -F expect + ;; + create-expect) + # requires modprobe ip_conntrack_ftp + $CONNTRACK -I expect --orig-src $SRC --orig-dst $DST \ + --tuple-src 4.4.4.4 --tuple-dst 5.5.5.5 \ + --mask-src 255.255.255.0 --mask-dst 255.255.255.255 \ + -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \ + -t 200 --tuple-port-src 10 --tuple-port-dst 300 \ + --mask-port-src 10 --mask-port-dst 300 + ;; + get-expect) + $CONNTRACK -G expect --orig-src 4.4.4.4 --orig-dst 5.5.5.5 \ + --p tcp --orig-port-src 0 --orig-port-dst 0 \ + --mask-port-src 10 --mask-port-dst 11 + ;; + delete-expect) + $CONNTRACK -D expect --orig-src 4.4.4.4 \ + --orig-dst 5.5.5.5 -p tcp --orig-port-src 0 \ + --orig-port-dst 0 --mask-port-src 10 --mask-port-dst 11 + ;; + *) + echo "Usage: $0 [dump" + echo " |new" + echo " |new-simple" + echo " |new-nat" + echo " |get" + echo " |change" + echo " |delete" + echo " |output" + echo " |flush" + echo " |dump-expect" + echo " |flush-expect" + echo " |create-expect" + echo " |get-expect" + echo " |delete-expect]" + ;; +esac -- cgit v1.2.3 From a5af71296069ded90819b9ad2e37b51a0c42e116 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 23:05:09 +0000 Subject: - Merge conntrack and conntrackd changelogs, even if it will be dropped from SVN soon. - Update INSTALL documentation --- CHANGELOG | 184 ---------------------------------------------------------- ChangeLog | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ INSTALL | 105 ++++++++++++++++----------------- Makefile.am | 2 +- 4 files changed, 238 insertions(+), 241 deletions(-) delete mode 100644 CHANGELOG (limited to 'Makefile.am') diff --git a/CHANGELOG b/CHANGELOG deleted file mode 100644 index afab61d..0000000 --- a/CHANGELOG +++ /dev/null @@ -1,184 +0,0 @@ -version 0.9.3 (yet unreleased) ------------------------------- -o fix commit of confirmed expectations (reported by Nishit Shah) -o fix double increment of counters in cache_update_force() (Niko Tyni) -o nl_dump_handler must return NFCT_CB_CONTINUE (Niko Tyni) -o initialize buffer in nl_event_handler() and nl_dump_handler() (Niko Tyni) -o CacheCommit value can be set via conntrackd.conf for the NACK approach -o fix leaks in the hashtable/cache flush path (Niko Tyni) -o fix leak if a connection already exists in the cache (Niko Tyni) -o introduce a new header that encapsulates netlink messages -o remove all '_entry' tail from all functions in cache.c -o split cache.c: move cache iterators to file cache_iterators.c -o fix inconsistencies in the cache API related to counters -o cleanup 'usage' message -o fix typo in examples/sync/nack/node1/conntrackd.conf -o introduce message checksumming as described in RFC1071 (enabled by default) -o major cleanups in the synchronization code -o just warn once that the maximum netlink socket buffer has been reached -o fix ignore conntrack entries by IP and introduce ignore pool abstraction layer -o introduce netlink socket buffer overrun handler -o constification of hash, compare and hashtable_test functions in hash.c -o introduce ACKnowledgement mechanisms to reduce the size of the resend queue -o remove OK messages at startup since provide useless data -o fix compilation warning in mcast.c: recvfrom takes socklen_t not size_t -o add a lock per buffer: makes buffer code thread safe -o introduce 'Replicate' clause to explicitely set states to be replicated -o kill cache feature abuse: introduce nicer cache hooks for sync algorithms -o fix oversized buffer allocated in the stack in the cache functions -o add support to dump internal/external cache in XML format '-x' - -version 0.9.2 (2006/01/17) --------------------------- -o remove spamming packet lost messages -o generalize network netlink sequence tracking -o fix bogus error message on resync `-R' -o fix endianess issues in the network netlink message -o introduce generic netlink multicast primitives to send and receive -o fix bogus replayed multicast message due to sequence numbering wraparound -o introduce counter for malformed netlink messages received -o introduce a new syntax for the `Sync' section in the configuration file -o several cleanups and remove unused variables -o add autostuff to include examples in the tarball (reported by Victor Lozano) -o use the new API available in libnetfilter_conntrack-0.0.50 -o implement a NACK based protocol for replication - -version 0.9.1 (2006/11/06) --------------------------- -o conntrackd requires kernel >= 2.6.18 -o remove bogus TIMERS_MODE constant -o implement bulk mode '-B': first works to address the preemption issue -o fix minor reduction conflicts in the configfile grammar -o check for CAP_NET_ADMIN instead of requiring root privileges -o check that linux/capability.h exists -o fix formatting at dump statistics '-s' -o move dump traffic stats before multicast traffic stats -o move event and dump handler to a generic infrastructure: kill events.c file -o kill unused function inc_ct_stats -o kill file resync.h -o cleanup broadcast_sync: renamed to mcast_send_sync -o sed 's/perror/debug/g' local.c -o fix bogus increment of update_fail stats at dump stage -o display descriptive error if we can't connect to conntrackd via UNIX socket -o remove debugging message from alarm.c -o move dump_mcast_stats to mcast.c where it really belongs -o rename stats.c to traffic_stats.c -o check for replayed/lost multicast message: simple seq tracking w/o recovery -o reissue nfnl_catch on ENOENT error: a message for other subsystem -o remove test/ directory in tree -o improve cache commit stats -o kill last_commit and last_flush from cache statistics: use the logfile -o recover cache naming for dump stats `-s' -o display multicast sequence tracking statistics: packets lost and replayed -o zero ct_sync_state and ct_stats_state structures after allocation -o improve keepalived scripts: - - resync with conntrack table on transition to master - - send bulk on transition to backup -o implement alarm cascade of ten levels -o implement timer cache flavour: limited life of entries in the external cache -o implement a global lock that protects operation with conntrack entries -o remove debug checking in cache_del_entry -o set a reduced timeout for committed entries: 180 seconds by default -o update comments on the sync-mode code -o introduce delay destroy messages facility -o increase timer for external states from 60 to 180 seconds -o remove unused replicate/dont_replicated constants -o fix cache entry clashing issue (reported by Maik Hentsche) -o fix bogus increment of error stats in the external cache -o remove pollution generated by `[REQ] cache dump' message from logfile - -version 0.9.0 (2006/09/17) --------------------------- -o implement initial for IPv6 (untested) -o implement generic extensible cache: kill the internal and external caches -o implement persistence cache feature -o implement lifetime cache feature -o modify UNIX facilities identification numbers: - separate master conntrack facilities and internal plugin facilities -o break backward compatibility of configuration file: - remove IgnoreLoopback, use IgnoreTrafficFor instead - remove IgnoreMulticastTraffic, use IgnoreTrafficFor instead -o merge event/event_subsys and sync/sync_subsys initialization to run.c -o improve control of the iteration process in the hashtables -o fix wrong locking in the alarm thread -o supersede AcceptNAT by StripNAT clause -o replace ignore traffic array by a hashtable -o move lockfile checking before daemonization -o on initialization error give a descriptive error -o introduce netlink socket size grown limitator -o introduce force resync with master conntrack table facility '-R' -o ignore SIGPIPE signal -o kill post_step since it is not used anymore - -version 0.8.3 (2006/09/03) --------------------------- -Author: Maik Hentsche - -o Fix typo in conntrackd -h -o Disable debugging messages by default -o No signals while signals handlings -o Add extra checkings at forking -o Check maximum size for file passed via -C - -Author: Pablo Neira Ayuso - -o retry select() if EINTR is returned (Reported by Maik Hentsche) -o Fix bug in slist_for_each_entry (Reported by Maik Hetsche) -o Signal handler registration done after intialization -o Implement alarm thread (based on Maik Hentsche's patch) -o Fix segfault on conntrackd -k (Reported by Maik Hentsche) -o Fix bug on alarm removal (Reported by Maik Hentsche) -o configure stops if bison, flex or yacc are not installed - -version 0.8.2 (2006/07/05) --------------------------- -o RelaxTransitions clause introduced in Sync mode -o multicast messages sequence tracking -o SocketBufferSize clause to set up the netlink socket buffer -o use new libnfnetlink API to solve limitations of nfnl_listen -o extra sanity checkings for netlink multicast messages -o improve statistics -o tons of cleanups 8) - -version 0.8.1 (2006/06/13) --------------------------- -o -f now just flushes the internal and external caches -o -F flushes the master conntrack table -o fix segfault under heavy load and signal received -o added -S mode for statistics: still needs more thinking - -version 0.8.0 (2006/06/11) --------------------------- -o more work to generalize the daemon: now it's ready to implement -modular support for adaptive timers and conntrack statistics, time -to implement them ;). This is *still* a work in progress. - -version 0.7.2 (2006/06/05) --------------------------- -o stupid bug in normal and alarm caches initialization: flush unset -o fix racy signal handling - -version 0.7.1 (2006/06/05) --------------------------- -o Bugfix for multicast sockets communication - -version 0.7 (2006/06/01) ------------------------- -o Major code re-structuration: internal and external cache abstraction -o sequence tracking for event messages -o expect more changes, I still dislike some stuff in its current status ;) - -version 0.6 (2006/05/31) ------------------------- -o Lock file support -o use new API nfct_conntrack_event_raw -o major code clean ups - -version 0.5 (2006/05/30) -------------------------- -o Fix multicast server binds to wrong interface -o Include clause `IgnoreProtocol', deprecates IgnoreUDP and IgnoreICMP - -version 0.4 (2006/05/29) ------------------------- -o Initial release diff --git a/ChangeLog b/ChangeLog index 1524ef6..2ef0535 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,191 @@ +version 0.9.3 (yet unreleased) +------------------------------ +o fix commit of confirmed expectations (reported by Nishit Shah) +o fix double increment of counters in cache_update_force() (Niko Tyni) +o nl_dump_handler must return NFCT_CB_CONTINUE (Niko Tyni) +o initialize buffer in nl_event_handler() and nl_dump_handler() (Niko Tyni) +o CacheCommit value can be set via conntrackd.conf for the NACK approach +o fix leaks in the hashtable/cache flush path (Niko Tyni) +o fix leak if a connection already exists in the cache (Niko Tyni) +o introduce a new header that encapsulates netlink messages +o remove all '_entry' tail from all functions in cache.c +o split cache.c: move cache iterators to file cache_iterators.c +o fix inconsistencies in the cache API related to counters +o cleanup 'usage' message +o fix typo in examples/sync/nack/node1/conntrackd.conf +o introduce message checksumming as described in RFC1071 (enabled by default) +o major cleanups in the synchronization code +o just warn once that the maximum netlink socket buffer has been reached +o fix ignore conntrack entries by IP and introduce ignore pool abstraction layer +o introduce netlink socket buffer overrun handler +o constification of hash, compare and hashtable_test functions in hash.c +o introduce ACKnowledgement mechanisms to reduce the size of the resend queue +o remove OK messages at startup since provide useless data +o fix compilation warning in mcast.c: recvfrom takes socklen_t not size_t +o add a lock per buffer: makes buffer code thread safe +o introduce 'Replicate' clause to explicitely set states to be replicated +o kill cache feature abuse: introduce nicer cache hooks for sync algorithms +o fix oversized buffer allocated in the stack in the cache functions +o add support to dump internal/external cache in XML format '-x' + +version 0.9.2 (2006/01/17) +-------------------------- +o remove spamming packet lost messages +o generalize network netlink sequence tracking +o fix bogus error message on resync `-R' +o fix endianess issues in the network netlink message +o introduce generic netlink multicast primitives to send and receive +o fix bogus replayed multicast message due to sequence numbering wraparound +o introduce counter for malformed netlink messages received +o introduce a new syntax for the `Sync' section in the configuration file +o several cleanups and remove unused variables +o add autostuff to include examples in the tarball (reported by Victor Lozano) +o use the new API available in libnetfilter_conntrack-0.0.50 +o implement a NACK based protocol for replication + +version 0.9.1 (2006/11/06) +-------------------------- +o conntrackd requires kernel >= 2.6.18 +o remove bogus TIMERS_MODE constant +o implement bulk mode '-B': first works to address the preemption issue +o fix minor reduction conflicts in the configfile grammar +o check for CAP_NET_ADMIN instead of requiring root privileges +o check that linux/capability.h exists +o fix formatting at dump statistics '-s' +o move dump traffic stats before multicast traffic stats +o move event and dump handler to a generic infrastructure: kill events.c file +o kill unused function inc_ct_stats +o kill file resync.h +o cleanup broadcast_sync: renamed to mcast_send_sync +o sed 's/perror/debug/g' local.c +o fix bogus increment of update_fail stats at dump stage +o display descriptive error if we can't connect to conntrackd via UNIX socket +o remove debugging message from alarm.c +o move dump_mcast_stats to mcast.c where it really belongs +o rename stats.c to traffic_stats.c +o check for replayed/lost multicast message: simple seq tracking w/o recovery +o reissue nfnl_catch on ENOENT error: a message for other subsystem +o remove test/ directory in tree +o improve cache commit stats +o kill last_commit and last_flush from cache statistics: use the logfile +o recover cache naming for dump stats `-s' +o display multicast sequence tracking statistics: packets lost and replayed +o zero ct_sync_state and ct_stats_state structures after allocation +o improve keepalived scripts: + - resync with conntrack table on transition to master + - send bulk on transition to backup +o implement alarm cascade of ten levels +o implement timer cache flavour: limited life of entries in the external cache +o implement a global lock that protects operation with conntrack entries +o remove debug checking in cache_del_entry +o set a reduced timeout for committed entries: 180 seconds by default +o update comments on the sync-mode code +o introduce delay destroy messages facility +o increase timer for external states from 60 to 180 seconds +o remove unused replicate/dont_replicated constants +o fix cache entry clashing issue (reported by Maik Hentsche) +o fix bogus increment of error stats in the external cache +o remove pollution generated by `[REQ] cache dump' message from logfile + +version 0.9.0 (2006/09/17) +-------------------------- +o implement initial for IPv6 (untested) +o implement generic extensible cache: kill the internal and external caches +o implement persistence cache feature +o implement lifetime cache feature +o modify UNIX facilities identification numbers: + separate master conntrack facilities and internal plugin facilities +o break backward compatibility of configuration file: + remove IgnoreLoopback, use IgnoreTrafficFor instead + remove IgnoreMulticastTraffic, use IgnoreTrafficFor instead +o merge event/event_subsys and sync/sync_subsys initialization to run.c +o improve control of the iteration process in the hashtables +o fix wrong locking in the alarm thread +o supersede AcceptNAT by StripNAT clause +o replace ignore traffic array by a hashtable +o move lockfile checking before daemonization +o on initialization error give a descriptive error +o introduce netlink socket size grown limitator +o introduce force resync with master conntrack table facility '-R' +o ignore SIGPIPE signal +o kill post_step since it is not used anymore + +version 0.8.3 (2006/09/03) +-------------------------- +Author: Maik Hentsche + +o Fix typo in conntrackd -h +o Disable debugging messages by default +o No signals while signals handlings +o Add extra checkings at forking +o Check maximum size for file passed via -C + +Author: Pablo Neira Ayuso + +o retry select() if EINTR is returned (Reported by Maik Hentsche) +o Fix bug in slist_for_each_entry (Reported by Maik Hetsche) +o Signal handler registration done after intialization +o Implement alarm thread (based on Maik Hentsche's patch) +o Fix segfault on conntrackd -k (Reported by Maik Hentsche) +o Fix bug on alarm removal (Reported by Maik Hentsche) +o configure stops if bison, flex or yacc are not installed + +version 0.8.2 (2006/07/05) +-------------------------- +o RelaxTransitions clause introduced in Sync mode +o multicast messages sequence tracking +o SocketBufferSize clause to set up the netlink socket buffer +o use new libnfnetlink API to solve limitations of nfnl_listen +o extra sanity checkings for netlink multicast messages +o improve statistics +o tons of cleanups 8) + +version 0.8.1 (2006/06/13) +-------------------------- +o -f now just flushes the internal and external caches +o -F flushes the master conntrack table +o fix segfault under heavy load and signal received +o added -S mode for statistics: still needs more thinking + +version 0.8.0 (2006/06/11) +-------------------------- +o more work to generalize the daemon: now it's ready to implement +modular support for adaptive timers and conntrack statistics, time +to implement them ;). This is *still* a work in progress. + +version 0.7.2 (2006/06/05) +-------------------------- +o stupid bug in normal and alarm caches initialization: flush unset +o fix racy signal handling + +version 0.7.1 (2006/06/05) +-------------------------- +o Bugfix for multicast sockets communication + +version 0.7 (2006/06/01) +------------------------ +o Major code re-structuration: internal and external cache abstraction +o sequence tracking for event messages +o expect more changes, I still dislike some stuff in its current status ;) + +version 0.6 (2006/05/31) +------------------------ +o Lock file support +o use new API nfct_conntrack_event_raw +o major code clean ups + +version 0.5 (2006/05/30) +------------------------- +o Fix multicast server binds to wrong interface +o Include clause `IgnoreProtocol', deprecates IgnoreUDP and IgnoreICMP + +version 0.4 (2006/05/29) +------------------------ +o Initial release + +conntrack changelog +=================== + 2006-03-20 o fix ICMP protocol extension parse callback diff --git a/INSTALL b/INSTALL index 0de8dc0..1a80dd0 100644 --- a/INSTALL +++ b/INSTALL @@ -1,26 +1,22 @@ -Copyright (C) 2006-2007 Pablo Neira Ayuso +Copyright (C) 2005-2007 Pablo Neira Ayuso -1.Basic Installation -==================== - - To compile and install 'conntrackd' just follow the classical steps: +0.Introduction +============== - $ ./configure - $ make - # make install - # mkdir /etc/conntrackd/ + The conntrack-tools package contains two programs: -2.1. Synchronization Mode -========================= + - conntrack: the command line interface to interact with the connection + tracking system. - Conntrackd can replicate the status of the connections that are currently - being processed by your stateful firewall based on Linux. This section - describes how to setup the daemon in synchronization mode: + - conntrackd: the connection tracking userspace daemon that can be used to + deploy highly available GNU/Linux firewalls and collect + statistics of the firewall use. -2.1.1. Requirements +1. Requirements +=============== - You have to install the following software in order to get conntrackd working, - make sure that you have installed them correctly before going forward: + You have to install the following software in order to get the conntrack-tools + working, make sure that you have installed them correctly before going forward: o linux kernel version >= 2.6.18 (http://www.kernel.org) with support for: - connection tracking system (quite obvious ;) @@ -28,26 +24,45 @@ Copyright (C) 2006-2007 Pablo Neira Ayuso - ctnetlink (ip_conntrack_netlink) - connection tracking event notification API - o libnfnetlink: the netfilter netlink library + o libnfnetlink: the netfilter netlink library available at: + + + + o libnetfilter_conntrack: the netfilter conntrack library available at: + + + +2.Basic Installation +==================== + + To compile and install conntrack-tools just follow the classical steps: + + $ ./configure + $ make + # make install + + Up to this point, the command line interface `conntrack' is ready for use. + However, the userspace daemon so-called `conntrackd' requires some magic + speells to get it working. - Since conntrackd version 0.9.2 you can used the official release availble at - http://www.netfilter.org/projects/libnfnetlink/files/ +3.Setting up conntrackd +======================= - Up to conntrackd version 0.9.1 use the unofficial release available at the - download section + conntrackd currently have two working modes: statistics and synchronization + modes, both details here below. - o libnetfilter_conntrack: the netfilter conntrack library +3.1. Synchronization Mode +========================= - Since conntrackd version 0.9.2 you can used the official release availble at - http://www.netfilter.org/projects/libnetfilter_conntrack/files/ + Conntrackd can replicate the status of the connections that are currently + being processed by your stateful firewall based on Linux. This section + describes how to setup the daemon in synchronization mode: - Up to conntrackd version 0.9.1 use the unnoficial release available at the - download section o Keepalived version 1.x (http://www.keepalived.org) check if your distribution comes with a recent version -2.1.2. Configuration +3.1.2. Configuration 1) Setting up keepalived @@ -142,7 +157,7 @@ Copyright (C) 2006-2007 Pablo Neira Ayuso # echo 1 > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_be_liberal -2.2. Statistics mode +3.2. Statistics mode ==================== Conntrackd can also run as statistics daemon, if you are not interested in @@ -150,41 +165,19 @@ Copyright (C) 2006-2007 Pablo Neira Ayuso synchronization mode working. This section details how to setup the daemon in statistics mode: -2.2.1. Requirements - - You have to install the following software in order to get conntrackd working, - make sure that you have them installed correctly before going forward: - - o linux kernel version >= 2.6.18 (http://www.kernel.org) with support for: - - connection tracking system - - nfnetlink - - ctnetlink (ip_conntrack_netlink) - - connection tracking event notification API - - o libnfnetlink: the netfilter netlink library - - Since conntrackd version 0.9.2 you can used the official release availble at - http://www.netfilter.org/projects/libnfnetlink/files/ - - Up to conntrackd version 0.9.1 use the unofficial release available at the - download section - - o libnetfilter_conntrack: the netfilter conntrack library - - Since conntrackd version 0.9.2 you can used the official release availble at - http://www.netfilter.org/projects/libnetfilter_conntrack/files/ +3.2.1. Requirements - Up to conntrackd version 0.9.1 use the unnoficial release available at the - download section + No extra requirements to set up the statistics mode apart from those detailed + in section 1. -2.2.2. Configuration +3.2.2. Configuration Setting up conntrackd in statistics mode is rather easy. Just copy the configuration file # cp examples/stats/conntrackd.conf /etc/conntrackd.conf -2.2.3. Running conntrackd in statistics mode +3.2.3. Running conntrackd in statistics mode To run conntrackd in statistics mode: diff --git a/Makefile.am b/Makefile.am index 8a4ce7c..033d52e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,7 +6,7 @@ AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 # man_MANS = "" # EXTRA_DIST = $(man_MANS) Make_global.am debian -EXTRA_DIST = Make_global.am CHANGELOG TODO +EXTRA_DIST = Make_global.am ChangeLog TODO SUBDIRS = src extensions DIST_SUBDIRS = include src extensions examples -- cgit v1.2.3 From 5515f19129d04f692ed6be36c016fd6502192aa0 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Tue, 17 Apr 2007 00:12:45 +0000 Subject: introduce conntrack(8) manpage --- Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 033d52e..07a5ea0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,8 +4,7 @@ include Make_global.am # have all needed files, that a GNU package needs AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 -# man_MANS = "" -# EXTRA_DIST = $(man_MANS) Make_global.am debian +man_MANS = conntrack.8 EXTRA_DIST = Make_global.am ChangeLog TODO SUBDIRS = src extensions -- cgit v1.2.3 From 9212740cfbefc500c93f55b2b5289b1740e9c9e0 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Tue, 17 Apr 2007 00:28:16 +0000 Subject: - bump version to 0.9.3 - show 'conntrack-tools' string when 'conntrack -V' is issued - include missing headers to include/Makefile.am --- Makefile.am | 2 +- configure.in | 2 +- include/Makefile.am | 3 ++- src/conntrack.c | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 07a5ea0..d60c935 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,7 +5,7 @@ include Make_global.am AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 man_MANS = conntrack.8 -EXTRA_DIST = Make_global.am ChangeLog TODO +EXTRA_DIST = $(man_MANS) Make_global.am ChangeLog TODO SUBDIRS = src extensions DIST_SUBDIRS = include src extensions examples diff --git a/configure.in b/configure.in index 5bd9815..e58bfc4 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -AC_INIT(conntrackd, 0.9.2, pablo@netfilter.org) +AC_INIT(conntrackd, 0.9.3, pablo@netfilter.org) AC_CANONICAL_SYSTEM diff --git a/include/Makefile.am b/include/Makefile.am index e669d73..a7716d9 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,5 +1,6 @@ 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 + debug.h log.h hash.h mcast.h buffer.h conntrack.h \ + state_helper.h network.h ignore.h diff --git a/src/conntrack.c b/src/conntrack.c index 30fbf69..b550c39 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -1104,7 +1104,7 @@ int main(int argc, char *argv[]) break; case CT_VERSION: - fprintf(stdout, "%s v%s\n", PROGNAME, VERSION); + printf("%s v%s (conntrack-tools)\n", PROGNAME, VERSION); break; case CT_HELP: usage(argv[0]); -- cgit v1.2.3 From 4c0d6e523ec8cdb7feb0480cd27da37f4b03394a Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Tue, 17 Apr 2007 01:03:51 +0000 Subject: - remove overkill recursive Makefile.am definition in examples/ (use EXTRA_DIST) --- Makefile.am | 4 ++-- configure.in | 4 ++-- examples/Makefile.am | 1 - examples/stats/Makefile.am | 1 - examples/sync/Makefile.am | 1 - examples/sync/nack/Makefile.am | 2 -- examples/sync/nack/node1/Makefile.am | 1 - examples/sync/nack/node2/Makefile.am | 1 - examples/sync/persistent/Makefile.am | 2 -- examples/sync/persistent/node1/Makefile.am | 1 - examples/sync/persistent/node2/Makefile.am | 1 - 11 files changed, 4 insertions(+), 15 deletions(-) delete mode 100644 examples/Makefile.am delete mode 100644 examples/stats/Makefile.am delete mode 100644 examples/sync/Makefile.am delete mode 100644 examples/sync/nack/Makefile.am delete mode 100644 examples/sync/nack/node1/Makefile.am delete mode 100644 examples/sync/nack/node2/Makefile.am delete mode 100644 examples/sync/persistent/Makefile.am delete mode 100644 examples/sync/persistent/node1/Makefile.am delete mode 100644 examples/sync/persistent/node2/Makefile.am (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index d60c935..6f0e6fb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,10 +5,10 @@ include Make_global.am AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 man_MANS = conntrack.8 -EXTRA_DIST = $(man_MANS) Make_global.am ChangeLog TODO +EXTRA_DIST = $(man_MANS) Make_global.am ChangeLog TODO examples SUBDIRS = src extensions -DIST_SUBDIRS = include src extensions examples +DIST_SUBDIRS = include src extensions LINKOPTS = -lnfnetlink -lnetfilter_conntrack -lpthread AM_CFLAGS = -g diff --git a/configure.in b/configure.in index e58bfc4..2982f74 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -AC_INIT(conntrackd, 0.9.3, pablo@netfilter.org) +AC_INIT(conntrack-tools, 0.9.3, pablo@netfilter.org) AC_CANONICAL_SYSTEM @@ -103,4 +103,4 @@ dnl debug/src/Makefile dnl extensions/Makefile dnl src/Makefile]) -AC_OUTPUT(Makefile src/Makefile include/Makefile extensions/Makefile examples/Makefile examples/stats/Makefile examples/sync/Makefile examples/sync/persistent/Makefile examples/sync/nack/Makefile examples/sync/persistent/node1/Makefile examples/sync/persistent/node2/Makefile examples/sync/nack/node1/Makefile examples/sync/nack/node2/Makefile) +AC_OUTPUT(Makefile src/Makefile include/Makefile extensions/Makefile) diff --git a/examples/Makefile.am b/examples/Makefile.am deleted file mode 100644 index be83d42..0000000 --- a/examples/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS = stats sync diff --git a/examples/stats/Makefile.am b/examples/stats/Makefile.am deleted file mode 100644 index b43c3b8..0000000 --- a/examples/stats/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -EXTRA_DIST = conntrackd.conf diff --git a/examples/sync/Makefile.am b/examples/sync/Makefile.am deleted file mode 100644 index 28e7643..0000000 --- a/examples/sync/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS = persistent nack diff --git a/examples/sync/nack/Makefile.am b/examples/sync/nack/Makefile.am deleted file mode 100644 index 6fd99b1..0000000 --- a/examples/sync/nack/Makefile.am +++ /dev/null @@ -1,2 +0,0 @@ -EXTRA_DIST = script_backup.sh script_master.sh -SUBDIRS = node1 node2 diff --git a/examples/sync/nack/node1/Makefile.am b/examples/sync/nack/node1/Makefile.am deleted file mode 100644 index edc0ed7..0000000 --- a/examples/sync/nack/node1/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -EXTRA_DIST = conntrackd.conf keepalived.conf diff --git a/examples/sync/nack/node2/Makefile.am b/examples/sync/nack/node2/Makefile.am deleted file mode 100644 index edc0ed7..0000000 --- a/examples/sync/nack/node2/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -EXTRA_DIST = conntrackd.conf keepalived.conf diff --git a/examples/sync/persistent/Makefile.am b/examples/sync/persistent/Makefile.am deleted file mode 100644 index 6fd99b1..0000000 --- a/examples/sync/persistent/Makefile.am +++ /dev/null @@ -1,2 +0,0 @@ -EXTRA_DIST = script_backup.sh script_master.sh -SUBDIRS = node1 node2 diff --git a/examples/sync/persistent/node1/Makefile.am b/examples/sync/persistent/node1/Makefile.am deleted file mode 100644 index edc0ed7..0000000 --- a/examples/sync/persistent/node1/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -EXTRA_DIST = conntrackd.conf keepalived.conf diff --git a/examples/sync/persistent/node2/Makefile.am b/examples/sync/persistent/node2/Makefile.am deleted file mode 100644 index edc0ed7..0000000 --- a/examples/sync/persistent/node2/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -EXTRA_DIST = conntrackd.conf keepalived.conf -- cgit v1.2.3 From 7e28837a6073600129d2fc06c23c40726ef5976a Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Sat, 9 Jun 2007 19:24:07 +0000 Subject: remove dlopen infrastructure: simplification, it was too much for it --- ChangeLog | 1 + Makefile.am | 2 +- configure.in | 9 --------- extensions/Makefile.am | 16 +++++----------- extensions/libct_proto_icmp.c | 4 +--- extensions/libct_proto_tcp.c | 4 +--- extensions/libct_proto_udp.c | 4 +--- include/conntrack.h | 4 ++++ src/Makefile.am | 2 +- src/conntrack.c | 20 ++++---------------- 10 files changed, 19 insertions(+), 47 deletions(-) (limited to 'Makefile.am') diff --git a/ChangeLog b/ChangeLog index c045f1f..86a9a46 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,6 +22,7 @@ o remove bogus option to get a conntrack in test.sh example file o add aliases --sport and --dport to make it more iptables-like o add support for `-L --src-nat' and `-L --dst-nat' to show natted connections o update conntrack(8) manpage +o remove dlopen infrastructure version 0.9.3 (2006/05/22) ------------------------------ diff --git a/Makefile.am b/Makefile.am index 6f0e6fb..05c311f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -7,7 +7,7 @@ AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 man_MANS = conntrack.8 EXTRA_DIST = $(man_MANS) Make_global.am ChangeLog TODO examples -SUBDIRS = src extensions +SUBDIRS = extensions src DIST_SUBDIRS = include src extensions LINKOPTS = -lnfnetlink -lnetfilter_conntrack -lpthread AM_CFLAGS = -g diff --git a/configure.in b/configure.in index 06c787f..41a001c 100644 --- a/configure.in +++ b/configure.in @@ -98,15 +98,6 @@ dnl AC_FUNC_MALLOC dnl AC_FUNC_VPRINTF dnl AC_CHECK_FUNCS([memset]) -dnl-------------------------------- - -if test ! -z "$libdir"; then - MODULE_DIR="\\\"$libdir/conntrack-tools/\\\"" - CFLAGS="$CFLAGS -DCONNTRACK_LIB_DIR=$MODULE_DIR" -fi - -dnl-------------------------------- - dnl AC_CONFIG_FILES([Makefile dnl debug/Makefile dnl debug/src/Makefile diff --git a/extensions/Makefile.am b/extensions/Makefile.am index db97c4d..cf45688 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -1,14 +1,8 @@ include $(top_srcdir)/Make_global.am -AM_CFLAGS=-fPIC -Wall -LIBS= +noinst_LTLIBRARIES = libct_proto_tcp.la libct_proto_udp.la \ + libct_proto_icmp.la -pkglib_LTLIBRARIES = ct_proto_tcp.la ct_proto_udp.la \ - ct_proto_icmp.la - -ct_proto_tcp_la_SOURCES = libct_proto_tcp.c -ct_proto_tcp_la_LDFLAGS = -module -avoid-version -ct_proto_udp_la_SOURCES = libct_proto_udp.c -ct_proto_udp_la_LDFLAGS = -module -avoid-version -ct_proto_icmp_la_SOURCES = libct_proto_icmp.c -ct_proto_icmp_la_LDFLAGS = -module -avoid-version +libct_proto_tcp_la_SOURCES = libct_proto_tcp.c +libct_proto_udp_la_SOURCES = libct_proto_udp.c +libct_proto_icmp_la_SOURCES = libct_proto_icmp.c diff --git a/extensions/libct_proto_icmp.c b/extensions/libct_proto_icmp.c index 5c7717a..765ced4 100644 --- a/extensions/libct_proto_icmp.c +++ b/extensions/libct_proto_icmp.c @@ -91,9 +91,7 @@ static struct ctproto_handler icmp = { .version = VERSION, }; -static void __attribute__ ((constructor)) init(void); - -static void init(void) +void register_icmp(void) { register_proto(&icmp); } diff --git a/extensions/libct_proto_tcp.c b/extensions/libct_proto_tcp.c index 1f0cde6..5a40cef 100644 --- a/extensions/libct_proto_tcp.c +++ b/extensions/libct_proto_tcp.c @@ -215,9 +215,7 @@ static struct ctproto_handler tcp = { .version = VERSION, }; -static void __attribute__ ((constructor)) init(void); - -static void init(void) +void register_tcp(void) { register_proto(&tcp); } diff --git a/extensions/libct_proto_udp.c b/extensions/libct_proto_udp.c index ff9c3d2..cb131d6 100644 --- a/extensions/libct_proto_udp.c +++ b/extensions/libct_proto_udp.c @@ -176,9 +176,7 @@ static struct ctproto_handler udp = { .version = VERSION, }; -static void __attribute__ ((constructor)) init(void); - -static void init(void) +void register_udp(void) { register_proto(&udp); } diff --git a/include/conntrack.h b/include/conntrack.h index 31f4f4f..f344d72 100644 --- a/include/conntrack.h +++ b/include/conntrack.h @@ -170,4 +170,8 @@ struct ctproto_handler { extern void register_proto(struct ctproto_handler *h); +extern void register_tcp(void); +extern void register_udp(void); +extern void register_icmp(void); + #endif diff --git a/src/Makefile.am b/src/Makefile.am index a67e09a..8647d04 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,7 +7,7 @@ CLEANFILES = read_config_yy.c read_config_lex.c sbin_PROGRAMS = conntrack conntrackd conntrack_SOURCES = conntrack.c -conntrack_LDFLAGS = -rdynamic +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 \ diff --git a/src/conntrack.c b/src/conntrack.c index a14ee4b..eece45b 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -136,8 +136,6 @@ static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = /*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, }; -static char *lib_dir = CONNTRACK_LIB_DIR; - static LIST_HEAD(proto_list); static unsigned int options; @@ -163,10 +161,6 @@ static struct ctproto_handler *findproto(char *name) if (!name) return handler; - lib_dir = getenv("CONNTRACK_LIB_DIR"); - if (!lib_dir) - lib_dir = CONNTRACK_LIB_DIR; - list_for_each(i, &proto_list) { cur = (struct ctproto_handler *) i; if (strcmp(cur->name, name) == 0) { @@ -175,16 +169,6 @@ static struct ctproto_handler *findproto(char *name) } } - if (!handler) { - char path[sizeof("ct_proto_.so") - + strlen(name) + strlen(lib_dir)]; - sprintf(path, "%s/ct_proto_%s.so", lib_dir, name); - if (dlopen(path, RTLD_NOW)) - handler = findproto(name); - else - fprintf(stderr, "%s\n", dlerror()); - } - return handler; } @@ -700,6 +684,10 @@ int main(int argc, char *argv[]) memset(__mask, 0, sizeof(__mask)); memset(__exp, 0, sizeof(__exp)); + register_tcp(); + register_udp(); + register_icmp(); + while ((c = getopt_long(argc, argv, "L::I::U::D::G::E::F::hVs:d:r:q:p:t:u:e:a:z[:]:{:}:m:i::f:o:", opts, NULL)) != -1) { -- cgit v1.2.3 From 4df0be6fbf6a47905e0edf11c13b49ea0eacee5b Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Mon, 2 Jul 2007 14:13:41 +0000 Subject: do not include .svn directories in tarballs --- Makefile.am | 1 + 1 file changed, 1 insertion(+) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 05c311f..17282b2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,3 +18,4 @@ libtool: $(LIBTOOL_DEPS) dist-hook: rm -rf `find $(distdir)/debian -name .svn` + rm -rf `find $(distdir)/examples -name .svn` -- cgit v1.2.3 From 8c634be62780c8467e6a61419d40cdc8b7a0c865 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Mon, 6 Aug 2007 09:43:06 +0000 Subject: conntrack-tools compilation problem (K.Kovacs) --- ChangeLog | 5 +++++ Makefile.am | 2 +- configure.in | 4 ++++ src/Makefile.am | 3 ++- 4 files changed, 12 insertions(+), 2 deletions(-) (limited to 'Makefile.am') diff --git a/ChangeLog b/ChangeLog index bb376bd..588cab0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +version 0.9.6 (yet unreleased) +------------------------------ + +o fix compilation problem due to missing headers (Krisztian Kovacs) + version 0.9.5 (2007/07/29) ------------------------------ diff --git a/Makefile.am b/Makefile.am index 17282b2..239eedf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,7 +9,7 @@ EXTRA_DIST = $(man_MANS) Make_global.am ChangeLog TODO examples SUBDIRS = extensions src DIST_SUBDIRS = include src extensions -LINKOPTS = -lnfnetlink -lnetfilter_conntrack -lpthread +LIBS = @LIBNETFILTER_CONNTRACK_LIBS@ AM_CFLAGS = -g $(OBJECTS): libtool diff --git a/configure.in b/configure.in index 7e1cd20..6582b1b 100644 --- a/configure.in +++ b/configure.in @@ -104,4 +104,8 @@ dnl debug/src/Makefile dnl extensions/Makefile dnl src/Makefile]) +CFLAGS="$CFLAGS $LIBNETFILTER_CONNTRACK_CFLAGS" + +AC_SUBST(LIBNETFILTER_CONNTRACK_LIBS) + AC_OUTPUT(Makefile src/Makefile include/Makefile extensions/Makefile) diff --git a/src/Makefile.am b/src/Makefile.am index d71e23c..83511fa 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,6 +8,7 @@ sbin_PROGRAMS = conntrack conntrackd 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 buffer.c \ local.c log.c mcast.c netlink.c \ @@ -22,6 +23,6 @@ conntrackd_SOURCES = alarm.c main.c run.c hash.c buffer.c \ build.c parse.c \ read_config_yy.y read_config_lex.l -conntrackd_LDFLAGS = $(all_libraries) -lnfnetlink -lnetfilter_conntrack +conntrackd_LDFLAGS = $(all_libraries) @LIBNETFILTER_CONNTRACK_LIBS@ EXTRA_DIST = read_config_yy.h -- cgit v1.2.3 From a2eb348ebb6bb3172aa46dd132befe2a24c2d302 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Fri, 21 Dec 2007 13:20:04 +0000 Subject: = conntrack = o fix missing `-g' and `-n' options in getopt_long control string o add support for secmark (requires Linux kernel >= 2.6.25) o add mark and secmark information to the manpage o cleanup error message = conntrackd = o add support for secmark (requires Linux kernel >= 2.6.25) o add conntrackd (8) manpage --- ChangeLog | 8 ++++++ Makefile.am | 2 +- TODO | 42 ++++++++++++++------------- configure.in | 2 +- conntrack.8 | 5 ++++ conntrackd.8 | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++ include/conntrack.h | 5 +++- src/build.c | 2 ++ src/conntrack.c | 55 +++++++++++++++++++++--------------- src/parse.c | 1 + 10 files changed, 158 insertions(+), 45 deletions(-) create mode 100644 conntrackd.8 (limited to 'Makefile.am') diff --git a/ChangeLog b/ChangeLog index 46242c5..9d8e753 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,10 +4,18 @@ version 0.9.6 (yet unreleased) o fix compilation problem due to missing headers (Krisztian Kovacs) o include kernel options and Fedora comments in the INSTALL file += conntrack = +o fix missing `-g' and `-n' options in getopt_long control string +o add support for secmark (requires Linux kernel >= 2.6.25) +o add mark and secmark information to the manpage +o cleanup error message + = conntrackd = 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 +o add support for secmark (requires Linux kernel >= 2.6.25) +o add conntrackd (8) manpage version 0.9.5 (2007/07/29) ------------------------------ diff --git a/Makefile.am b/Makefile.am index 239eedf..3abf2cc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,7 +4,7 @@ include Make_global.am # have all needed files, that a GNU package needs AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 -man_MANS = conntrack.8 +man_MANS = conntrack.8 conntrackd.8 EXTRA_DIST = $(man_MANS) Make_global.am ChangeLog TODO examples SUBDIRS = extensions src diff --git a/TODO b/TODO index 482b677..7f5b949 100644 --- a/TODO +++ b/TODO @@ -2,28 +2,32 @@ There are several tasks that are pending to be done, I have classified them by dificulty levels: = Relatively easy = - * add syslog support (based on Simon Lodal's patch) - * improve shell scripts for keepalived/heartbeat: *really* important - * use NACK based protocol, feedback: call pablo :-) - * manpage for conntrackd(8) - * use the floating priority feature in keepalived to avoid premature - take over. + [ ] improve shell scripts for keepalived/heartbeat: *really* important + [ ] NACK as default protocol + [ ] rename persistent to alarm + [X] manpage for conntrackd(8) + [ ] add scripts to use the floating priority feature in keepalived to avoid + premature take over. + [ ] ignorepool with unlimited size and ignore networks + [ ] selective conntracks removal + [ ] debian/rpm packages + [ ] improve website + [ ] Dumazet improvement hashtable (multiply vs. divide) + [X] add secmark support = Requires some work = - * study better keepalived transitions - * test/fix ipv6 support - * have a look at open issues - * implement support for TCP window tracking (patches are on the table) at - the moment you have to disable it: + [ ] study better keepalived transitions + [ ] test/fix ipv6 support + [ ] add support setup related conntracks + [ ] NAT sequence adjustment support - echo 1 > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_be_liberal - -= Requires kernel patches = - * setup master conntrack to match IPCT_RELATED - -= Open issues = - * unsupported iptables matches: += Open issues that won't be ever resolved = + * unsupported stateful iptables matches: * connbytes: probably the persistent may support it * recent: requires further study * quota: private data counters - * connection tracking NAT helpers: sequence adjustment issues (?) + += conntrack = + * add support for -D --dport 1000 + * improve error messages + * add support for SCTP (requires kernel >= 2.6.25) diff --git a/configure.in b/configure.in index 9400e37..bcd43f2 100644 --- a/configure.in +++ b/configure.in @@ -18,7 +18,7 @@ esac dnl Dependencies LIBNFNETLINK_REQUIRED=0.0.25 -LIBNETFILTER_CONNTRACK_REQUIRED=0.0.82 +LIBNETFILTER_CONNTRACK_REQUIRED=0.0.87 PKG_CHECK_MODULES(LIBNFNETLINK, libnfnetlink >= $LIBNFNETLINK_REQUIRED,, AC_MSG_ERROR(Cannot find libnfnetlink >= $LIBNFNETLINK_REQUIRED)) diff --git a/conntrack.8 b/conntrack.8 index d095d6c..0924888 100644 --- a/conntrack.8 +++ b/conntrack.8 @@ -106,6 +106,11 @@ This option is only required in conjunction with "-L, --dump". If this option is .TP .BI "-t, --timeout " "TIMEOUT" Specify the timeout. +.BI "-m, --mark " "MARK" +Specify the conntrack mark. +.TP +.BI "-c, --secmark " "SECMARK" +Specify the conntrack selinux security mark. .TP .BI "-u, --status " "[ASSURED|SEEN_REPLY|UNSET][,...]" Specify the conntrack status. diff --git a/conntrackd.8 b/conntrackd.8 new file mode 100644 index 0000000..8e2f2cc --- /dev/null +++ b/conntrackd.8 @@ -0,0 +1,81 @@ +.TH CONNTRACKD 8 "Dec 21, 2007" "" "" + +.\" Man page written by Pablo Neira Ayuso (Dec 2007) + +.SH NAME +conntrackd \- netfilter connection tracking userspace daemon +.SH SYNOPSIS +.BR "conntrackd [options]" +.SH DESCRIPTION +.B conntrackd +provides a userspace daemon for the netfilter connection tracking system. This daemon synchronizes connection tracking states among several replica firewalls. Thus, +.B conntrackd +can be used to implement highly available stateful firewalls. The daemon fully supports Primary-Backup and Multiprimary setups for both symmetric and asymmetric paths. It can also be used as statistics collector. +.SH OPTIONS +The options recognized by +.B conntrackd +can be divided into several different groups. +.SS MODES +These options specify the particular operation mode in which conntrackd runs. Only one of them can be specified at any given time. +.TP +.BI "-d " +Run conntrackd in daemon mode. This option can be combined with "-S" +.TP +.BI "-S " +Run conntrackd in statistics mode. Default mode is synchronization mode, so if you want to use +.B conntrackd +in statistics mode, you have to pass this option +.SS CLIENT COMMANDS +.B conntrackd +can be used in client mode to request several information and operations to a running daemon +.TP +.BI "-i " +Dump the internal cache, i.e. show local states +.TP +.BI "-e " +Dump the external cache, i.e. show foreign states +.TP +.BI "-x " +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 +.TP +.BI "-k " +Kill the daemon +.TP +.BI "-s " +Dump statistics +.TP +.BI "-R " +Force a resync against the kernel connection tracking table +.SH DIAGNOSTICS +The exit code is 0 for correct function. Errors cause an exit code of 1. +.SH EXAMPLES +.TP +.B conntrackd \-d +Runs conntrackd in daemon and synchronization mode +.TP +.B conntrackd \-i +Dumps the states held in the internal cache, i.e. those handled by this firewall +.TP +.B conntrackd \-e +Dumps the states held in the external cache, i.e. those handled by other replica firewalls +.TP +.B conntrackd \-c +Commits the internal cache into the kernel connection tracking system. This is used to inject the state so that the connections can be recovered during the failover. +.SH DEPENDENCIES +This daemon requires a Linux kernel version >= 2.6.18. TCP window tracking support requires >= 2.6.22, otherwise you have to disable it. Helpers are fully supported since >= 2.6.25, however, if you use any previous version, depending on the protocol helper and your setup (e.g. if you setup performs NAT sequence adjustments or not), your help connection may be successfully recovered. +.TP +There are several unsupported stateful iptables matches such as recent, connbytes and the quota matches which gather internal information to operate. Since that information does not belong to the domain of the connection tracking system, connections affected by those matches may not be fully recovered during the takeover. +.SH SEE ALSO +.BR conntrack (8), iptables (8) +.br +.BR "http://people.netfilter.org/pablo/conntrack-tools/" +.SH AUTHORS +Pablo Neira Ayuso wrote and maintains the conntrackd tool +.TP +Please send bug reports to . Subscription is required. +.PP +Man page written by Pablo Neira Ayuso . diff --git a/include/conntrack.h b/include/conntrack.h index 5edc0e9..1b2581e 100644 --- a/include/conntrack.h +++ b/include/conntrack.h @@ -127,7 +127,10 @@ enum options { CT_OPT_OUTPUT_BIT = 19, CT_OPT_OUTPUT = (1 << CT_OPT_OUTPUT_BIT), - CT_OPT_MAX = CT_OPT_OUTPUT_BIT + CT_OPT_SECMARK_BIT = 20, + CT_OPT_SECMARK = (1 << CT_OPT_SECMARK_BIT), + + CT_OPT_MAX = CT_OPT_SECMARK_BIT }; #define NUMBER_OF_OPT CT_OPT_MAX+1 diff --git a/src/build.c b/src/build.c index 981548e..109b26e 100644 --- a/src/build.c +++ b/src/build.c @@ -97,6 +97,8 @@ void build_netpld(struct nf_conntrack *ct, struct netpld *pld, int query) __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_SECMARK)) + __build_u32(ct, pld, ATTR_SECMARK); if (nfct_attr_is_set(ct, ATTR_STATUS)) __build_u32(ct, pld, ATTR_STATUS); diff --git a/src/conntrack.c b/src/conntrack.c index 165809b..65dc4a7 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -67,7 +67,7 @@ static const char cmd_need_param[NUMBER_OF_CMD] static const char *optflags[NUMBER_OF_OPT] = { "src","dst","reply-src","reply-dst","protonum","timeout","status","zero", "event-mask","tuple-src","tuple-dst","mask-src","mask-dst","nat-range","mark", -"id","family","src-nat","dst-nat","output" }; +"id","family","src-nat","dst-nat","output","secmark"}; static struct option original_opts[] = { {"dump", 2, 0, 'L'}, @@ -96,6 +96,7 @@ static struct option original_opts[] = { {"mask-dst", 1, 0, '}'}, {"nat-range", 1, 0, 'a'}, /* deprecated */ {"mark", 1, 0, 'm'}, + {"secmark", 1, 0, 'c'}, {"id", 2, 0, 'i'}, /* deprecated */ {"family", 1, 0, 'f'}, {"src-nat", 2, 0, 'n'}, @@ -122,22 +123,22 @@ static unsigned int global_option_offset = 0; static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = /* Well, it's better than "Re: Linux vs FreeBSD" */ { - /* s d r q p t u z e [ ] { } a m i f n g o */ -/*CT_LIST*/ {2,2,2,2,2,0,0,2,0,0,0,0,0,0,2,2,2,2,2,2}, -/*CT_CREATE*/ {2,2,2,2,1,1,1,0,0,0,0,0,0,2,2,0,0,2,2,0}, -/*CT_UPDATE*/ {2,2,2,2,1,2,2,0,0,0,0,0,0,0,2,2,0,0,0,0}, -/*CT_DELETE*/ {2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0}, -/*CT_GET*/ {2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2}, -/*CT_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*CT_EVENT*/ {2,2,2,2,2,0,0,0,2,0,0,0,0,0,2,0,0,2,2,2}, -/*VERSION*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*HELP*/ {0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_LIST*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0}, -/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0,0,0,0}, -/*EXP_DELETE*/{1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_GET*/ {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + /* s d r q p t u z e [ ] { } a m i f n g o c */ +/*CT_LIST*/ {2,2,2,2,2,0,0,2,0,0,0,0,0,0,2,2,2,2,2,2,2}, +/*CT_CREATE*/ {2,2,2,2,1,1,1,0,0,0,0,0,0,2,2,0,0,2,2,0,2}, +/*CT_UPDATE*/ {2,2,2,2,1,2,2,0,0,0,0,0,0,0,2,2,0,0,0,0,2}, +/*CT_DELETE*/ {2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0}, +/*CT_GET*/ {2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2,0}, +/*CT_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*CT_EVENT*/ {2,2,2,2,2,0,0,0,2,0,0,0,0,0,2,0,0,2,2,2,2}, +/*VERSION*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*HELP*/ {0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_LIST*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0}, +/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0,0,0,0,0}, +/*EXP_DELETE*/{1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_GET*/ {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, }; static LIST_HEAD(proto_list); @@ -145,7 +146,8 @@ static LIST_HEAD(proto_list); static unsigned int options; static unsigned int command; -#define CT_COMPARISON (CT_OPT_PROTO | CT_OPT_ORIG | CT_OPT_REPL | CT_OPT_MARK) +#define CT_COMPARISON (CT_OPT_PROTO | CT_OPT_ORIG | CT_OPT_REPL | CT_OPT_MARK |\ + CT_OPT_SECMARK) void register_proto(struct ctproto_handler *h) { @@ -206,7 +208,6 @@ void exit_error(enum exittype status, char *msg, ...) fprintf(stderr,"%s v%s: ", PROGNAME, VERSION); vfprintf(stderr, msg, args); va_end(args); - fprintf(stderr, "\n"); if (status == PARAMETER_PROBLEM) exit_tryhelp(status); exit(status); @@ -522,6 +523,7 @@ static const char usage_conntrack_parameters[] = " -n, --src-nat ip\t\t\tsource NAT ip\n" " -g, --dst-nat ip\t\t\tdestination NAT ip\n" " -m, --mark mark\t\t\tSet mark\n" + " -c, --secmark secmark\t\t\tSet selinux secmark\n" " -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"; @@ -556,7 +558,7 @@ void usage(char *prog) { fprintf(stdout, "\n%s", usage_tables); fprintf(stdout, "\n%s", usage_conntrack_parameters); fprintf(stdout, "\n%s", usage_expectation_parameters); - fprintf(stdout, "\n%s", usage_parameters); + fprintf(stdout, "\n%s\n", usage_parameters); } static unsigned int output_mask; @@ -677,9 +679,10 @@ int main(int argc, char *argv[]) register_udp(); register_icmp(); - while ((c = getopt_long(argc, argv, - "L::I::U::D::G::E::F::hVs:d:r:q:p:t:u:e:a:z[:]:{:}:m:i::f:o:", - opts, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "L::I::U::D::G::E::F::hVs:d:r:q:" + "p:t:u:e:a:z[:]:{:}:m:i::f:o:n::" + "g::c:", + opts, NULL)) != -1) { switch(c) { case 'L': type = check_type(argc, argv); @@ -948,6 +951,12 @@ int main(int argc, char *argv[]) continue; nfct_set_attr_u32(obj, ATTR_MARK, atol(optarg)); break; + case 'c': + options |= CT_OPT_SECMARK; + if (!optarg) + continue; + nfct_set_attr_u32(obj, ATTR_SECMARK, atol(optarg)); + break; case 'i': printf("warning: ignoring --id. deprecated option.\n"); break; diff --git a/src/parse.c b/src/parse.c index 81b70c4..8816e7a 100644 --- a/src/parse.c +++ b/src/parse.c @@ -55,6 +55,7 @@ parse h[ATTR_MAX] = { [ATTR_TIMEOUT] = parse_u32, [ATTR_MARK] = parse_u32, [ATTR_STATUS] = parse_u32, + [ATTR_SECMARK] = parse_u32, }; void parse_netpld(struct nf_conntrack *ct, struct netpld *pld, int *query) -- cgit v1.2.3 From 735a6fc681809beb52c160b09507aa0999fbc6ba Mon Sep 17 00:00:00 2001 From: "Ayuso/emailAddress=pablo@netfilter.org" Date: Fri, 21 Dec 2007 18:15:04 +0000 Subject: rename `examples' directory to `doc' --- ChangeLog | 1 + Makefile.am | 2 +- doc/cli/test.sh | 106 ++++++++++++++++++++++ doc/debian.conntrackd.init.d | 48 ++++++++++ doc/stats/conntrackd.conf | 76 ++++++++++++++++ doc/sync/alarm/README | 1 + doc/sync/alarm/node1/conntrackd.conf | 140 ++++++++++++++++++++++++++++++ doc/sync/alarm/node1/keepalived.conf | 39 +++++++++ doc/sync/alarm/node2/conntrackd.conf | 140 ++++++++++++++++++++++++++++++ doc/sync/alarm/node2/keepalived.conf | 39 +++++++++ doc/sync/alarm/script_backup.sh | 3 + doc/sync/alarm/script_master.sh | 4 + doc/sync/ftfw/README | 1 + doc/sync/ftfw/node1/conntrackd.conf | 135 ++++++++++++++++++++++++++++ doc/sync/ftfw/node1/keepalived.conf | 39 +++++++++ doc/sync/ftfw/node2/conntrackd.conf | 134 ++++++++++++++++++++++++++++ doc/sync/ftfw/node2/keepalived.conf | 39 +++++++++ doc/sync/ftfw/script_backup.sh | 3 + doc/sync/ftfw/script_master.sh | 5 ++ examples/cli/test.sh | 106 ---------------------- examples/debian.conntrackd.init.d | 48 ---------- examples/stats/conntrackd.conf | 76 ---------------- examples/sync/alarm/README | 1 - examples/sync/alarm/node1/conntrackd.conf | 140 ------------------------------ examples/sync/alarm/node1/keepalived.conf | 39 --------- examples/sync/alarm/node2/conntrackd.conf | 140 ------------------------------ examples/sync/alarm/node2/keepalived.conf | 39 --------- examples/sync/alarm/script_backup.sh | 3 - examples/sync/alarm/script_master.sh | 4 - examples/sync/ftfw/README | 1 - examples/sync/ftfw/node1/conntrackd.conf | 135 ---------------------------- examples/sync/ftfw/node1/keepalived.conf | 39 --------- examples/sync/ftfw/node2/conntrackd.conf | 134 ---------------------------- examples/sync/ftfw/node2/keepalived.conf | 39 --------- examples/sync/ftfw/script_backup.sh | 3 - examples/sync/ftfw/script_master.sh | 5 -- 36 files changed, 954 insertions(+), 953 deletions(-) create mode 100644 doc/cli/test.sh create mode 100644 doc/debian.conntrackd.init.d create mode 100644 doc/stats/conntrackd.conf create mode 100644 doc/sync/alarm/README create mode 100644 doc/sync/alarm/node1/conntrackd.conf create mode 100644 doc/sync/alarm/node1/keepalived.conf create mode 100644 doc/sync/alarm/node2/conntrackd.conf create mode 100644 doc/sync/alarm/node2/keepalived.conf create mode 100644 doc/sync/alarm/script_backup.sh create mode 100644 doc/sync/alarm/script_master.sh create mode 100644 doc/sync/ftfw/README create mode 100644 doc/sync/ftfw/node1/conntrackd.conf create mode 100644 doc/sync/ftfw/node1/keepalived.conf create mode 100644 doc/sync/ftfw/node2/conntrackd.conf create mode 100644 doc/sync/ftfw/node2/keepalived.conf create mode 100644 doc/sync/ftfw/script_backup.sh create mode 100644 doc/sync/ftfw/script_master.sh delete mode 100644 examples/cli/test.sh delete mode 100644 examples/debian.conntrackd.init.d delete mode 100644 examples/stats/conntrackd.conf delete mode 100644 examples/sync/alarm/README delete mode 100644 examples/sync/alarm/node1/conntrackd.conf delete mode 100644 examples/sync/alarm/node1/keepalived.conf delete mode 100644 examples/sync/alarm/node2/conntrackd.conf delete mode 100644 examples/sync/alarm/node2/keepalived.conf delete mode 100755 examples/sync/alarm/script_backup.sh delete mode 100755 examples/sync/alarm/script_master.sh delete mode 100644 examples/sync/ftfw/README delete mode 100644 examples/sync/ftfw/node1/conntrackd.conf delete mode 100644 examples/sync/ftfw/node1/keepalived.conf delete mode 100644 examples/sync/ftfw/node2/conntrackd.conf delete mode 100644 examples/sync/ftfw/node2/keepalived.conf delete mode 100755 examples/sync/ftfw/script_backup.sh delete mode 100755 examples/sync/ftfw/script_master.sh (limited to 'Makefile.am') diff --git a/ChangeLog b/ChangeLog index 272b078..e893439 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,6 +21,7 @@ o Use more appropriate names for the existing synchronization modes: o rename `persistent' mode to `alarm' o rename `nack' mode to `ftfw' o Now default synchronization mode is ftfw instead of alarm +o rename `examples' directory to `doc' version 0.9.5 (2007/07/29) ------------------------------ diff --git a/Makefile.am b/Makefile.am index 3abf2cc..3d4f9f3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,7 +5,7 @@ include Make_global.am AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 man_MANS = conntrack.8 conntrackd.8 -EXTRA_DIST = $(man_MANS) Make_global.am ChangeLog TODO examples +EXTRA_DIST = $(man_MANS) Make_global.am ChangeLog TODO doc SUBDIRS = extensions src DIST_SUBDIRS = include src extensions diff --git a/doc/cli/test.sh b/doc/cli/test.sh new file mode 100644 index 0000000..2a0fef7 --- /dev/null +++ b/doc/cli/test.sh @@ -0,0 +1,106 @@ +CONNTRACK=conntrack + +SRC=1.1.1.1 +DST=2.2.2.2 +SPORT=2005 +DPORT=21 + +case $1 in + dump) + echo "Dumping conntrack table" + $CONNTRACK -L + ;; + flush) + echo "Flushing conntrack table" + $CONNTRACK -F + ;; + new) + echo "creating a new conntrack" + $CONNTRACK -I --orig-src $SRC --orig-dst $DST \ + --reply-src $DST --reply-dst $SRC -p tcp \ + --orig-port-src $SPORT --orig-port-dst $DPORT \ + --reply-port-src $DPORT --reply-port-dst $SPORT \ + --state LISTEN -u SEEN_REPLY -t 50 + ;; + new-simple) + echo "creating a new conntrack (simplified)" + $CONNTRACK -I -s $SRC -d $DST \ + -p tcp --sport $SPORT --dport $DPORT \ + --state LISTEN -u SEEN_REPLY -t 50 + ;; + new-nat) + echo "creating a new conntrack (NAT)" + $CONNTRACK -I -s $SRC -d $DST \ + -p tcp --sport $SPORT --dport $DPORT \ + --state LISTEN -u SEEN_REPLY -t 50 --dst-nat 8.8.8.8 + ;; + get) + echo "getting a conntrack" + $CONNTRACK -G -s $SRC -d $DST \ + -p tcp --sport $SPORT --dport $DPORT + ;; + change) + echo "change a conntrack" + $CONNTRACK -U -s $SRC -d $DST \ + -p tcp --sport $SPORT --dport $DPORT \ + --state TIME_WAIT -u ASSURED,SEEN_REPLY -t 500 + ;; + delete) + $CONNTRACK -D -s $SRC -d $DST \ + -p tcp --sport $SPORT --dport $DPORT + ;; + output) + proc=$(cat /proc/net/ip_conntrack | wc -l) + netl=$($CONNTRACK -L | wc -l) + count=$(cat /proc/sys/net/ipv4/netfilter/ip_conntrack_count) + if [ $proc -ne $netl ]; then + echo "proc is $proc and netl is $netl and count is $count" + else + if [ $proc -ne $count ]; then + echo "proc is $proc and netl is $netl and count is $count" + else + echo "now $proc" + fi + fi + ;; + dump-expect) + $CONNTRACK -L expect + ;; + flush-expect) + $CONNTRACK -F expect + ;; + create-expect) + # requires modprobe ip_conntrack_ftp + $CONNTRACK -I expect --orig-src $SRC --orig-dst $DST \ + --tuple-src 4.4.4.4 --tuple-dst 5.5.5.5 \ + --mask-src 255.255.255.0 --mask-dst 255.255.255.255 \ + -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \ + -t 200 --tuple-port-src 10240 --tuple-port-dst 10241\ + --mask-port-src 10 --mask-port-dst 300 + ;; + get-expect) + $CONNTRACK -G expect --orig-src 4.4.4.4 --orig-dst 5.5.5.5 \ + --p tcp --orig-port-src 10240 --orig-port-dst 10241 + ;; + delete-expect) + $CONNTRACK -D expect --orig-src 4.4.4.4 \ + --orig-dst 5.5.5.5 -p tcp --orig-port-src 10240 \ + --orig-port-dst 10241 + ;; + *) + echo "Usage: $0 [dump" + echo " |new" + echo " |new-simple" + echo " |new-nat" + echo " |get" + echo " |change" + echo " |delete" + echo " |output" + echo " |flush" + echo " |dump-expect" + echo " |flush-expect" + echo " |create-expect" + echo " |get-expect" + echo " |delete-expect]" + ;; +esac diff --git a/doc/debian.conntrackd.init.d b/doc/debian.conntrackd.init.d new file mode 100644 index 0000000..ba847dd --- /dev/null +++ b/doc/debian.conntrackd.init.d @@ -0,0 +1,48 @@ +#!/bin/sh +# +# /etc/init.d/conntrackd +# +# Maximilian Wilhelm +# -- Mon, 06 Nov 2006 18:39:07 +0100 +# + +export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + +NAME="conntrackd" +DAEMON=`command -v conntrackd` +CONFIG="/etc/conntrack/conntrackd.conf" +PIDFILE="/var/run/${NAME}.pid" + + +# Gracefully exit if there is no daemon (debian way of life) +if [ ! -x "${DAEMON}" ]; then + exit 0 +fi + +# Check for config file +if [ ! -f /etc/conntrackd/conntrackd.conf ]; then + echo "Error: There is no config file for $NAME" >&2 + exit 1; +fi + +case "$1" in + start) + echo -n "Starting $NAME: " + start-stop-daemon --start --quiet --make-pidfile --pidfile "/var/run/${NAME}.pid" --background --exec "${DAEMON}" && echo "done." || echo "FAILED!" + ;; + stop) + echo -n "Stopping $NAME:" + start-stop-daemon --stop --quiet --oknodo --pidfile "/var/run/${NAME}.pid" && echo "done." || echo "FAILED!" + ;; + + restart) + $0 start + $0 stop + ;; + + *) + echo "Usage: /etc/init.d/conntrackd {start|stop|restart}" + exit 1 +esac + +exit 0 diff --git a/doc/stats/conntrackd.conf b/doc/stats/conntrackd.conf new file mode 100644 index 0000000..07deaa8 --- /dev/null +++ b/doc/stats/conntrackd.conf @@ -0,0 +1,76 @@ +# +# General settings +# +General { + # + # Number of buckets in the caches: hash table + # + HashSize 8192 + + # + # Maximum number of conntracks: + # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max + # + HashLimit 65535 + + # + # Logfile: on, off, or a filename + # Default: on (/var/log/conntrackd.log) + # + #LogFile off + + # + # Syslog: on, off or a facility name (daemon (default) or local0..7) + # Default: off + # + #Syslog on + + # + # Lockfile + # + LockFile /var/lock/conntrack.lock + + # + # Unix socket configuration + # + UNIX { + Path /tmp/sync.sock + Backlog 20 + } + + # + # Netlink socket buffer size + # + SocketBufferSize 262142 + + # + # Increase the socket buffer up to maximun if required + # + SocketBufferSizeMaxGrown 655355 +} + +# +# Ignore traffic for a certain set of IP's: Usually +# all the IP assigned to the firewall since local +# traffic must be ignored, just forwarded connections +# are worth to replicate +# +IgnoreTrafficFor { + IPv4_address 127.0.0.1 # loopback +} + +# +# Do not replicate certain protocol traffic +# +IgnoreProtocol { + UDP +# ICMP +# IGMP +# VRRP + # numeric numbers also valid +} + +# +# Strip NAT traffic +# +StripNAT diff --git a/doc/sync/alarm/README b/doc/sync/alarm/README new file mode 100644 index 0000000..dfd8474 --- /dev/null +++ b/doc/sync/alarm/README @@ -0,0 +1 @@ +This directory contains the files for the ALARM based protocol diff --git a/doc/sync/alarm/node1/conntrackd.conf b/doc/sync/alarm/node1/conntrackd.conf new file mode 100644 index 0000000..3004d07 --- /dev/null +++ b/doc/sync/alarm/node1/conntrackd.conf @@ -0,0 +1,140 @@ +# +# Synchronizer settings +# +Sync { + Mode ALARM { + # + # If a conntrack entry is not modified in <= 15 seconds, then + # a message is broadcasted. This mechanism is used to + # resynchronize nodes that just joined the multicast group + # + RefreshTime 15 + + # + # If we don't receive a notification about the state of + # an entry in the external cache after N seconds, then + # remove it. + # + CacheTimeout 180 + + # + # Entries committed to the connection tracking table + # starts with a limited timeout of N seconds until the + # takeover process is completed. + # + CommitTimeout 180 + } + + # + # Multicast IP and interface where messages are + # broadcasted (dedicated link). IMPORTANT: Make sure + # that iptables accepts traffic for destination + # 225.0.0.50, eg: + # + # iptables -I INPUT -d 225.0.0.50 -j ACCEPT + # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT + # + Multicast { + IPv4_address 225.0.0.50 + IPv4_interface 192.168.100.100 # IP of dedicated link + Interface eth2 + Group 3780 + } + + # Enable/Disable message checksumming + Checksum on + + # Uncomment this if you want to replicate just certain TCP states. + # This option introduces a tradeoff in the replication: it reduces + # CPU consumption and lost messages rate at the cost of having + # backup replicas that don't contain the current state that the active + # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, + # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. + # + # Replicate ESTABLISHED TIME_WAIT for TCP + + # If you have a multiprimary setup (active-active) without connection + # persistency, ie. you can't know which firewall handles a packet + # that is part of a connection, then you need direct commit of + # conntrack entries to the kernel conntrack table. OSPF setups must + # set on this option. Default is Off. + # + # CacheWriteThrough On +} + +# +# General settings +# +General { + # + # Number of buckets in the caches: hash table + # + HashSize 8192 + + # + # Maximum number of conntracks: + # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max + # + HashLimit 65535 + + # + # Logfile: on, off, or a filename + # Default: on (/var/log/conntrackd.log) + # + #LogFile off + + # + # Syslog: on, off or a facility name (daemon (default) or local0..7) + # Default: off + # + #Syslog on + + # + # Lockfile + # + LockFile /var/lock/conntrack.lock + + # + # Unix socket configuration + # + UNIX { + Path /tmp/sync.sock + Backlog 20 + } + + # + # Netlink socket buffer size + # + SocketBufferSize 262142 + + # + # Increase the socket buffer up to maximum if required + # + SocketBufferSizeMaxGrown 655355 +} + +# +# Ignore traffic for a certain set of IP's: Usually +# all the IP assigned to the firewall since local +# traffic must be ignored, just forwarded connections +# are worth to replicate +# +IgnoreTrafficFor { + IPv4_address 127.0.0.1 # loopback + IPv4_address 192.168.0.1 + IPv4_address 192.168.1.1 + IPv4_address 192.168.100.100 # dedicated link ip + IPv4_address 192.168.0.100 # virtual IP 1 + IPv4_address 192.168.1.100 # virtual IP 2 +} + +# +# Do not replicate certain protocol traffic +# +IgnoreProtocol { + UDP + ICMP + IGMP + VRRP + # numeric numbers also valid +} diff --git a/doc/sync/alarm/node1/keepalived.conf b/doc/sync/alarm/node1/keepalived.conf new file mode 100644 index 0000000..f937467 --- /dev/null +++ b/doc/sync/alarm/node1/keepalived.conf @@ -0,0 +1,39 @@ +vrrp_sync_group G1 { # must be before vrrp_instance declaration + group { + VI_1 + VI_2 + } + notify_master /etc/conntrackd/script_master.sh + notify_backup /etc/conntrackd/script_backup.sh +# notify_fault /etc/conntrackd/script_fault.sh +} + +vrrp_instance VI_1 { + interface eth1 + state SLAVE + virtual_router_id 61 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.0.100 # default CIDR mask is /32 + } +} + +vrrp_instance VI_2 { + interface eth0 + state SLAVE + virtual_router_id 62 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.1.100 + } +} diff --git a/doc/sync/alarm/node2/conntrackd.conf b/doc/sync/alarm/node2/conntrackd.conf new file mode 100644 index 0000000..fb12130 --- /dev/null +++ b/doc/sync/alarm/node2/conntrackd.conf @@ -0,0 +1,140 @@ +# +# Synchronizer settings +# +Sync { + Mode ALARM { + # + # If a conntrack entry is not modified in <= 15 seconds, then + # a message is broadcasted. This mechanism is used to + # resynchronize nodes that just joined the multicast group + # + RefreshTime 15 + + # + # If we don't receive a notification about the state of + # an entry in the external cache after N seconds, then + # remove it. + # + CacheTimeout 180 + + # + # Entries committed to the connection tracking table + # starts with a limited timeout of N seconds until the + # takeover process is completed. + # + CommitTimeout 180 + } + + # + # Multicast IP and interface where messages are + # broadcasted (dedicated link). IMPORTANT: Make sure + # that iptables accepts traffic for destination + # 225.0.0.50, eg: + # + # iptables -I INPUT -d 225.0.0.50 -j ACCEPT + # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT + # + Multicast { + IPv4_address 225.0.0.50 + IPv4_interface 192.168.100.200 # IP of dedicated link + Interface eth2 + Group 3780 + } + + # Enable/Disable message checksumming + Checksum on + + # Uncomment this if you want to replicate just certain TCP states. + # This option introduces a tradeoff in the replication: it reduces + # CPU consumption and lost messages rate at the cost of having + # backup replicas that don't contain the current state that the active + # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, + # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. + # + # Replicate ESTABLISHED TIME_WAIT for TCP + + # If you have a multiprimary setup (active-active) without connection + # persistency, ie. you can't know which firewall handles a packet + # that is part of a connection, then you need direct commit of + # conntrack entries to the kernel conntrack table. OSPF setups must + # set on this option. Default is Off. + # + # CacheWriteThrough On +} + +# +# General settings +# +General { + # + # Number of buckets in the caches: hash table + # + HashSize 8192 + + # + # Maximum number of conntracks: + # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max + # + HashLimit 65535 + + # + # Logfile: on, off, or a filename + # Default: on (/var/log/conntrackd.log) + # + #LogFile off + + # + # Syslog: on, off or a facility name (daemon (default) or local0..7) + # Default: off + # + #Syslog on + + # + # Lockfile + # + LockFile /var/lock/conntrack.lock + + # + # Unix socket configuration + # + UNIX { + Path /tmp/sync.sock + Backlog 20 + } + + # + # Netlink socket buffer size + # + SocketBufferSize 262142 + + # + # Increase the socket buffer up to maximum if required + # + SocketBufferSizeMaxGrown 655355 +} + +# +# Ignore traffic for a certain set of IP's: Usually +# all the IP assigned to the firewall since local +# traffic must be ignored, just forwarded connections +# are worth to replicate +# +IgnoreTrafficFor { + IPv4_address 127.0.0.1 # loopback + IPv4_address 192.168.0.2 + IPv4_address 192.168.1.2 + IPv4_address 192.168.100.200 # dedicated link ip + IPv4_address 192.168.0.200 # virtual IP 1 + IPv4_address 192.168.1.200 # virtual IP 2 +} + +# +# Do not replicate certain protocol traffic +# +IgnoreProtocol { + UDP + ICMP + IGMP + VRRP + # numeric numbers also valid +} diff --git a/doc/sync/alarm/node2/keepalived.conf b/doc/sync/alarm/node2/keepalived.conf new file mode 100644 index 0000000..f937467 --- /dev/null +++ b/doc/sync/alarm/node2/keepalived.conf @@ -0,0 +1,39 @@ +vrrp_sync_group G1 { # must be before vrrp_instance declaration + group { + VI_1 + VI_2 + } + notify_master /etc/conntrackd/script_master.sh + notify_backup /etc/conntrackd/script_backup.sh +# notify_fault /etc/conntrackd/script_fault.sh +} + +vrrp_instance VI_1 { + interface eth1 + state SLAVE + virtual_router_id 61 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.0.100 # default CIDR mask is /32 + } +} + +vrrp_instance VI_2 { + interface eth0 + state SLAVE + virtual_router_id 62 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.1.100 + } +} diff --git a/doc/sync/alarm/script_backup.sh b/doc/sync/alarm/script_backup.sh new file mode 100644 index 0000000..8ea2ad8 --- /dev/null +++ b/doc/sync/alarm/script_backup.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +/usr/sbin/conntrackd -B diff --git a/doc/sync/alarm/script_master.sh b/doc/sync/alarm/script_master.sh new file mode 100644 index 0000000..70c26c9 --- /dev/null +++ b/doc/sync/alarm/script_master.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +/usr/sbin/conntrackd -c +/usr/sbin/conntrackd -R diff --git a/doc/sync/ftfw/README b/doc/sync/ftfw/README new file mode 100644 index 0000000..a09db10 --- /dev/null +++ b/doc/sync/ftfw/README @@ -0,0 +1 @@ +This directory contains the files for the FT-FW based protocol diff --git a/doc/sync/ftfw/node1/conntrackd.conf b/doc/sync/ftfw/node1/conntrackd.conf new file mode 100644 index 0000000..fadeb9d --- /dev/null +++ b/doc/sync/ftfw/node1/conntrackd.conf @@ -0,0 +1,135 @@ +# +# Synchronizer settings +# +Sync { + Mode FTFW { + # + # Size of the buffer that hold destroy messages for + # possible resends (in bytes) + # + ResendBufferSize 262144 + + # + # Entries committed to the connection tracking table + # starts with a limited timeout of N seconds until the + # takeover process is completed. + # + CommitTimeout 180 + + # Set Acknowledgement window size + ACKWindowSize 20 + } + + # + # Multicast IP and interface where messages are + # broadcasted (dedicated link). IMPORTANT: Make sure + # that iptables accepts traffic for destination + # 225.0.0.50, eg: + # + # iptables -I INPUT -d 225.0.0.50 -j ACCEPT + # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT + # + Multicast { + IPv4_address 225.0.0.50 + IPv4_interface 192.168.100.100 # IP of dedicated link + Interface eth2 + Group 3780 + } + + # Enable/Disable message checksumming + Checksum on + + # Uncomment this if you want to replicate just certain TCP states. + # This option introduces a tradeoff in the replication: it reduces + # CPU consumption and lost messages rate at the cost of having + # backup replicas that don't contain the current state that the active + # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, + # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. + # + # Replicate ESTABLISHED TIME_WAIT for TCP + + # If you have a multiprimary setup (active-active) without connection + # persistency, ie. you can't know which firewall handles a packet + # that is part of a connection, then you need direct commit of + # conntrack entries to the kernel conntrack table. OSPF setups must + # set on this option. Default is Off. + # + # CacheWriteThrough On +} + +# +# General settings +# +General { + # + # Number of buckets in the caches: hash table + # + HashSize 8192 + + # + # Maximum number of conntracks: + # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max + # + HashLimit 65535 + + # + # Logfile: on, off, or a filename + # Default: on (/var/log/conntrackd.log) + # + #LogFile off + + # + # Syslog: on, off or a facility name (daemon (default) or local0..7) + # Default: off + # + #Syslog on + + # + # Lockfile + # + LockFile /var/lock/conntrack.lock + + # + # Unix socket configuration + # + UNIX { + Path /tmp/sync.sock + Backlog 20 + } + + # + # Netlink socket buffer size + # + SocketBufferSize 262142 + + # + # Increase the socket buffer up to maximum if required + # + SocketBufferSizeMaxGrown 655355 +} + +# +# Ignore traffic for a certain set of IP's: Usually +# all the IP assigned to the firewall since local +# traffic must be ignored, just forwarded connections +# are worth to replicate +# +IgnoreTrafficFor { + IPv4_address 127.0.0.1 # loopback + IPv4_address 192.168.0.1 + IPv4_address 192.168.1.1 + IPv4_address 192.168.100.100 # dedicated link ip + IPv4_address 192.168.0.100 # virtual IP 1 + IPv4_address 192.168.1.100 # virtual IP 2 +} + +# +# Do not replicate certain protocol traffic +# +IgnoreProtocol { + UDP + ICMP + IGMP + VRRP + # numeric numbers also valid +} diff --git a/doc/sync/ftfw/node1/keepalived.conf b/doc/sync/ftfw/node1/keepalived.conf new file mode 100644 index 0000000..f937467 --- /dev/null +++ b/doc/sync/ftfw/node1/keepalived.conf @@ -0,0 +1,39 @@ +vrrp_sync_group G1 { # must be before vrrp_instance declaration + group { + VI_1 + VI_2 + } + notify_master /etc/conntrackd/script_master.sh + notify_backup /etc/conntrackd/script_backup.sh +# notify_fault /etc/conntrackd/script_fault.sh +} + +vrrp_instance VI_1 { + interface eth1 + state SLAVE + virtual_router_id 61 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.0.100 # default CIDR mask is /32 + } +} + +vrrp_instance VI_2 { + interface eth0 + state SLAVE + virtual_router_id 62 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.1.100 + } +} diff --git a/doc/sync/ftfw/node2/conntrackd.conf b/doc/sync/ftfw/node2/conntrackd.conf new file mode 100644 index 0000000..59ffc4f --- /dev/null +++ b/doc/sync/ftfw/node2/conntrackd.conf @@ -0,0 +1,134 @@ +# +# Synchronizer settings +# +Sync { + Mode FTFW { + # + # Size of the buffer that hold destroy messages for + # possible resends (in bytes) + # + ResendBufferSize 262144 + + # Entries committed to the connection tracking table + # starts with a limited timeout of N seconds until the + # takeover process is completed. + # + CommitTimeout 180 + + # Set Acknowledgement window size + ACKWindowSize 20 + } + + # + # Multicast IP and interface where messages are + # broadcasted (dedicated link). IMPORTANT: Make sure + # that iptables accepts traffic for destination + # 225.0.0.50, eg: + # + # iptables -I INPUT -d 225.0.0.50 -j ACCEPT + # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT + # + Multicast { + IPv4_address 225.0.0.50 + IPv4_interface 192.168.100.200 # IP of dedicated link + Interface eth2 + Group 3780 + } + + # Enable/Disable message checksumming + Checksum on + + # Uncomment this if you want to replicate just certain TCP states. + # This option introduces a tradeoff in the replication: it reduces + # CPU consumption and lost messages rate at the cost of having + # backup replicas that don't contain the current state that the active + # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, + # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. + # + # Replicate ESTABLISHED TIME_WAIT for TCP + + # If you have a multiprimary setup (active-active) without connection + # persistency, ie. you can't know which firewall handles a packet + # that is part of a connection, then you need direct commit of + # conntrack entries to the kernel conntrack table. OSPF setups must + # set on this option. Default is Off. + # + # CacheWriteThrough On +} + +# +# General settings +# +General { + # + # Number of buckets in the caches: hash table + # + HashSize 8192 + + # + # Maximum number of conntracks: + # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max + # + HashLimit 65535 + + # + # Logfile: on, off, or a filename + # Default: on (/var/log/conntrackd.log) + # + #LogFile off + + # + # Syslog: on, off or a facility name (daemon (default) or local0..7) + # Default: off + # + #Syslog on + + # + # Lockfile + # + LockFile /var/lock/conntrack.lock + + # + # Unix socket configuration + # + UNIX { + Path /tmp/sync.sock + Backlog 20 + } + + # + # Netlink socket buffer size + # + SocketBufferSize 262142 + + # + # Increase the socket buffer up to maximum if required + # + SocketBufferSizeMaxGrown 655355 +} + +# +# Ignore traffic for a certain set of IP's: Usually +# all the IP assigned to the firewall since local +# traffic must be ignored, just forwarded connections +# are worth to replicate +# +IgnoreTrafficFor { + IPv4_address 127.0.0.1 # loopback + IPv4_address 192.168.0.2 + IPv4_address 192.168.1.2 + IPv4_address 192.168.100.200 # dedicated link ip + IPv4_address 192.168.0.200 # virtual IP 1 + IPv4_address 192.168.1.200 # virtual IP 2 +} + +# +# Do not replicate certain protocol traffic +# +IgnoreProtocol { + UDP + ICMP + IGMP + VRRP + # numeric numbers also valid +} diff --git a/doc/sync/ftfw/node2/keepalived.conf b/doc/sync/ftfw/node2/keepalived.conf new file mode 100644 index 0000000..f937467 --- /dev/null +++ b/doc/sync/ftfw/node2/keepalived.conf @@ -0,0 +1,39 @@ +vrrp_sync_group G1 { # must be before vrrp_instance declaration + group { + VI_1 + VI_2 + } + notify_master /etc/conntrackd/script_master.sh + notify_backup /etc/conntrackd/script_backup.sh +# notify_fault /etc/conntrackd/script_fault.sh +} + +vrrp_instance VI_1 { + interface eth1 + state SLAVE + virtual_router_id 61 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.0.100 # default CIDR mask is /32 + } +} + +vrrp_instance VI_2 { + interface eth0 + state SLAVE + virtual_router_id 62 + priority 80 + advert_int 3 + authentication { + auth_type PASS + auth_pass papas_con_tomate + } + virtual_ipaddress { + 192.168.1.100 + } +} diff --git a/doc/sync/ftfw/script_backup.sh b/doc/sync/ftfw/script_backup.sh new file mode 100644 index 0000000..813e375 --- /dev/null +++ b/doc/sync/ftfw/script_backup.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +/usr/sbin/conntrackd -n # request a resync from other nodes via multicast diff --git a/doc/sync/ftfw/script_master.sh b/doc/sync/ftfw/script_master.sh new file mode 100644 index 0000000..ff1dbc0 --- /dev/null +++ b/doc/sync/ftfw/script_master.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +/usr/sbin/conntrackd -c # commit the cache +/usr/sbin/conntrackd -f # flush the caches +/usr/sbin/conntrackd -R # resync with kernel conntrack table diff --git a/examples/cli/test.sh b/examples/cli/test.sh deleted file mode 100644 index 2a0fef7..0000000 --- a/examples/cli/test.sh +++ /dev/null @@ -1,106 +0,0 @@ -CONNTRACK=conntrack - -SRC=1.1.1.1 -DST=2.2.2.2 -SPORT=2005 -DPORT=21 - -case $1 in - dump) - echo "Dumping conntrack table" - $CONNTRACK -L - ;; - flush) - echo "Flushing conntrack table" - $CONNTRACK -F - ;; - new) - echo "creating a new conntrack" - $CONNTRACK -I --orig-src $SRC --orig-dst $DST \ - --reply-src $DST --reply-dst $SRC -p tcp \ - --orig-port-src $SPORT --orig-port-dst $DPORT \ - --reply-port-src $DPORT --reply-port-dst $SPORT \ - --state LISTEN -u SEEN_REPLY -t 50 - ;; - new-simple) - echo "creating a new conntrack (simplified)" - $CONNTRACK -I -s $SRC -d $DST \ - -p tcp --sport $SPORT --dport $DPORT \ - --state LISTEN -u SEEN_REPLY -t 50 - ;; - new-nat) - echo "creating a new conntrack (NAT)" - $CONNTRACK -I -s $SRC -d $DST \ - -p tcp --sport $SPORT --dport $DPORT \ - --state LISTEN -u SEEN_REPLY -t 50 --dst-nat 8.8.8.8 - ;; - get) - echo "getting a conntrack" - $CONNTRACK -G -s $SRC -d $DST \ - -p tcp --sport $SPORT --dport $DPORT - ;; - change) - echo "change a conntrack" - $CONNTRACK -U -s $SRC -d $DST \ - -p tcp --sport $SPORT --dport $DPORT \ - --state TIME_WAIT -u ASSURED,SEEN_REPLY -t 500 - ;; - delete) - $CONNTRACK -D -s $SRC -d $DST \ - -p tcp --sport $SPORT --dport $DPORT - ;; - output) - proc=$(cat /proc/net/ip_conntrack | wc -l) - netl=$($CONNTRACK -L | wc -l) - count=$(cat /proc/sys/net/ipv4/netfilter/ip_conntrack_count) - if [ $proc -ne $netl ]; then - echo "proc is $proc and netl is $netl and count is $count" - else - if [ $proc -ne $count ]; then - echo "proc is $proc and netl is $netl and count is $count" - else - echo "now $proc" - fi - fi - ;; - dump-expect) - $CONNTRACK -L expect - ;; - flush-expect) - $CONNTRACK -F expect - ;; - create-expect) - # requires modprobe ip_conntrack_ftp - $CONNTRACK -I expect --orig-src $SRC --orig-dst $DST \ - --tuple-src 4.4.4.4 --tuple-dst 5.5.5.5 \ - --mask-src 255.255.255.0 --mask-dst 255.255.255.255 \ - -p tcp --orig-port-src $SPORT --orig-port-dst $DPORT \ - -t 200 --tuple-port-src 10240 --tuple-port-dst 10241\ - --mask-port-src 10 --mask-port-dst 300 - ;; - get-expect) - $CONNTRACK -G expect --orig-src 4.4.4.4 --orig-dst 5.5.5.5 \ - --p tcp --orig-port-src 10240 --orig-port-dst 10241 - ;; - delete-expect) - $CONNTRACK -D expect --orig-src 4.4.4.4 \ - --orig-dst 5.5.5.5 -p tcp --orig-port-src 10240 \ - --orig-port-dst 10241 - ;; - *) - echo "Usage: $0 [dump" - echo " |new" - echo " |new-simple" - echo " |new-nat" - echo " |get" - echo " |change" - echo " |delete" - echo " |output" - echo " |flush" - echo " |dump-expect" - echo " |flush-expect" - echo " |create-expect" - echo " |get-expect" - echo " |delete-expect]" - ;; -esac diff --git a/examples/debian.conntrackd.init.d b/examples/debian.conntrackd.init.d deleted file mode 100644 index ba847dd..0000000 --- a/examples/debian.conntrackd.init.d +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh -# -# /etc/init.d/conntrackd -# -# Maximilian Wilhelm -# -- Mon, 06 Nov 2006 18:39:07 +0100 -# - -export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin - -NAME="conntrackd" -DAEMON=`command -v conntrackd` -CONFIG="/etc/conntrack/conntrackd.conf" -PIDFILE="/var/run/${NAME}.pid" - - -# Gracefully exit if there is no daemon (debian way of life) -if [ ! -x "${DAEMON}" ]; then - exit 0 -fi - -# Check for config file -if [ ! -f /etc/conntrackd/conntrackd.conf ]; then - echo "Error: There is no config file for $NAME" >&2 - exit 1; -fi - -case "$1" in - start) - echo -n "Starting $NAME: " - start-stop-daemon --start --quiet --make-pidfile --pidfile "/var/run/${NAME}.pid" --background --exec "${DAEMON}" && echo "done." || echo "FAILED!" - ;; - stop) - echo -n "Stopping $NAME:" - start-stop-daemon --stop --quiet --oknodo --pidfile "/var/run/${NAME}.pid" && echo "done." || echo "FAILED!" - ;; - - restart) - $0 start - $0 stop - ;; - - *) - echo "Usage: /etc/init.d/conntrackd {start|stop|restart}" - exit 1 -esac - -exit 0 diff --git a/examples/stats/conntrackd.conf b/examples/stats/conntrackd.conf deleted file mode 100644 index 07deaa8..0000000 --- a/examples/stats/conntrackd.conf +++ /dev/null @@ -1,76 +0,0 @@ -# -# General settings -# -General { - # - # Number of buckets in the caches: hash table - # - HashSize 8192 - - # - # Maximum number of conntracks: - # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max - # - HashLimit 65535 - - # - # Logfile: on, off, or a filename - # Default: on (/var/log/conntrackd.log) - # - #LogFile off - - # - # Syslog: on, off or a facility name (daemon (default) or local0..7) - # Default: off - # - #Syslog on - - # - # Lockfile - # - LockFile /var/lock/conntrack.lock - - # - # Unix socket configuration - # - UNIX { - Path /tmp/sync.sock - Backlog 20 - } - - # - # Netlink socket buffer size - # - SocketBufferSize 262142 - - # - # Increase the socket buffer up to maximun if required - # - SocketBufferSizeMaxGrown 655355 -} - -# -# Ignore traffic for a certain set of IP's: Usually -# all the IP assigned to the firewall since local -# traffic must be ignored, just forwarded connections -# are worth to replicate -# -IgnoreTrafficFor { - IPv4_address 127.0.0.1 # loopback -} - -# -# Do not replicate certain protocol traffic -# -IgnoreProtocol { - UDP -# ICMP -# IGMP -# VRRP - # numeric numbers also valid -} - -# -# Strip NAT traffic -# -StripNAT diff --git a/examples/sync/alarm/README b/examples/sync/alarm/README deleted file mode 100644 index dfd8474..0000000 --- a/examples/sync/alarm/README +++ /dev/null @@ -1 +0,0 @@ -This directory contains the files for the ALARM based protocol diff --git a/examples/sync/alarm/node1/conntrackd.conf b/examples/sync/alarm/node1/conntrackd.conf deleted file mode 100644 index 3004d07..0000000 --- a/examples/sync/alarm/node1/conntrackd.conf +++ /dev/null @@ -1,140 +0,0 @@ -# -# Synchronizer settings -# -Sync { - Mode ALARM { - # - # If a conntrack entry is not modified in <= 15 seconds, then - # a message is broadcasted. This mechanism is used to - # resynchronize nodes that just joined the multicast group - # - RefreshTime 15 - - # - # If we don't receive a notification about the state of - # an entry in the external cache after N seconds, then - # remove it. - # - CacheTimeout 180 - - # - # Entries committed to the connection tracking table - # starts with a limited timeout of N seconds until the - # takeover process is completed. - # - CommitTimeout 180 - } - - # - # Multicast IP and interface where messages are - # broadcasted (dedicated link). IMPORTANT: Make sure - # that iptables accepts traffic for destination - # 225.0.0.50, eg: - # - # iptables -I INPUT -d 225.0.0.50 -j ACCEPT - # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT - # - Multicast { - IPv4_address 225.0.0.50 - IPv4_interface 192.168.100.100 # IP of dedicated link - Interface eth2 - Group 3780 - } - - # Enable/Disable message checksumming - Checksum on - - # Uncomment this if you want to replicate just certain TCP states. - # This option introduces a tradeoff in the replication: it reduces - # CPU consumption and lost messages rate at the cost of having - # backup replicas that don't contain the current state that the active - # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, - # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. - # - # Replicate ESTABLISHED TIME_WAIT for TCP - - # If you have a multiprimary setup (active-active) without connection - # persistency, ie. you can't know which firewall handles a packet - # that is part of a connection, then you need direct commit of - # conntrack entries to the kernel conntrack table. OSPF setups must - # set on this option. Default is Off. - # - # CacheWriteThrough On -} - -# -# General settings -# -General { - # - # Number of buckets in the caches: hash table - # - HashSize 8192 - - # - # Maximum number of conntracks: - # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max - # - HashLimit 65535 - - # - # Logfile: on, off, or a filename - # Default: on (/var/log/conntrackd.log) - # - #LogFile off - - # - # Syslog: on, off or a facility name (daemon (default) or local0..7) - # Default: off - # - #Syslog on - - # - # Lockfile - # - LockFile /var/lock/conntrack.lock - - # - # Unix socket configuration - # - UNIX { - Path /tmp/sync.sock - Backlog 20 - } - - # - # Netlink socket buffer size - # - SocketBufferSize 262142 - - # - # Increase the socket buffer up to maximum if required - # - SocketBufferSizeMaxGrown 655355 -} - -# -# Ignore traffic for a certain set of IP's: Usually -# all the IP assigned to the firewall since local -# traffic must be ignored, just forwarded connections -# are worth to replicate -# -IgnoreTrafficFor { - IPv4_address 127.0.0.1 # loopback - IPv4_address 192.168.0.1 - IPv4_address 192.168.1.1 - IPv4_address 192.168.100.100 # dedicated link ip - IPv4_address 192.168.0.100 # virtual IP 1 - IPv4_address 192.168.1.100 # virtual IP 2 -} - -# -# Do not replicate certain protocol traffic -# -IgnoreProtocol { - UDP - ICMP - IGMP - VRRP - # numeric numbers also valid -} diff --git a/examples/sync/alarm/node1/keepalived.conf b/examples/sync/alarm/node1/keepalived.conf deleted file mode 100644 index f937467..0000000 --- a/examples/sync/alarm/node1/keepalived.conf +++ /dev/null @@ -1,39 +0,0 @@ -vrrp_sync_group G1 { # must be before vrrp_instance declaration - group { - VI_1 - VI_2 - } - notify_master /etc/conntrackd/script_master.sh - notify_backup /etc/conntrackd/script_backup.sh -# notify_fault /etc/conntrackd/script_fault.sh -} - -vrrp_instance VI_1 { - interface eth1 - state SLAVE - virtual_router_id 61 - priority 80 - advert_int 3 - authentication { - auth_type PASS - auth_pass papas_con_tomate - } - virtual_ipaddress { - 192.168.0.100 # default CIDR mask is /32 - } -} - -vrrp_instance VI_2 { - interface eth0 - state SLAVE - virtual_router_id 62 - priority 80 - advert_int 3 - authentication { - auth_type PASS - auth_pass papas_con_tomate - } - virtual_ipaddress { - 192.168.1.100 - } -} diff --git a/examples/sync/alarm/node2/conntrackd.conf b/examples/sync/alarm/node2/conntrackd.conf deleted file mode 100644 index fb12130..0000000 --- a/examples/sync/alarm/node2/conntrackd.conf +++ /dev/null @@ -1,140 +0,0 @@ -# -# Synchronizer settings -# -Sync { - Mode ALARM { - # - # If a conntrack entry is not modified in <= 15 seconds, then - # a message is broadcasted. This mechanism is used to - # resynchronize nodes that just joined the multicast group - # - RefreshTime 15 - - # - # If we don't receive a notification about the state of - # an entry in the external cache after N seconds, then - # remove it. - # - CacheTimeout 180 - - # - # Entries committed to the connection tracking table - # starts with a limited timeout of N seconds until the - # takeover process is completed. - # - CommitTimeout 180 - } - - # - # Multicast IP and interface where messages are - # broadcasted (dedicated link). IMPORTANT: Make sure - # that iptables accepts traffic for destination - # 225.0.0.50, eg: - # - # iptables -I INPUT -d 225.0.0.50 -j ACCEPT - # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT - # - Multicast { - IPv4_address 225.0.0.50 - IPv4_interface 192.168.100.200 # IP of dedicated link - Interface eth2 - Group 3780 - } - - # Enable/Disable message checksumming - Checksum on - - # Uncomment this if you want to replicate just certain TCP states. - # This option introduces a tradeoff in the replication: it reduces - # CPU consumption and lost messages rate at the cost of having - # backup replicas that don't contain the current state that the active - # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, - # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. - # - # Replicate ESTABLISHED TIME_WAIT for TCP - - # If you have a multiprimary setup (active-active) without connection - # persistency, ie. you can't know which firewall handles a packet - # that is part of a connection, then you need direct commit of - # conntrack entries to the kernel conntrack table. OSPF setups must - # set on this option. Default is Off. - # - # CacheWriteThrough On -} - -# -# General settings -# -General { - # - # Number of buckets in the caches: hash table - # - HashSize 8192 - - # - # Maximum number of conntracks: - # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max - # - HashLimit 65535 - - # - # Logfile: on, off, or a filename - # Default: on (/var/log/conntrackd.log) - # - #LogFile off - - # - # Syslog: on, off or a facility name (daemon (default) or local0..7) - # Default: off - # - #Syslog on - - # - # Lockfile - # - LockFile /var/lock/conntrack.lock - - # - # Unix socket configuration - # - UNIX { - Path /tmp/sync.sock - Backlog 20 - } - - # - # Netlink socket buffer size - # - SocketBufferSize 262142 - - # - # Increase the socket buffer up to maximum if required - # - SocketBufferSizeMaxGrown 655355 -} - -# -# Ignore traffic for a certain set of IP's: Usually -# all the IP assigned to the firewall since local -# traffic must be ignored, just forwarded connections -# are worth to replicate -# -IgnoreTrafficFor { - IPv4_address 127.0.0.1 # loopback - IPv4_address 192.168.0.2 - IPv4_address 192.168.1.2 - IPv4_address 192.168.100.200 # dedicated link ip - IPv4_address 192.168.0.200 # virtual IP 1 - IPv4_address 192.168.1.200 # virtual IP 2 -} - -# -# Do not replicate certain protocol traffic -# -IgnoreProtocol { - UDP - ICMP - IGMP - VRRP - # numeric numbers also valid -} diff --git a/examples/sync/alarm/node2/keepalived.conf b/examples/sync/alarm/node2/keepalived.conf deleted file mode 100644 index f937467..0000000 --- a/examples/sync/alarm/node2/keepalived.conf +++ /dev/null @@ -1,39 +0,0 @@ -vrrp_sync_group G1 { # must be before vrrp_instance declaration - group { - VI_1 - VI_2 - } - notify_master /etc/conntrackd/script_master.sh - notify_backup /etc/conntrackd/script_backup.sh -# notify_fault /etc/conntrackd/script_fault.sh -} - -vrrp_instance VI_1 { - interface eth1 - state SLAVE - virtual_router_id 61 - priority 80 - advert_int 3 - authentication { - auth_type PASS - auth_pass papas_con_tomate - } - virtual_ipaddress { - 192.168.0.100 # default CIDR mask is /32 - } -} - -vrrp_instance VI_2 { - interface eth0 - state SLAVE - virtual_router_id 62 - priority 80 - advert_int 3 - authentication { - auth_type PASS - auth_pass papas_con_tomate - } - virtual_ipaddress { - 192.168.1.100 - } -} diff --git a/examples/sync/alarm/script_backup.sh b/examples/sync/alarm/script_backup.sh deleted file mode 100755 index 8ea2ad8..0000000 --- a/examples/sync/alarm/script_backup.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -/usr/sbin/conntrackd -B diff --git a/examples/sync/alarm/script_master.sh b/examples/sync/alarm/script_master.sh deleted file mode 100755 index 70c26c9..0000000 --- a/examples/sync/alarm/script_master.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -/usr/sbin/conntrackd -c -/usr/sbin/conntrackd -R diff --git a/examples/sync/ftfw/README b/examples/sync/ftfw/README deleted file mode 100644 index a09db10..0000000 --- a/examples/sync/ftfw/README +++ /dev/null @@ -1 +0,0 @@ -This directory contains the files for the FT-FW based protocol diff --git a/examples/sync/ftfw/node1/conntrackd.conf b/examples/sync/ftfw/node1/conntrackd.conf deleted file mode 100644 index fadeb9d..0000000 --- a/examples/sync/ftfw/node1/conntrackd.conf +++ /dev/null @@ -1,135 +0,0 @@ -# -# Synchronizer settings -# -Sync { - Mode FTFW { - # - # Size of the buffer that hold destroy messages for - # possible resends (in bytes) - # - ResendBufferSize 262144 - - # - # Entries committed to the connection tracking table - # starts with a limited timeout of N seconds until the - # takeover process is completed. - # - CommitTimeout 180 - - # Set Acknowledgement window size - ACKWindowSize 20 - } - - # - # Multicast IP and interface where messages are - # broadcasted (dedicated link). IMPORTANT: Make sure - # that iptables accepts traffic for destination - # 225.0.0.50, eg: - # - # iptables -I INPUT -d 225.0.0.50 -j ACCEPT - # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT - # - Multicast { - IPv4_address 225.0.0.50 - IPv4_interface 192.168.100.100 # IP of dedicated link - Interface eth2 - Group 3780 - } - - # Enable/Disable message checksumming - Checksum on - - # Uncomment this if you want to replicate just certain TCP states. - # This option introduces a tradeoff in the replication: it reduces - # CPU consumption and lost messages rate at the cost of having - # backup replicas that don't contain the current state that the active - # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, - # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. - # - # Replicate ESTABLISHED TIME_WAIT for TCP - - # If you have a multiprimary setup (active-active) without connection - # persistency, ie. you can't know which firewall handles a packet - # that is part of a connection, then you need direct commit of - # conntrack entries to the kernel conntrack table. OSPF setups must - # set on this option. Default is Off. - # - # CacheWriteThrough On -} - -# -# General settings -# -General { - # - # Number of buckets in the caches: hash table - # - HashSize 8192 - - # - # Maximum number of conntracks: - # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max - # - HashLimit 65535 - - # - # Logfile: on, off, or a filename - # Default: on (/var/log/conntrackd.log) - # - #LogFile off - - # - # Syslog: on, off or a facility name (daemon (default) or local0..7) - # Default: off - # - #Syslog on - - # - # Lockfile - # - LockFile /var/lock/conntrack.lock - - # - # Unix socket configuration - # - UNIX { - Path /tmp/sync.sock - Backlog 20 - } - - # - # Netlink socket buffer size - # - SocketBufferSize 262142 - - # - # Increase the socket buffer up to maximum if required - # - SocketBufferSizeMaxGrown 655355 -} - -# -# Ignore traffic for a certain set of IP's: Usually -# all the IP assigned to the firewall since local -# traffic must be ignored, just forwarded connections -# are worth to replicate -# -IgnoreTrafficFor { - IPv4_address 127.0.0.1 # loopback - IPv4_address 192.168.0.1 - IPv4_address 192.168.1.1 - IPv4_address 192.168.100.100 # dedicated link ip - IPv4_address 192.168.0.100 # virtual IP 1 - IPv4_address 192.168.1.100 # virtual IP 2 -} - -# -# Do not replicate certain protocol traffic -# -IgnoreProtocol { - UDP - ICMP - IGMP - VRRP - # numeric numbers also valid -} diff --git a/examples/sync/ftfw/node1/keepalived.conf b/examples/sync/ftfw/node1/keepalived.conf deleted file mode 100644 index f937467..0000000 --- a/examples/sync/ftfw/node1/keepalived.conf +++ /dev/null @@ -1,39 +0,0 @@ -vrrp_sync_group G1 { # must be before vrrp_instance declaration - group { - VI_1 - VI_2 - } - notify_master /etc/conntrackd/script_master.sh - notify_backup /etc/conntrackd/script_backup.sh -# notify_fault /etc/conntrackd/script_fault.sh -} - -vrrp_instance VI_1 { - interface eth1 - state SLAVE - virtual_router_id 61 - priority 80 - advert_int 3 - authentication { - auth_type PASS - auth_pass papas_con_tomate - } - virtual_ipaddress { - 192.168.0.100 # default CIDR mask is /32 - } -} - -vrrp_instance VI_2 { - interface eth0 - state SLAVE - virtual_router_id 62 - priority 80 - advert_int 3 - authentication { - auth_type PASS - auth_pass papas_con_tomate - } - virtual_ipaddress { - 192.168.1.100 - } -} diff --git a/examples/sync/ftfw/node2/conntrackd.conf b/examples/sync/ftfw/node2/conntrackd.conf deleted file mode 100644 index 59ffc4f..0000000 --- a/examples/sync/ftfw/node2/conntrackd.conf +++ /dev/null @@ -1,134 +0,0 @@ -# -# Synchronizer settings -# -Sync { - Mode FTFW { - # - # Size of the buffer that hold destroy messages for - # possible resends (in bytes) - # - ResendBufferSize 262144 - - # Entries committed to the connection tracking table - # starts with a limited timeout of N seconds until the - # takeover process is completed. - # - CommitTimeout 180 - - # Set Acknowledgement window size - ACKWindowSize 20 - } - - # - # Multicast IP and interface where messages are - # broadcasted (dedicated link). IMPORTANT: Make sure - # that iptables accepts traffic for destination - # 225.0.0.50, eg: - # - # iptables -I INPUT -d 225.0.0.50 -j ACCEPT - # iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT - # - Multicast { - IPv4_address 225.0.0.50 - IPv4_interface 192.168.100.200 # IP of dedicated link - Interface eth2 - Group 3780 - } - - # Enable/Disable message checksumming - Checksum on - - # Uncomment this if you want to replicate just certain TCP states. - # This option introduces a tradeoff in the replication: it reduces - # CPU consumption and lost messages rate at the cost of having - # backup replicas that don't contain the current state that the active - # replica holds. TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, - # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN. - # - # Replicate ESTABLISHED TIME_WAIT for TCP - - # If you have a multiprimary setup (active-active) without connection - # persistency, ie. you can't know which firewall handles a packet - # that is part of a connection, then you need direct commit of - # conntrack entries to the kernel conntrack table. OSPF setups must - # set on this option. Default is Off. - # - # CacheWriteThrough On -} - -# -# General settings -# -General { - # - # Number of buckets in the caches: hash table - # - HashSize 8192 - - # - # Maximum number of conntracks: - # it must be >= $ cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max - # - HashLimit 65535 - - # - # Logfile: on, off, or a filename - # Default: on (/var/log/conntrackd.log) - # - #LogFile off - - # - # Syslog: on, off or a facility name (daemon (default) or local0..7) - # Default: off - # - #Syslog on - - # - # Lockfile - # - LockFile /var/lock/conntrack.lock - - # - # Unix socket configuration - # - UNIX { - Path /tmp/sync.sock - Backlog 20 - } - - # - # Netlink socket buffer size - # - SocketBufferSize 262142 - - # - # Increase the socket buffer up to maximum if required - # - SocketBufferSizeMaxGrown 655355 -} - -# -# Ignore traffic for a certain set of IP's: Usually -# all the IP assigned to the firewall since local -# traffic must be ignored, just forwarded connections -# are worth to replicate -# -IgnoreTrafficFor { - IPv4_address 127.0.0.1 # loopback - IPv4_address 192.168.0.2 - IPv4_address 192.168.1.2 - IPv4_address 192.168.100.200 # dedicated link ip - IPv4_address 192.168.0.200 # virtual IP 1 - IPv4_address 192.168.1.200 # virtual IP 2 -} - -# -# Do not replicate certain protocol traffic -# -IgnoreProtocol { - UDP - ICMP - IGMP - VRRP - # numeric numbers also valid -} diff --git a/examples/sync/ftfw/node2/keepalived.conf b/examples/sync/ftfw/node2/keepalived.conf deleted file mode 100644 index f937467..0000000 --- a/examples/sync/ftfw/node2/keepalived.conf +++ /dev/null @@ -1,39 +0,0 @@ -vrrp_sync_group G1 { # must be before vrrp_instance declaration - group { - VI_1 - VI_2 - } - notify_master /etc/conntrackd/script_master.sh - notify_backup /etc/conntrackd/script_backup.sh -# notify_fault /etc/conntrackd/script_fault.sh -} - -vrrp_instance VI_1 { - interface eth1 - state SLAVE - virtual_router_id 61 - priority 80 - advert_int 3 - authentication { - auth_type PASS - auth_pass papas_con_tomate - } - virtual_ipaddress { - 192.168.0.100 # default CIDR mask is /32 - } -} - -vrrp_instance VI_2 { - interface eth0 - state SLAVE - virtual_router_id 62 - priority 80 - advert_int 3 - authentication { - auth_type PASS - auth_pass papas_con_tomate - } - virtual_ipaddress { - 192.168.1.100 - } -} diff --git a/examples/sync/ftfw/script_backup.sh b/examples/sync/ftfw/script_backup.sh deleted file mode 100755 index 813e375..0000000 --- a/examples/sync/ftfw/script_backup.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -/usr/sbin/conntrackd -n # request a resync from other nodes via multicast diff --git a/examples/sync/ftfw/script_master.sh b/examples/sync/ftfw/script_master.sh deleted file mode 100755 index ff1dbc0..0000000 --- a/examples/sync/ftfw/script_master.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -/usr/sbin/conntrackd -c # commit the cache -/usr/sbin/conntrackd -f # flush the caches -/usr/sbin/conntrackd -R # resync with kernel conntrack table -- cgit v1.2.3 From 36d597429d71448c93e8c598e6a615ce4e0c14ec 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 16:41:08 +0000 Subject: Max Kellermann : remove "-g" from Makefile.am, this should be specified by the user --- ChangeLog | 1 + Makefile.am | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile.am') diff --git a/ChangeLog b/ChangeLog index 63179e7..63d8f5f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -49,6 +49,7 @@ o use umask() to set up file permissions Max Kellermann : o fix shadow warnings by renaming variables or making them local +o remove "-g" from Makefile.am, this should be specified by the user = conntrackd = o resolve global variable "alarm" conflict with alarm() function in unistd.h. diff --git a/Makefile.am b/Makefile.am index 3d4f9f3..0cd321b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,7 +10,6 @@ EXTRA_DIST = $(man_MANS) Make_global.am ChangeLog TODO doc SUBDIRS = extensions src DIST_SUBDIRS = include src extensions LIBS = @LIBNETFILTER_CONNTRACK_LIBS@ -AM_CFLAGS = -g $(OBJECTS): libtool libtool: $(LIBTOOL_DEPS) -- cgit v1.2.3 From 7784ef33db4361269afe9b302fa9dbb4a65aaf35 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Sat, 9 Feb 2008 20:07:36 +0000 Subject: o add IPv6 information to synchronization messages o add support for NAT sequence adjustment (requires Linux kernel >= 2.6.25) o remove TODO file from release tarballs --- ChangeLog | 2 ++ Makefile.am | 2 +- TODO | 2 +- configure.in | 2 +- src/build.c | 18 +++++++++++++++--- src/parse.c | 19 ++++++++++++++++--- 6 files changed, 36 insertions(+), 9 deletions(-) (limited to 'Makefile.am') diff --git a/ChangeLog b/ChangeLog index aa9b3d2..a91511f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -45,6 +45,8 @@ o constify queue_iterate() o use list_del_init() and list_empty() to check if a node is in the list 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 Max Kellermann : diff --git a/Makefile.am b/Makefile.am index 0cd321b..f9fba72 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,7 +5,7 @@ include Make_global.am AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 man_MANS = conntrack.8 conntrackd.8 -EXTRA_DIST = $(man_MANS) Make_global.am ChangeLog TODO doc +EXTRA_DIST = $(man_MANS) Make_global.am ChangeLog doc SUBDIRS = extensions src DIST_SUBDIRS = include src extensions diff --git a/TODO b/TODO index 9450aeb..c3cd004 100644 --- a/TODO +++ b/TODO @@ -20,7 +20,7 @@ by dificulty levels: [ ] study better keepalived transitions [X] fix ipv6 support [X] add support setup related conntracks - [ ] NAT sequence adjustment support + [X] NAT sequence adjustment support = Open issues that won't be ever resolved = * unsupported stateful iptables matches: diff --git a/configure.in b/configure.in index 6a9d882..920f42f 100644 --- a/configure.in +++ b/configure.in @@ -18,7 +18,7 @@ esac dnl Dependencies LIBNFNETLINK_REQUIRED=0.0.32 -LIBNETFILTER_CONNTRACK_REQUIRED=0.0.88 +LIBNETFILTER_CONNTRACK_REQUIRED=0.0.89 PKG_CHECK_MODULES(LIBNFNETLINK, libnfnetlink >= $LIBNFNETLINK_REQUIRED,, AC_MSG_ERROR(Cannot find libnfnetlink >= $LIBNFNETLINK_REQUIRED)) diff --git a/src/build.c b/src/build.c index 3de1c25..d6c8837 100644 --- a/src/build.c +++ b/src/build.c @@ -58,6 +58,14 @@ static void __build_u32(const struct nf_conntrack *ct, addattr(pld, attr, &data, sizeof(uint32_t)); } +static void __build_pointer_be(const struct nf_conntrack *ct, + struct netpld *pld, + int attr, + size_t size) +{ + addattr(pld, attr, nfct_get_attr(ct, attr), size); +} + static void __nat_build_u32(uint32_t data, struct netpld *pld, int attr) { data = htonl(data); @@ -70,13 +78,17 @@ static void __nat_build_u16(uint16_t data, struct netpld *pld, int attr) addattr(pld, attr, &data, sizeof(uint16_t)); } -/* XXX: IPv6 and ICMP not supported */ +/* XXX: ICMP not supported */ void build_netpld(struct nf_conntrack *ct, struct netpld *pld, int query) { if (nfct_attr_is_set(ct, ATTR_IPV4_SRC)) - __build_u32(ct, pld, ATTR_IPV4_SRC); + __build_pointer_be(ct, pld, ATTR_IPV4_SRC, sizeof(uint32_t)); if (nfct_attr_is_set(ct, ATTR_IPV4_DST)) - __build_u32(ct, pld, ATTR_IPV4_DST); + __build_pointer_be(ct, pld, ATTR_IPV4_DST, sizeof(uint32_t)); + if (nfct_attr_is_set(ct, ATTR_IPV6_SRC)) + __build_pointer_be(ct, pld, ATTR_IPV6_SRC, sizeof(uint32_t)*4); + if (nfct_attr_is_set(ct, ATTR_IPV6_DST)) + __build_pointer_be(ct, pld, ATTR_IPV6_DST, sizeof(uint32_t)*4); if (nfct_attr_is_set(ct, ATTR_L3PROTO)) __build_u8(ct, pld, ATTR_L3PROTO); if (nfct_attr_is_set(ct, ATTR_PORT_SRC)) diff --git a/src/parse.c b/src/parse.c index 5bc71ef..8ef2e8d 100644 --- a/src/parse.c +++ b/src/parse.c @@ -38,11 +38,18 @@ static void parse_u32(struct nf_conntrack *ct, int attr, void *data) nfct_set_attr_u32(ct, attr, ntohl(*value)); } +static void parse_pointer_be(struct nf_conntrack *ct, int attr, void *data) +{ + nfct_set_attr(ct, attr, data); +} + typedef void (*parse)(struct nf_conntrack *ct, int attr, void *data); static parse h[ATTR_MAX] = { - [ATTR_IPV4_SRC] = parse_u32, - [ATTR_IPV4_DST] = parse_u32, + [ATTR_IPV4_SRC] = parse_pointer_be, + [ATTR_IPV4_DST] = parse_pointer_be, + [ATTR_IPV6_SRC] = parse_pointer_be, + [ATTR_IPV6_DST] = parse_pointer_be, [ATTR_L3PROTO] = parse_u8, [ATTR_PORT_SRC] = parse_u16, [ATTR_PORT_DST] = parse_u16, @@ -61,7 +68,13 @@ static parse h[ATTR_MAX] = { [ATTR_MASTER_L3PROTO] = parse_u8, [ATTR_MASTER_PORT_SRC] = parse_u16, [ATTR_MASTER_PORT_DST] = parse_u16, - [ATTR_MASTER_L4PROTO] = parse_u8 + [ATTR_MASTER_L4PROTO] = parse_u8, + [ATTR_ORIG_NAT_SEQ_CORRECTION_POS] = parse_u32, + [ATTR_ORIG_NAT_SEQ_OFFSET_BEFORE] = parse_u32, + [ATTR_ORIG_NAT_SEQ_OFFSET_AFTER] = parse_u32, + [ATTR_REPL_NAT_SEQ_CORRECTION_POS] = parse_u32, + [ATTR_REPL_NAT_SEQ_OFFSET_BEFORE] = parse_u32, + [ATTR_REPL_NAT_SEQ_OFFSET_AFTER] = parse_u32, }; void parse_netpld(struct nf_conntrack *ct, struct netpld *pld, int *query) -- cgit v1.2.3 From f5c1405f460a4d79e6fbafda3cb9e29e35886aea Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Sun, 9 Mar 2008 20:14:08 +0000 Subject: remove .svn from doc/ in tarballs (reported by Gilad Benjamini) --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index f9fba72..80b6b39 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,4 +17,4 @@ libtool: $(LIBTOOL_DEPS) dist-hook: rm -rf `find $(distdir)/debian -name .svn` - rm -rf `find $(distdir)/examples -name .svn` + rm -rf `find $(distdir)/doc -name .svn` -- cgit v1.2.3 From 40598325d5ff7a6b928640e456a377001aeae285 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 15 Jun 2008 22:03:53 +0200 Subject: do not include Changelog in tarballs, user git shortlog for changelog instead --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 80b6b39..7383328 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,7 +5,7 @@ include Make_global.am AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 man_MANS = conntrack.8 conntrackd.8 -EXTRA_DIST = $(man_MANS) Make_global.am ChangeLog doc +EXTRA_DIST = $(man_MANS) Make_global.am doc SUBDIRS = extensions src DIST_SUBDIRS = include src extensions -- cgit v1.2.3 From 4dd73e4e34b57685d8a85e041f6a0b4a65200e30 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 26 Jan 2009 19:30:33 +0100 Subject: build: upgrade build system - add .gitignore files - replace outdated autoconf macros by new constructs, including autogen.sh - and use AC_CONFIG_MACRO_DIR as suggested by libtool2: libtoolize: Consider adding `AC_CONFIG_MACRO_DIR([m4])' to configure.in and libtoolize: rerunning libtoolize, to keep the correct libtool macros in-tree. libtoolize: Consider adding `-I m4' to ACLOCAL_AMFLAGS in Makefile.am. Signed-off-by: Jan Engelhardt Signed-off-by: Pablo Neira Ayuso --- Makefile.am | 1 + autogen.sh | 18 ++---------------- configure.in | 6 ++++-- 3 files changed, 7 insertions(+), 18 deletions(-) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 7383328..fde65aa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,6 +2,7 @@ include Make_global.am # not a GNU package. You can remove this line, if # have all needed files, that a GNU package needs +ACLOCAL_AMFLAGS = -I m4 AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 man_MANS = conntrack.8 conntrackd.8 diff --git a/autogen.sh b/autogen.sh index e76d3ef..36b2a2a 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,18 +1,4 @@ #!/bin/sh -run () -{ - echo "running: $*" - eval $* - - if test $? != 0 ; then - echo "error: while running '$*'" - exit 1 - fi -} - -run aclocal -run libtoolize -f -#run autoheader -run automake -a -run autoconf +autoreconf -fi; +rm -Rf autom4te.cache; diff --git a/configure.in b/configure.in index c430df7..cd2e7d5 100644 --- a/configure.in +++ b/configure.in @@ -2,7 +2,8 @@ AC_INIT(conntrack-tools, 0.9.10, pablo@netfilter.org) AC_CANONICAL_SYSTEM -AM_INIT_AUTOMAKE +AC_CONFIG_MACRO_DIR([m4]) +AM_INIT_AUTOMAKE([-Wall]) AC_PROG_CC AM_PROG_LIBTOOL @@ -130,4 +131,5 @@ CFLAGS="$CFLAGS $LIBNETFILTER_CONNTRACK_CFLAGS" AC_SUBST(LIBNETFILTER_CONNTRACK_LIBS) -AC_OUTPUT(Makefile src/Makefile include/Makefile extensions/Makefile) +AC_CONFIG_FILES([Makefile src/Makefile include/Makefile extensions/Makefile]) +AC_OUTPUT -- cgit v1.2.3 From 40698eacd312893cc9feba2b6b93d81d47245f74 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 6 Mar 2009 19:50:43 +0100 Subject: src: remove debian/ directory This patch removes the debian directory. According to the debian policy, this directory should not be in source tree. Signed-off-by: Pablo Neira Ayuso --- Makefile.am | 1 - debian/changelog | 11 ----------- debian/conntrack.install | 2 -- debian/control | 20 -------------------- debian/copyright | 9 --------- debian/libconntrack-extensions.install | 1 - debian/rules | 12 ------------ 7 files changed, 56 deletions(-) delete mode 100644 debian/changelog delete mode 100644 debian/conntrack.install delete mode 100644 debian/control delete mode 100644 debian/copyright delete mode 100644 debian/libconntrack-extensions.install delete mode 100755 debian/rules (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index fde65aa..c7afd08 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,5 +17,4 @@ libtool: $(LIBTOOL_DEPS) $(SHELL) ./config.status --recheck dist-hook: - rm -rf `find $(distdir)/debian -name .svn` rm -rf `find $(distdir)/doc -name .svn` diff --git a/debian/changelog b/debian/changelog deleted file mode 100644 index 3f9c444..0000000 --- a/debian/changelog +++ /dev/null @@ -1,11 +0,0 @@ -conntrack (1.00beta1) unstable; urgency=low - - * new upstream release - - -- Harald Welte Sat, 07 Jan 2006 15:55:51 +0100 - -conntrack (0.99-0+pre1) unstable; urgency=low - - * initial debian release - - -- Max Kellermann Sun, 27 Nov 2005 18:17:30 +0100 diff --git a/debian/conntrack.install b/debian/conntrack.install deleted file mode 100644 index 2e15100..0000000 --- a/debian/conntrack.install +++ /dev/null @@ -1,2 +0,0 @@ -usr/sbin -usr/share/man diff --git a/debian/control b/debian/control deleted file mode 100644 index 949ee84..0000000 --- a/debian/control +++ /dev/null @@ -1,20 +0,0 @@ -Source: conntrack -Section: net -Priority: optional -Maintainer: Max Kellermann -Build-Depends: cdbs (>= 0.4), debhelper (>= 4.2), gcc (>= 3.4), libnfnetlink-dev (>= 0.0.13), libnetfilter-conntrack-dev (>= 0.0.28) -Standards-Version: 3.6.2 - -Package: conntrack -Architecture: any -Depends: ${shlibs:Depends}, libconntrack-extensions (= ${Source-Version}) -Description: Program to modify the conntrack tables - The userspace connection tracking table administration program. - -Package: libconntrack-extensions -Architecture: any -Depends: ${shlibs:Depends} -Description: Program to modify the conntrack tables - The userspace connection tracking table administration program. - . - This package provides the protocol extensions. diff --git a/debian/copyright b/debian/copyright deleted file mode 100644 index 469c053..0000000 --- a/debian/copyright +++ /dev/null @@ -1,9 +0,0 @@ -This Debian package was created by Max Kellermann . - -The upstream sources were downloaded from: - http://ftp.netfilter.org/pub/conntrack/ - -The GNU General Public License version 2 applies to the upstream -sources. On Debian systems, the complete text of the GNU General -Public License version 2 can be found in the -/usr/share/common-licenses/GPL-2 file. diff --git a/debian/libconntrack-extensions.install b/debian/libconntrack-extensions.install deleted file mode 100644 index d018987..0000000 --- a/debian/libconntrack-extensions.install +++ /dev/null @@ -1 +0,0 @@ -usr/lib/conntrack diff --git a/debian/rules b/debian/rules deleted file mode 100755 index 1255026..0000000 --- a/debian/rules +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/make -f -# -*- mode: makefile; coding: utf-8 -*- - -UPSTREAM_VERSION := $(shell dpkg-parsechangelog | egrep '^Version:' | cut -f2 -d' ' | cut -f1 -d-) -DEB_TARBALL := conntrack-$(UPSTREAM_VERSION).tar.bz2 -DEB_TAR_SRCDIR := conntrack-$(UPSTREAM_VERSION) - -include /usr/share/cdbs/1/rules/debhelper.mk -#include /usr/share/cdbs/1/rules/tarball.mk -include /usr/share/cdbs/1/class/autotools.mk - -DEB_DH_INSTALL_SOURCEDIR := debian/tmp -- cgit v1.2.3 From 0e8c6f54446f2e78036e3f46344ebd4e2e10533e Mon Sep 17 00:00:00 2001 From: Thomas Jarosch Date: Tue, 26 May 2009 11:48:24 +0200 Subject: build: Added "m4" directory to make dist Otherwise autoreconf fails like this: aclocal: couldn't open directory `m4': No such file or directory autoreconf: aclocal failed with exit status: 1 Signed-off-by: Thomas Jarosch Signed-off-by: Pablo Neira Ayuso --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index c7afd08..70c1bd0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,7 +6,7 @@ ACLOCAL_AMFLAGS = -I m4 AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 man_MANS = conntrack.8 conntrackd.8 -EXTRA_DIST = $(man_MANS) Make_global.am doc +EXTRA_DIST = $(man_MANS) Make_global.am doc m4 SUBDIRS = extensions src DIST_SUBDIRS = include src extensions -- cgit v1.2.3 From 1050f99bb5af5047cf60b7a57ef9f8357e305f9b Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 31 Oct 2010 00:29:11 +0200 Subject: build: use modern call syntax for AM_INIT_AUTOMAKE automake options also need to definitely go into configure.ac, otherwise they only apply to a single directory. Signed-off-by: Jan Engelhardt --- Makefile.am | 3 --- configure.ac | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 70c1bd0..23f646c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,9 +1,6 @@ include Make_global.am -# not a GNU package. You can remove this line, if -# have all needed files, that a GNU package needs ACLOCAL_AMFLAGS = -I m4 -AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 man_MANS = conntrack.8 conntrackd.8 EXTRA_DIST = $(man_MANS) Make_global.am doc m4 diff --git a/configure.ac b/configure.ac index 88faede..f840a00 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_INIT(conntrack-tools, 0.9.15, pablo@netfilter.org) AC_CANONICAL_SYSTEM AC_CONFIG_MACRO_DIR([m4]) -AM_INIT_AUTOMAKE([-Wall]) +AM_INIT_AUTOMAKE([-Wall foreign subdir-objects dist-bzip2 1.6]) AC_PROG_CC AM_PROG_LIBTOOL -- cgit v1.2.3 From 0dd464957c864829bf5730b71279765a0376e3f6 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 31 Oct 2010 00:36:40 +0200 Subject: build: remove statements without effect Signed-off-by: Jan Engelhardt --- Makefile.am | 4 ---- configure.ac | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 23f646c..afb4595 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,9 +9,5 @@ SUBDIRS = extensions src DIST_SUBDIRS = include src extensions LIBS = @LIBNETFILTER_CONNTRACK_LIBS@ -$(OBJECTS): libtool -libtool: $(LIBTOOL_DEPS) - $(SHELL) ./config.status --recheck - dist-hook: rm -rf `find $(distdir)/doc -name .svn` diff --git a/configure.ac b/configure.ac index f840a00..e068798 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_INIT(conntrack-tools, 0.9.15, pablo@netfilter.org) -AC_CANONICAL_SYSTEM +AC_CANONICAL_HOST AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([-Wall foreign subdir-objects dist-bzip2 1.6]) @@ -12,7 +12,7 @@ AC_PROG_LN_S AM_PROG_LEX AC_PROG_YACC -case $target in +case "$host" in *-*-linux*) ;; *) AC_MSG_ERROR([Linux only, dude!]);; esac -- cgit v1.2.3