summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Harpin <development@landsofshadow.co.uk>2015-11-21 14:44:29 +0000
committerAlex Harpin <development@landsofshadow.co.uk>2015-11-21 14:44:29 +0000
commit2a53b5dfee3c80b4c4940ad4c73c82248b4571bb (patch)
tree73a4fe81edc619a6180ee8d1a02ef5b1942ba910
parent1e0476f8157fc09c6f9ff086e7b55452b39ea48d (diff)
parente61ac9a2e58cdcf6dc9a12d32b1f221e078e5d05 (diff)
downloadconntrack-tools-2a53b5dfee3c80b4c4940ad4c73c82248b4571bb.tar.gz
conntrack-tools-2a53b5dfee3c80b4c4940ad4c73c82248b4571bb.zip
Merge tag 'conntrack-tools-1.4.0' into lithium
conntrack-tools 1.4.0 release
-rw-r--r--Make_global.am4
-rw-r--r--configure.ac13
-rw-r--r--doc/helper/conntrackd.conf13
-rw-r--r--doc/manual/conntrack-tools.tmpl166
-rw-r--r--doc/sync/alarm/conntrackd.conf3
-rw-r--r--doc/sync/ftfw/conntrackd.conf3
-rw-r--r--doc/sync/notrack/conntrackd.conf3
-rw-r--r--include/helper.h9
-rw-r--r--include/linux/netfilter/nfnetlink_queue.h11
-rw-r--r--src/Makefile.am5
-rw-r--r--src/build.c3
-rw-r--r--src/conntrack.c161
-rw-r--r--src/cthelper.c9
-rw-r--r--src/ctnl.c4
-rw-r--r--src/expect.c2
-rw-r--r--src/filter.c12
-rw-r--r--src/helpers/ftp.c7
-rw-r--r--src/nfct-extensions/helper.c8
-rw-r--r--src/parse.c1
-rw-r--r--src/read_config_lex.l1
-rw-r--r--src/read_config_yy.y42
-rw-r--r--tests/conntrackd/cthelper/expect.c3
-rwxr-xr-xtests/conntrackd/cthelper/main.c4
23 files changed, 340 insertions, 147 deletions
diff --git a/Make_global.am b/Make_global.am
index 7b5342d..23c7dd0 100644
--- a/Make_global.am
+++ b/Make_global.am
@@ -4,4 +4,6 @@ AM_CFLAGS = -std=gnu99 -W -Wall \
-Wmissing-prototypes -Wwrite-strings -Wcast-qual -Wfloat-equal -Wshadow -Wpointer-arith -Wbad-function-cast -Wsign-compare -Waggregate-return -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wstrict-prototypes -Wundef \
-Wno-unused-parameter ${LIBNFNETLINK_CFLAGS} ${LIBMNL_CFLAGS} \
${LIBNETFILTER_CONNTRACK_CFLAGS} \
- ${LIBNETFILTER_CTTIMEOUT_CFLAGS}
+ ${LIBNETFILTER_CTTIMEOUT_CFLAGS} \
+ ${LIBNETFILTER_QUEUE_CFLAGS} \
+ ${LIBNETFILTER_CTHELPER_CFLAGS}
diff --git a/configure.ac b/configure.ac
index f628521..cbe581c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT(conntrack-tools, 1.2.1, pablo@netfilter.org)
+AC_INIT(conntrack-tools, 1.4.0, pablo@netfilter.org)
AC_CONFIG_AUX_DIR([build-aux])
AC_CANONICAL_HOST
@@ -54,12 +54,12 @@ else
flex.])
fi
-PKG_CHECK_MODULES([LIBNFNETLINK], [libnfnetlink >= 1.0.0])
+PKG_CHECK_MODULES([LIBNFNETLINK], [libnfnetlink >= 1.0.1])
PKG_CHECK_MODULES([LIBMNL], [libmnl >= 1.0.3])
-PKG_CHECK_MODULES([LIBNETFILTER_CONNTRACK], [libnetfilter_conntrack >= 1.0.1])
+PKG_CHECK_MODULES([LIBNETFILTER_CONNTRACK], [libnetfilter_conntrack >= 1.0.2])
PKG_CHECK_MODULES([LIBNETFILTER_CTTIMEOUT], [libnetfilter_cttimeout >= 1.0.0])
PKG_CHECK_MODULES([LIBNETFILTER_CTHELPER], [libnetfilter_cthelper >= 1.0.0])
-PKG_CHECK_MODULES([LIBNETFILTER_QUEUE], [libnetfilter_queue >= 1.0.0])
+PKG_CHECK_MODULES([LIBNETFILTER_QUEUE], [libnetfilter_queue >= 1.0.2])
AC_CHECK_HEADERS([linux/capability.h],, [AC_MSG_ERROR([Cannot find linux/capabibility.h])])
@@ -119,5 +119,10 @@ dnl debug/src/Makefile
dnl extensions/Makefile
dnl src/Makefile])
+if test ! -z "$libdir"; then
+ MODULE_DIR="\\\"$libdir/conntrack-tools/\\\""
+ CFLAGS="$CFLAGS -DCONNTRACKD_LIB_DIR=$MODULE_DIR"
+fi
+
AC_CONFIG_FILES([Makefile src/Makefile include/Makefile include/linux/Makefile include/linux/netfilter/Makefile extensions/Makefile src/helpers/Makefile])
AC_OUTPUT
diff --git a/doc/helper/conntrackd.conf b/doc/helper/conntrackd.conf
index 80f1f92..56f5162 100644
--- a/doc/helper/conntrackd.conf
+++ b/doc/helper/conntrackd.conf
@@ -14,6 +14,16 @@ Helper {
# the kernel.
#
QueueNum 0
+
+ #
+ # Maximum number of packets waiting in the queue to receive
+ # a verdict from user-space. Default is 1024.
+ #
+ # Rise value if you hit the following error message:
+ # "nf_queue: full at X entries, dropping packets(s)"
+ #
+ QueueLen 10240
+
#
# Set the Expectation policy for this helper.
#
@@ -30,6 +40,7 @@ Helper {
}
Type rpc inet tcp {
QueueNum 1
+ QueueLen 10240
Policy rpc {
ExpectMax 1
ExpectTimeout 300
@@ -37,6 +48,7 @@ Helper {
}
Type rpc inet udp {
QueueNum 2
+ QueueLen 10240
Policy rpc {
ExpectMax 1
ExpectTimeout 300
@@ -44,6 +56,7 @@ Helper {
}
Type tns inet tcp {
QueueNum 3
+ QueueLen 10240
Policy tns {
ExpectMax 1
ExpectTimeout 300
diff --git a/doc/manual/conntrack-tools.tmpl b/doc/manual/conntrack-tools.tmpl
index dbf836d..f21a4ff 100644
--- a/doc/manual/conntrack-tools.tmpl
+++ b/doc/manual/conntrack-tools.tmpl
@@ -19,7 +19,7 @@
</authorgroup>
<copyright>
- <year>2008-2011</year>
+ <year>2008-2012</year>
<holder>Pablo Neira Ayuso</holder>
</copyright>
@@ -37,7 +37,7 @@
<releaseinfo>
This document details how to install and configure the
<ulink url="http://conntrack-tools.netfilter.org">conntrack-tools</ulink>
- &gt;= 1.0.0. This document will evolve in the future to cover new features
+ &gt;= 1.4.0. This document will evolve in the future to cover new features
and changes.</releaseinfo>
</bookinfo>
@@ -660,6 +660,13 @@ Sync {
<sect3 id="sync-expect"><title>Synchronization of expectations</title>
+ <note><title>Check your Linux kernel version first</title>
+ <para>
+ The synchronization of expectations require a Linux kernel &gt;= 3.5
+ to work appropriately.
+ </para>
+ </note>
+
<para>The connection tracking system provides helpers that allows you to
filter multi-flow application protocols like FTP, H.323 and SIP among many
others. These protocols usually split the control and data traffic in
@@ -689,7 +696,9 @@ Sync {
ExpectationSync {
ftp
sip
- h323
+ ras # for H.323
+ q.931 # for H.323
+ h.245 # for H.323
}
}
}</programlisting>
@@ -818,7 +827,154 @@ Sync {
</sect2>
-<sect2 id="sync-trouble"><title>Troubleshooting</title>
+</sect1>
+
+<sect1 id="helpers"><title>User-space helpers</title>
+
+ <note><title>Check your Linux kernel version first</title>
+ <para>
+ The user-space helper infrastructure requires a Linux kernel &gt;= 3.6
+ to work appropriately.
+ </para>
+ </note>
+
+<para>Connection tracking helpers allows you to filter multi-flow protocols
+that usually separate control and data traffic into different flows.
+These protocols usually violate network layering by including layer 3/4
+details, eg. IP address and TCP/UDP ports, in their application protocol
+(which resides in layer 7). This is problematic for gateways since they
+operate at packet-level, ie. layers 3/4, and therefore they miss this
+important information to filter these protocols appropriately.</para>
+
+<para>Helpers inspect packet content (at layer 7) and create the so-called
+expectations. These expectations are added to one internal table
+that resides in the gateway. For each new packet arriving to the
+gateway, the gateway first looks up for matching expectations. If
+there is any, then this flow is accepted since it's been expected.
+Note this lookup only occurs for the first packet that is part of one
+newly established flow, not for all packets.</para>
+
+<para>Since 1.4.0, conntrackd provides the infrastructure to develop
+helpers in user-space. The main features of the user-space infrastructure
+for helpers are:</para>
+
+<itemizedlist>
+
+<listitem><para>Rapid connection tracking helper development, as developing code
+in user-space is usually faster.</para></listitem>
+
+<listitem><para>Reliability: A buggy helper does not crash the kernel. If the helper
+fails, ie. the conntrackd crashes, Moreover, we can monitor the helper process
+and restart it in case of problems.</para></listitem>
+
+<listitem><para>Security: Avoid complex string matching and mangling in
+kernel-space running in privileged mode. Going further, we can even think
+about running user-space helper as a non-root process.</para></listitem>
+
+<listitem><para>It allows the development of very specific helpers for
+proprietary protocols that are not standard. This is the case of the SQL*net
+helper. Implementing this in kernel-space may be problematic, since
+this may not be accepted for ainline inclusion in the Linux kernel.
+As an alternative, we can still distribute this support as separate
+patches. However, my personal experience is that, given that the
+kernel API/ABI is not stable, changes in the interface lead to the
+breakage of the patch. This highly increase the overhead in the
+maintainance.</para></listitem>
+
+</itemizedlist>
+
+<para>Currently, the infrastructure supports the following user-space helpers:
+</para>
+
+<itemizedlist>
+<listitem><para>Oracle*TNS, to support its special <emphasis>Redirect</emphasis> message.</para></listitem>
+<listitem><para>NFSv3, mind that version 4 does not require this helper.</para></listitem>
+<listitem><para>FTP (this helper is also available in kernel-space).</para></listitem>
+</itemizedlist>
+
+<para>The following steps describe how to enable the RPC portmapper helper for NFSv3 (this is similar for other helpers):</para>
+
+<orderedlist>
+<listitem><para>Register user-space helper:
+
+<programlisting>
+nfct helper add rpc inet udp
+nfct helper add rpc inet tcp
+</programlisting>
+
+This registers the portmapper helper for both UDP and TCP (NFSv3 traffic goes both over TCP and UDP).
+</para></listitem>
+
+<listitem><para>Add iptables rule using the CT target:
+
+<programlisting>
+# iptables -I OUTPUT -t raw -p udp --dport 111 -j CT --helper rpc
+# iptables -I OUTPUT -t raw -p tcp --dport 111 -j CT --helper rpc
+</programlisting>
+
+With this, packets matching port TCP/UDP/111 are passed to user-space for
+inspection. If there is no instance of conntrackd configured to support
+user-space helpers, no inspection happens and packets are not sent to
+user-space.</para></listitem>
+
+<listitem><para>Add configuration to conntrackd.conf:
+
+<programlisting>
+Helper {
+ Type rpc inet udp {
+ QueueNum 1
+ QueueLen 10240
+ Policy rpc {
+ ExpectMax 1
+ ExpectTimeout 300
+ }
+ }
+ Type rpc inet tcp {
+ QueueNum 2
+ QueueLen 10240
+ Policy rpc {
+ ExpectMax 1
+ ExpectTimeout 300
+ }
+ }
+}
+</programlisting>
+
+This configures conntrackd to use NFQUEUE queue numbers 1 and 2 to send traffic
+for inspection to user-space</para>
+
+ <note><title>If you have some custom libnetfilter_queue application</title>
+ <para>
+ Make sure your queue numbers do not collide with those used in your
+ conntrackd.conf file.
+ </para>
+ </note>
+
+</listitem>
+
+</orderedlist>
+
+<para>Now you can test this (assuming you have some working NFSv3 setup) with:
+
+<programlisting>
+mount -t nfs -onfsvers=3 mynfs.server.info:/srv/cvs /mnt/
+</programlisting>
+
+</para>
+
+<para>You should see new expectations being added via:
+
+<programlisting>
+# conntrack -E expect
+ [NEW] 300 proto=17 src=1.2.3.4 dst=1.2.3.4 sport=0 dport=54834 mask-src=255.255.255.255 mask-dst=255.255.255.255 sport=0 dport=65535 master-src=1.2.3.4 master-dst=1.2.3.4 sport=58190 dport=111 PERMANENT class=0 helper=rpc
+ [NEW] 300 proto=6 src=1.2.3.4 dst=1.2.3.4 sport=0 dport=2049 mask-src=255.255.255.255 mask-dst=255.255.255.255 sport=0 dport=65535 master-src=1.2.3.4 master-dst=1.2.3.4 sport=55450 dport=111 PERMANENT class=0 helper=rpc
+ [NEW] 300 proto=17 src=1.2.3.4 dst=1.2.3.4 sport=0 dport=58031 mask-src=255.255.255.255 mask-dst=255.255.255.255 sport=0 dport=65535 master-src=1.2.3.4 master-dst=1.2.3.4 sport=56309 dport=111 PERMANENT class=0 helper=rpc
+</programlisting>
+</para>
+
+</sect1>
+
+<sect1 id="sync-trouble"><title>Troubleshooting</title>
<para>Problems with <emphasis>conntrackd</emphasis>? The following list
of questions should help for troubleshooting:</para>
@@ -1024,8 +1180,6 @@ not enough space errors: 0
</qandaset>
-</sect2>
-
</sect1>
</chapter>
diff --git a/doc/sync/alarm/conntrackd.conf b/doc/sync/alarm/conntrackd.conf
index b9520fb..0223745 100644
--- a/doc/sync/alarm/conntrackd.conf
+++ b/doc/sync/alarm/conntrackd.conf
@@ -194,7 +194,8 @@ Sync {
# Set this option on if you want to enable the synchronization
# of expectations. You have to specify the list of helpers that
- # you want to enable. Default is off.
+ # you want to enable. Default is off. This feature requires
+ # a Linux kernel >= 3.5.
#
# ExpectationSync {
# ftp
diff --git a/doc/sync/ftfw/conntrackd.conf b/doc/sync/ftfw/conntrackd.conf
index 53a7d0f..65e7b77 100644
--- a/doc/sync/ftfw/conntrackd.conf
+++ b/doc/sync/ftfw/conntrackd.conf
@@ -217,7 +217,8 @@ Sync {
# Set this option on if you want to enable the synchronization
# of expectations. You have to specify the list of helpers that
- # you want to enable. Default is off.
+ # you want to enable. Default is off. This feature requires
+ # a Linux kernel >= 3.5.
#
# ExpectationSync {
# ftp
diff --git a/doc/sync/notrack/conntrackd.conf b/doc/sync/notrack/conntrackd.conf
index 11f022e..3d036fb 100644
--- a/doc/sync/notrack/conntrackd.conf
+++ b/doc/sync/notrack/conntrackd.conf
@@ -256,7 +256,8 @@ Sync {
# Set this option on if you want to enable the synchronization
# of expectations. You have to specify the list of helpers that
- # you want to enable. Default is off.
+ # you want to enable. Default is off. This feature requires
+ # a Linux kernel >= 3.5.
#
# ExpectationSync {
# ftp
diff --git a/include/helper.h b/include/helper.h
index 02ff3df..9d96fb7 100644
--- a/include/helper.h
+++ b/include/helper.h
@@ -35,6 +35,7 @@ struct ctd_helper {
struct ctd_helper_instance {
struct list_head head;
uint32_t queue_num;
+ uint32_t queue_len;
uint16_t l3proto;
uint8_t l4proto;
struct ctd_helper *helper;
@@ -99,6 +100,12 @@ enum ip_conntrack_info {
#define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
-#define pr_debug printf
+#if 0
+#define pr_debug(fmt, arg...) \
+ printf(fmt, ##arg)
+#else
+#define pr_debug(fmt, arg...) \
+ ({ if (0) printf(fmt, ##arg); 0; })
+#endif
#endif
diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h
index da44b33..e0d8fd8 100644
--- a/include/linux/netfilter/nfnetlink_queue.h
+++ b/include/linux/netfilter/nfnetlink_queue.h
@@ -80,19 +80,20 @@ struct nfqnl_msg_config_params {
__u8 copy_mode; /* enum nfqnl_config_mode */
} __attribute__ ((packed));
-enum nfqnl_flags {
- NFQNL_F_NONE = 0,
- NFQNL_F_CONNTRACK = (1 << 0),
-};
enum nfqnl_attr_config {
NFQA_CFG_UNSPEC,
NFQA_CFG_CMD, /* nfqnl_msg_config_cmd */
NFQA_CFG_PARAMS, /* nfqnl_msg_config_params */
NFQA_CFG_QUEUE_MAXLEN, /* __u32 */
- NFQA_CFG_FLAGS, /* __u32 */
+ NFQA_CFG_MASK, /* identify which flags to change */
+ NFQA_CFG_FLAGS, /* value of these flags (__u32) */
__NFQA_CFG_MAX
};
#define NFQA_CFG_MAX (__NFQA_CFG_MAX-1)
+/* Flags for NFQA_CFG_FLAGS */
+#define NFQA_CFG_F_FAIL_OPEN (1 << 0)
+#define NFQA_CFG_F_CONNTRACK (1 << 1)
+
#endif /* _NFNETLINK_QUEUE_H */
diff --git a/src/Makefile.am b/src/Makefile.am
index e00d35b..ec03e46 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,8 +9,7 @@ CLEANFILES = read_config_yy.c read_config_lex.c
sbin_PROGRAMS = conntrack conntrackd nfct
conntrack_SOURCES = conntrack.c
-
-conntrack_LDADD = ../extensions/libct_proto_tcp.la ../extensions/libct_proto_udp.la ../extensions/libct_proto_udplite.la ../extensions/libct_proto_icmp.la ../extensions/libct_proto_icmpv6.la ../extensions/libct_proto_sctp.la ../extensions/libct_proto_dccp.la ../extensions/libct_proto_gre.la ../extensions/libct_proto_unknown.la ${LIBNETFILTER_CONNTRACK_LIBS} ${LIBMNL_LIBS}
+conntrack_LDADD = ../extensions/libct_proto_tcp.la ../extensions/libct_proto_udp.la ../extensions/libct_proto_udplite.la ../extensions/libct_proto_icmp.la ../extensions/libct_proto_icmpv6.la ../extensions/libct_proto_sctp.la ../extensions/libct_proto_dccp.la ../extensions/libct_proto_gre.la ../extensions/libct_proto_unknown.la ${LIBNETFILTER_CONNTRACK_LIBS} ${LIBMNL_LIBS} ${LIBNFNETLINK_LIBS}
nfct_SOURCES = nfct.c \
helpers.c \
@@ -47,7 +46,7 @@ read_config_yy.o read_config_lex.o: AM_CFLAGS += -Wno-missing-prototypes -Wno-mi
conntrackd_LDADD = ${LIBMNL_LIBS} ${LIBNETFILTER_CONNTRACK_LIBS} \
${LIBNETFILTER_QUEUE_LIBS} ${LIBNETFILTER_CTHELPER_LIBS} \
- ${libdl_LIBS}
+ ${libdl_LIBS} ${LIBNFNETLINK_LIBS}
conntrackd_LDFLAGS = -export-dynamic
diff --git a/src/build.c b/src/build.c
index f01e7c8..330f057 100644
--- a/src/build.c
+++ b/src/build.c
@@ -360,7 +360,8 @@ void exp2msg(const struct nf_expect *exp, struct nethdr *n)
exp_build_u32(exp, ATTR_EXP_NAT_DIR, n, NTA_EXP_NAT_DIR);
}
- exp_build_str(exp, ATTR_EXP_HELPER_NAME, n, NTA_EXP_HELPER_NAME);
+ if (nfexp_attr_is_set(exp, ATTR_EXP_HELPER_NAME))
+ exp_build_str(exp, ATTR_EXP_HELPER_NAME, n, NTA_EXP_HELPER_NAME);
if (nfexp_attr_is_set(exp, ATTR_EXP_FN))
exp_build_str(exp, ATTR_EXP_FN, n, NTA_EXP_FN);
}
diff --git a/src/conntrack.c b/src/conntrack.c
index ee85022..7451a80 100644
--- a/src/conntrack.c
+++ b/src/conntrack.c
@@ -587,6 +587,8 @@ exit_error(enum exittype status, const char *msg, ...)
va_end(args);
if (status == PARAMETER_PROBLEM)
exit_tryhelp(status);
+ /* release template objects that were allocated in the setup stage. */
+ free_tmpl_objects();
exit(status);
}
@@ -820,45 +822,27 @@ add_command(unsigned int *cmd, const int newcmd)
*cmd |= newcmd;
}
-static char *get_table(int argc, char *argv[])
+static unsigned int
+check_type(int argc, char *argv[])
{
char *table = NULL;
- /* Nasty bug or feature in getopt_long ?
+ /* 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] != '!')
+ else if (optind < argc && argv[optind][0] != '-'
+ && argv[optind][0] != '!')
table = argv[optind++];
-
- return table;
-}
-
-enum {
- CT_TABLE_CONNTRACK,
- CT_TABLE_EXPECT,
- CT_TABLE_DYING,
- CT_TABLE_UNCONFIRMED,
-};
-
-static unsigned int check_type(int argc, char *argv[])
-{
- const char *table = get_table(argc, argv);
-
- /* default to conntrack subsystem if nothing has been specified. */
- if (table == NULL)
- return CT_TABLE_CONNTRACK;
-
+
+ if (!table)
+ return 0;
+
if (strncmp("expect", table, strlen(table)) == 0)
- return CT_TABLE_EXPECT;
+ return 1;
else if (strncmp("conntrack", table, strlen(table)) == 0)
- return CT_TABLE_CONNTRACK;
- else if (strncmp("dying", table, strlen(table)) == 0)
- return CT_TABLE_DYING;
- else if (strncmp("unconfirmed", table, strlen(table)) == 0)
- return CT_TABLE_UNCONFIRMED;
+ return 0;
else
exit_error(PARAMETER_PROBLEM, "unknown type `%s'", table);
@@ -1072,7 +1056,7 @@ filter_nat(const struct nf_conntrack *obj, const struct nf_conntrack *ct)
else if (options & CT_OPT_DST_NAT)
return !has_dstnat;
- return (options & (CT_OPT_SRC_NAT | CT_OPT_DST_NAT)) ? 1 : 0;
+ return 0;
}
static int counter;
@@ -1557,6 +1541,26 @@ nfct_mnl_dump(uint16_t subsys, uint16_t type, mnl_cb_t cb)
return res;
}
+static int
+nfct_mnl_get(uint16_t subsys, uint16_t type, mnl_cb_t cb)
+{
+ char buf[MNL_SOCKET_BUFFER_SIZE];
+ struct nlmsghdr *nlh;
+ int res;
+
+ nlh = nfct_mnl_nlmsghdr_put(buf, subsys, type);
+
+ res = mnl_socket_sendto(sock.mnl, nlh, nlh->nlmsg_len);
+ if (res < 0)
+ return res;
+
+ res = mnl_socket_recvfrom(sock.mnl, buf, sizeof(buf));
+ if (res < 0)
+ return res;
+
+ return mnl_cb_run(buf, res, nlh->nlmsg_seq, sock.portid, cb, NULL);
+}
+
static int nfct_stats_attr_cb(const struct nlattr *attr, void *data)
{
const struct nlattr **tb = data;
@@ -1651,24 +1655,34 @@ static int nfexp_stats_cb(const struct nlmsghdr *nlh, void *data)
return MNL_CB_OK;
}
-static int mnl_nfct_dump_cb(const struct nlmsghdr *nlh, void *data)
+static int nfct_stats_global_attr_cb(const struct nlattr *attr, void *data)
{
- struct nf_conntrack *ct;
- char buf[4096];
+ const struct nlattr **tb = data;
+ int type = mnl_attr_get_type(attr);
- ct = nfct_new();
- if (ct == NULL)
+ if (mnl_attr_type_valid(attr, CTA_STATS_GLOBAL_MAX) < 0)
return MNL_CB_OK;
- nfct_nlmsg_parse(nlh, ct);
+ if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
+ perror("mnl_attr_validate");
+ return MNL_CB_ERROR;
+ }
- nfct_snprintf(buf, sizeof(buf), ct, NFCT_T_UNKNOWN, NFCT_O_DEFAULT, 0);
- printf("%s\n", buf);
+ tb[type] = attr;
+ return MNL_CB_OK;
+}
- nfct_destroy(ct);
+static int nfct_global_stats_cb(const struct nlmsghdr *nlh, void *data)
+{
+ struct nlattr *tb[CTA_STATS_GLOBAL_MAX+1] = {};
+ struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
- counter++;
+ mnl_attr_parse(nlh, sizeof(*nfg), nfct_stats_global_attr_cb, tb);
+ if (tb[CTA_STATS_GLOBAL_ENTRIES]) {
+ printf("%d\n",
+ ntohl(mnl_attr_get_u32(tb[CTA_STATS_GLOBAL_ENTRIES])));
+ }
return MNL_CB_OK;
}
@@ -1706,16 +1720,6 @@ int main(int argc, char *argv[])
switch(c) {
/* commands */
case 'L':
- type = check_type(argc, argv);
- /* Special case: dumping dying and unconfirmed list
- * are handled like normal conntrack dumps.
- */
- if (type == CT_TABLE_DYING ||
- type == CT_TABLE_UNCONFIRMED)
- add_command(&command, cmd2type[c][0]);
- else
- add_command(&command, cmd2type[c][type]);
- break;
case 'I':
case 'D':
case 'G':
@@ -1726,25 +1730,14 @@ int main(int argc, char *argv[])
case 'C':
case 'S':
type = check_type(argc, argv);
- if (type == CT_TABLE_DYING ||
- type == CT_TABLE_UNCONFIRMED) {
- exit_error(PARAMETER_PROBLEM,
- "Can't do that command with "
- "tables `dying' and `unconfirmed'");
- }
add_command(&command, cmd2type[c][type]);
break;
case 'U':
type = check_type(argc, argv);
- if (type == CT_TABLE_DYING ||
- type == CT_TABLE_UNCONFIRMED) {
- exit_error(PARAMETER_PROBLEM,
- "Can't do that command with "
- "tables `dying' and `unconfirmed'");
- } else if (type == CT_TABLE_CONNTRACK)
+ if (type == 0)
add_command(&command, CT_UPDATE);
else
- exit_error(PARAMETER_PROBLEM,
+ exit_error(PARAMETER_PROBLEM,
"Can't update expectations");
break;
/* options */
@@ -1944,28 +1937,6 @@ int main(int argc, char *argv[])
struct nfct_filter_dump *filter_dump;
case CT_LIST:
- if (type == CT_TABLE_DYING) {
- if (nfct_mnl_socket_open() < 0)
- exit_error(OTHER_PROBLEM, "Can't open handler");
-
- res = nfct_mnl_dump(NFNL_SUBSYS_CTNETLINK,
- IPCTNL_MSG_CT_GET_DYING,
- mnl_nfct_dump_cb);
-
- nfct_mnl_socket_close();
- break;
- } else if (type == CT_TABLE_UNCONFIRMED) {
- if (nfct_mnl_socket_open() < 0)
- exit_error(OTHER_PROBLEM, "Can't open handler");
-
- res = nfct_mnl_dump(NFNL_SUBSYS_CTNETLINK,
- IPCTNL_MSG_CT_GET_UNCONFIRMED,
- mnl_nfct_dump_cb);
-
- nfct_mnl_socket_close();
- break;
- }
-
cth = nfct_open(CONNTRACK, 0);
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
@@ -2216,7 +2187,25 @@ int main(int argc, char *argv[])
res = nfexp_catch(cth);
nfct_close(cth);
break;
- case CT_COUNT: {
+ case CT_COUNT:
+ /* If we fail with netlink, fall back to /proc to ensure
+ * backward compatibility.
+ */
+ if (nfct_mnl_socket_open() < 0)
+ goto try_proc_count;
+
+ res = nfct_mnl_get(NFNL_SUBSYS_CTNETLINK,
+ IPCTNL_MSG_CT_GET_STATS,
+ nfct_global_stats_cb);
+
+ nfct_mnl_socket_close();
+
+ /* don't look at /proc, we got the information via ctnetlink */
+ if (res >= 0)
+ break;
+
+try_proc_count:
+ {
#define NF_CONNTRACK_COUNT_PROC "/proc/sys/net/netfilter/nf_conntrack_count"
FILE *fd;
int count;
diff --git a/src/cthelper.c b/src/cthelper.c
index e303558..307be96 100644
--- a/src/cthelper.c
+++ b/src/cthelper.c
@@ -353,8 +353,9 @@ static int cthelper_setup(struct ctd_helper_instance *cur)
nfct_helper_attr_set_u32(t, NFCTH_ATTR_STATUS,
NFCT_HELPER_STATUS_ENABLED);
- dlog(LOG_NOTICE, "configuring helper `%s' with queuenum=%d",
- cur->helper->name, cur->queue_num);
+ dlog(LOG_NOTICE, "configuring helper `%s' with queuenum=%d and "
+ "queuelen=%d", cur->helper->name, cur->queue_num,
+ cur->queue_len);
for (j=0; j<CTD_HELPER_POLICY_MAX; j++) {
struct nfct_helper_policy *p;
@@ -431,7 +432,9 @@ static int cthelper_nfqueue_setup(struct ctd_helper_instance *cur)
nlh = nfq_hdr_put(buf, NFQNL_MSG_CONFIG, cur->queue_num);
nfq_nlmsg_cfg_put_params(nlh, NFQNL_COPY_PACKET, 0xffff);
- mnl_attr_put_u32(nlh, NFQA_CFG_FLAGS, htonl(NFQNL_F_CONNTRACK));
+ mnl_attr_put_u32(nlh, NFQA_CFG_FLAGS, htonl(NFQA_CFG_F_CONNTRACK));
+ mnl_attr_put_u32(nlh, NFQA_CFG_MASK, htonl(0xffffffff));
+ mnl_attr_put_u32(nlh, NFQA_CFG_QUEUE_MAXLEN, htonl(cur->queue_len));
if (mnl_socket_sendto(STATE_CTH(nl), nlh, nlh->nlmsg_len) < 0) {
dlog(LOG_ERR, "failed to send configuration");
diff --git a/src/ctnl.c b/src/ctnl.c
index 107cd5d..bb54727 100644
--- a/src/ctnl.c
+++ b/src/ctnl.c
@@ -164,7 +164,9 @@ static void do_polling_alarm(struct alarm_block *a, void *data)
STATE(mode)->internal->exp.purge();
nl_send_resync(STATE(resync));
- nl_send_expect_resync(STATE(resync));
+ if (CONFIG(flags) & CTD_EXPECT)
+ nl_send_expect_resync(STATE(resync));
+
add_alarm(&STATE(polling_alarm), CONFIG(poll_kernel_secs), 0);
}
diff --git a/src/expect.c b/src/expect.c
index 94c26bc..6069770 100644
--- a/src/expect.c
+++ b/src/expect.c
@@ -177,7 +177,7 @@ static int cthelper_expect_cmd(struct nf_expect *exp, int cmd)
int cthelper_add_expect(struct nf_expect *exp)
{
- return cthelper_expect_cmd(exp, NFCT_Q_CREATE);
+ return cthelper_expect_cmd(exp, NFCT_Q_CREATE_UPDATE);
}
int cthelper_del_expect(struct nf_expect *exp)
diff --git a/src/filter.c b/src/filter.c
index 39dd4ca..02a8078 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -473,7 +473,17 @@ int exp_filter_find(struct exp_filter *f, const struct nf_expect *exp)
return 1;
list_for_each_entry(item, &f->list, head) {
- const char *name = nfexp_get_attr(exp, ATTR_EXP_HELPER_NAME);
+ const char *name;
+
+ if (nfexp_attr_is_set(exp, ATTR_EXP_HELPER_NAME))
+ name = nfexp_get_attr(exp, ATTR_EXP_HELPER_NAME);
+ else {
+ /* No helper name, this is likely to be a kernel older
+ * which does not include the helper name, just skip
+ * this so we don't crash.
+ */
+ return 0;
+ }
/* we allow partial matching to support things like sip-PORT. */
if (strncasecmp(item->helper_name, name,
diff --git a/src/helpers/ftp.c b/src/helpers/ftp.c
index 962020b..2c8dcd6 100644
--- a/src/helpers/ftp.c
+++ b/src/helpers/ftp.c
@@ -346,7 +346,12 @@ static int nf_nat_ftp_fmt_cmd(enum nf_ct_ftp_type type,
port >> 8,
port & 0xFF);
case NF_CT_FTP_EPRT:
- return snprintf(buffer, buflen, "|1|%pI4|%u|", &addr, port);
+ return snprintf(buffer, buflen, "|1|%u.%u.%u.%u|%u|",
+ ((unsigned char *)&addr)[0],
+ ((unsigned char *)&addr)[1],
+ ((unsigned char *)&addr)[2],
+ ((unsigned char *)&addr)[3],
+ port);
case NF_CT_FTP_EPSV:
return snprintf(buffer, buflen, "|||%u|", port);
}
diff --git a/src/nfct-extensions/helper.c b/src/nfct-extensions/helper.c
index e8f85bb..f91fc41 100644
--- a/src/nfct-extensions/helper.c
+++ b/src/nfct-extensions/helper.c
@@ -202,9 +202,7 @@ int nfct_cmd_helper_add(int argc, char *argv[])
return -1;
}
- /* XXX use prefix defined in configure.ac. */
- helper = helper_find("/usr/lib/conntrack-tools",
- argv[3], l4proto, RTLD_LAZY);
+ helper = helper_find(CONNTRACKD_LIB_DIR, argv[3], l4proto, RTLD_LAZY);
if (helper == NULL) {
nfct_perror("that helper is not supported");
return -1;
@@ -558,9 +556,7 @@ int nfct_cmd_helper_disable(int argc, char *argv[])
return -1;
}
- /* XXX use prefix defined in configure.ac. */
- helper = helper_find("/usr/lib/conntrack-tools",
- argv[3], l4proto, RTLD_LAZY);
+ helper = helper_find(CONNTRACKD_LIB_DIR, argv[3], l4proto, RTLD_LAZY);
if (helper == NULL) {
nfct_perror("that helper is not supported");
return -1;
diff --git a/src/parse.c b/src/parse.c
index c3b7f7f..8ce4495 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -19,6 +19,7 @@
#include "network.h"
+#include <stdlib.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
#ifndef ssizeof
diff --git a/src/read_config_lex.l b/src/read_config_lex.l
index 31fa32e..bec2d81 100644
--- a/src/read_config_lex.l
+++ b/src/read_config_lex.l
@@ -144,6 +144,7 @@ notrack [N|n][O|o][T|t][R|r][A|a][C|c][K|k]
"ErrorQueueLength" { return T_ERROR_QUEUE_LENGTH; }
"Helper" { return T_HELPER; }
"QueueNum" { return T_HELPER_QUEUE_NUM; }
+"QueueLen" { return T_HELPER_QUEUE_LEN; }
"Policy" { return T_HELPER_POLICY; }
"ExpectMax" { return T_HELPER_EXPECT_MAX; }
"ExpectTimeout" { return T_HELPER_EXPECT_TIMEOUT; }
diff --git a/src/read_config_yy.y b/src/read_config_yy.y
index 623b79d..72a9654 100644
--- a/src/read_config_yy.y
+++ b/src/read_config_yy.y
@@ -56,6 +56,7 @@ struct stack symbol_stack;
enum {
SYMBOL_HELPER_QUEUE_NUM,
+ SYMBOL_HELPER_QUEUE_LEN,
SYMBOL_HELPER_POLICY_EXPECT_ROOT,
SYMBOL_HELPER_EXPECT_POLICY_LEAF,
};
@@ -86,8 +87,8 @@ enum {
%token T_SCHEDULER T_TYPE T_PRIO T_NETLINK_EVENTS_RELIABLE
%token T_DISABLE_INTERNAL_CACHE T_DISABLE_EXTERNAL_CACHE T_ERROR_QUEUE_LENGTH
%token T_OPTIONS T_TCP_WINDOW_TRACKING T_EXPECT_SYNC
-%token T_HELPER T_HELPER_QUEUE_NUM T_HELPER_POLICY T_HELPER_EXPECT_MAX
-%token T_HELPER_EXPECT_TIMEOUT
+%token T_HELPER T_HELPER_QUEUE_NUM T_HELPER_QUEUE_LEN T_HELPER_POLICY
+%token T_HELPER_EXPECT_TIMEOUT T_HELPER_EXPECT_MAX
%token <string> T_IP T_PATH_VAL
%token <val> T_NUMBER
@@ -1313,25 +1314,6 @@ filter_protocol_item : T_UDP
pent->p_proto);
};
-filter_protocol_item : T_UDP
-{
- struct protoent *pent;
-
- pent = getprotobyname("udp");
- if (pent == NULL) {
- print_err(CTD_CFG_WARN, "getprotobyname() cannot find "
- "protocol `udp' in /etc/protocols");
- break;
- }
- ct_filter_add_proto(STATE(us_filter), pent->p_proto);
-
- __kernel_filter_start();
-
- nfct_filter_add_attr_u32(STATE(filter),
- NFCT_FILTER_L4PROTO,
- pent->p_proto);
-};
-
filter_item : T_ADDRESS T_ACCEPT '{' filter_address_list '}'
{
ct_filter_set_logic(STATE(us_filter),
@@ -1658,6 +1640,13 @@ helper_type: T_TYPE T_STRING T_STRING T_STRING '{' helper_type_list '}'
stack_item_free(e);
break;
}
+ case SYMBOL_HELPER_QUEUE_LEN: {
+ int *qlen = (int *) &e->data;
+
+ helper_inst->queue_len = *qlen;
+ stack_item_free(e);
+ break;
+ }
case SYMBOL_HELPER_POLICY_EXPECT_ROOT: {
struct ctd_helper_policy *pol =
(struct ctd_helper_policy *) &e->data;
@@ -1715,6 +1704,17 @@ helper_type: T_HELPER_QUEUE_NUM T_NUMBER
stack_item_push(&symbol_stack, e);
};
+helper_type: T_HELPER_QUEUE_LEN T_NUMBER
+{
+ int *qlen;
+ struct stack_item *e;
+
+ e = stack_item_alloc(SYMBOL_HELPER_QUEUE_LEN, sizeof(int));
+ qlen = (int *) e->data;
+ *qlen = $2;
+ stack_item_push(&symbol_stack, e);
+};
+
helper_type: T_HELPER_POLICY T_STRING '{' helper_policy_list '}'
{
struct stack_item *e;
diff --git a/tests/conntrackd/cthelper/expect.c b/tests/conntrackd/cthelper/expect.c
index c667293..d1d1d28 100644
--- a/tests/conntrackd/cthelper/expect.c
+++ b/tests/conntrackd/cthelper/expect.c
@@ -25,7 +25,8 @@ cthelper_expect_init(struct nf_expect *exp, struct nf_conntrack *master,
uint32_t class,
union nfct_attr_grp_addr *saddr,
union nfct_attr_grp_addr *daddr,
- uint8_t l4proto, uint16_t *sport, uint16_t *dport)
+ uint8_t l4proto, uint16_t *sport, uint16_t *dport,
+ uint32_t flags)
{
struct nf_conntrack *expected, *mask;
diff --git a/tests/conntrackd/cthelper/main.c b/tests/conntrackd/cthelper/main.c
index f229c5d..7021f00 100755
--- a/tests/conntrackd/cthelper/main.c
+++ b/tests/conntrackd/cthelper/main.c
@@ -119,10 +119,10 @@ cthelper_process_packet(const uint8_t *pkt, uint32_t pktlen,
ct->myct->ct = tmp;
if (pktb_mangled(pktb)) {
- int i;
+ uint32_t i;
uint8_t *data = pktb_network_header(pktb);
- printf("\e[1;31mmangled content: ", pktb_len(pktb));
+ printf("\e[1;31mmangled content: ");
for (i=0; i < pktb_len(pktb); i++)
printf("%c", data[i]);