From ba615ec2d1b256175bbdc7b5f0b09e285e3f2001 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.in | 1 + src/source-nfq.c | 25 +++++++++++++++++++++++++ suricata.yaml.in | 3 +++ 3 files changed, 29 insertions(+) diff --git a/configure.in b/configure.in index 3700df6adf84..4ec3575a3f99 100644 --- a/configure.in +++ b/configure.in @@ -553,6 +553,7 @@ AC_INIT(configure.in) 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 9b3018acb6d9..82842261cab7 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,12 @@ void NFQInitConfig(char quiet) } } + (void)ConfGetBool("nfq.fail-open", (int *)&boolval); + if (boolval) { + SCLogInfo("Enabling fail-open on queue"); + nfq_config.flags |= NFQ_FLAG_FAIL_OPEN; + } + if ((ConfGetInt("nfq.repeat-mark", &value)) == 1) { nfq_config.mark = (uint32_t)value; } @@ -497,6 +507,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 4d3261b20685..cbcd6d0bfd1e 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 use 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