From 2c5727592110622bc8f00c23990cca281e50fd15 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Tue, 7 Aug 2012 18:20:13 +0200 Subject: [PATCH] nfq: implement "fail-open" support. On linux >= 3.6, you can use the fail-open option on a NFQ queue to have the kernel accept the packet if userspace is not able to keep pace. Please note that the kernel will not trigger an error if the feature is activated in userspace libraries but not available in kernel. This patch implements the option for suricata by adding a nfq.fail-open configuration variable which is desactivated by default. --- configure.ac | 1 + src/source-nfq.c | 30 ++++++++++++++++++++++++++++++ suricata.yaml.in | 3 +++ 3 files changed, 34 insertions(+) diff --git a/configure.ac b/configure.ac index 6c0f4df79a..9a6d13a049 100644 --- a/configure.ac +++ b/configure.ac @@ -553,6 +553,7 @@ AC_INIT(configure.ac) AC_CHECK_LIB(netfilter_queue, nfq_open,, NFQ="no",) AC_CHECK_LIB([netfilter_queue], [nfq_set_queue_maxlen],AC_DEFINE_UNQUOTED([HAVE_NFQ_MAXLEN],[1],[Found queue max length support in netfilter_queue]) ,,[-lnfnetlink]) AC_CHECK_LIB([netfilter_queue], [nfq_set_verdict2],AC_DEFINE_UNQUOTED([HAVE_NFQ_SET_VERDICT2],[1],[Found nfq_set_verdict2 function in netfilter_queue]) ,,[-lnfnetlink]) + AC_CHECK_LIB([netfilter_queue], [nfq_set_queue_flags],AC_DEFINE_UNQUOTED([HAVE_NFQ_SET_QUEUE_FLAGS],[1],[Found nfq_set_queue_flags function in netfilter_queue]) ,,[-lnfnetlink]) # check if the argument to nfq_get_payload is signed or unsigned AC_MSG_CHECKING([for signed nfq_get_payload payload argument]) diff --git a/src/source-nfq.c b/src/source-nfq.c index 9b3018acb6..78b936d45c 100644 --- a/src/source-nfq.c +++ b/src/source-nfq.c @@ -156,11 +156,14 @@ typedef enum NFQMode_ { NFQ_ROUTE_MODE, } NFQMode; +#define NFQ_FLAG_FAIL_OPEN (1 << 0) + typedef struct NFQCnf_ { NFQMode mode; uint32_t mark; uint32_t mask; uint32_t next_queue; + uint32_t flags; } NFQCnf; NFQCnf nfq_config; @@ -208,6 +211,7 @@ void NFQInitConfig(char quiet) { intmax_t value = 0; char* nfq_mode = NULL; + int boolval; SCLogDebug("Initializing NFQ"); @@ -228,6 +232,17 @@ void NFQInitConfig(char quiet) } } + (void)ConfGetBool("nfq.fail-open", (int *)&boolval); + if (boolval) { +#ifdef HAVE_NFQ_SET_QUEUE_FLAGS + SCLogInfo("Enabling fail-open on queue"); + nfq_config.flags |= NFQ_FLAG_FAIL_OPEN; +#else + SCLogError(SC_ERR_NFQ_NOSUPPORT, + "nfq.fail-open set but NFQ library has no support for it."); +#endif + } + if ((ConfGetInt("nfq.repeat-mark", &value)) == 1) { nfq_config.mark = (uint32_t)value; } @@ -497,6 +512,21 @@ TmEcode NFQInitThread(NFQThreadVars *nfq_t, uint32_t queue_maxlen) setsockopt(nfq_q->fd, SOL_NETLINK, NETLINK_NO_ENOBUFS, &opt, sizeof(int)); #endif +#ifdef HAVE_NFQ_SET_QUEUE_FLAGS + if (nfq_config.flags & NFQ_FLAG_FAIL_OPEN) { + uint32_t flags = NFQA_CFG_F_FAIL_OPEN; + uint32_t mask = NFQA_CFG_F_FAIL_OPEN; + int r = nfq_set_queue_flags(nfq_q->qh, mask, flags); + + if (r == -1) { + SCLogWarning(SC_ERR_NFQ_SET_MODE, "can't set fail-open mode: %s", + strerror(errno)); + } else { + SCLogInfo("fail-open mode should be set on queue"); + } + } +#endif + /* set a timeout to the socket so we can check for a signal * in case we don't get packets for a longer period. */ tv.tv_sec = 1; diff --git a/suricata.yaml.in b/suricata.yaml.in index a554a1e8ff..a2ceaba5c7 100644 --- a/suricata.yaml.in +++ b/suricata.yaml.in @@ -189,11 +189,14 @@ magic-file: @e_magic_file@ # this mode, you need to set mode to 'repeat' # If you want packet to be sent to another queue after an ACCEPT decision # set mode to 'route' and set next-queue value. +# On linux >= 3.6, you can set the fail-open option to yes to have the kernel +# accept the packet if suricata is not able to keep pace. nfq: # mode: accept # repeat-mark: 1 # repeat-mask: 1 # route-queue: 2 +# fail-open: yes # af-packet support # Set threads to > 1 to use PACKET_FANOUT support