diff options
-rw-r--r-- | Make_global.am | 4 | ||||
-rw-r--r-- | configure.ac | 13 | ||||
-rw-r--r-- | doc/helper/conntrackd.conf | 13 | ||||
-rw-r--r-- | doc/manual/conntrack-tools.tmpl | 166 | ||||
-rw-r--r-- | doc/sync/alarm/conntrackd.conf | 3 | ||||
-rw-r--r-- | doc/sync/ftfw/conntrackd.conf | 3 | ||||
-rw-r--r-- | doc/sync/notrack/conntrackd.conf | 3 | ||||
-rw-r--r-- | include/helper.h | 9 | ||||
-rw-r--r-- | include/linux/netfilter/nfnetlink_queue.h | 11 | ||||
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/build.c | 3 | ||||
-rw-r--r-- | src/conntrack.c | 161 | ||||
-rw-r--r-- | src/cthelper.c | 9 | ||||
-rw-r--r-- | src/ctnl.c | 4 | ||||
-rw-r--r-- | src/expect.c | 2 | ||||
-rw-r--r-- | src/filter.c | 12 | ||||
-rw-r--r-- | src/helpers/ftp.c | 7 | ||||
-rw-r--r-- | src/nfct-extensions/helper.c | 8 | ||||
-rw-r--r-- | src/parse.c | 1 | ||||
-rw-r--r-- | src/read_config_lex.l | 1 | ||||
-rw-r--r-- | src/read_config_yy.y | 42 | ||||
-rw-r--r-- | tests/conntrackd/cthelper/expect.c | 3 | ||||
-rwxr-xr-x | tests/conntrackd/cthelper/main.c | 4 |
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> - >= 1.0.0. This document will evolve in the future to cover new features + >= 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 >= 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 >= 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"); @@ -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]); |