aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/suricata/src/runmode-pfring.c
diff options
context:
space:
mode:
authorAshlee Young <ashlee@onosfw.com>2015-09-09 22:21:41 -0700
committerAshlee Young <ashlee@onosfw.com>2015-09-09 22:21:41 -0700
commit8879b125d26e8db1a5633de5a9c692eb2d1c4f83 (patch)
treec7259d85a991b83dfa85ab2e339360669fc1f58e /framework/src/suricata/src/runmode-pfring.c
parent13d05bc8458758ee39cb829098241e89616717ee (diff)
suricata checkin based on commit id a4bce14770beee46a537eda3c3f6e8e8565d5d0a
Change-Id: I9a214fa0ee95e58fc640e50bd604dac7f42db48f
Diffstat (limited to 'framework/src/suricata/src/runmode-pfring.c')
-rw-r--r--framework/src/suricata/src/runmode-pfring.c521
1 files changed, 521 insertions, 0 deletions
diff --git a/framework/src/suricata/src/runmode-pfring.c b/framework/src/suricata/src/runmode-pfring.c
new file mode 100644
index 00000000..fbbd8c91
--- /dev/null
+++ b/framework/src/suricata/src/runmode-pfring.c
@@ -0,0 +1,521 @@
+/* Copyright (C) 2007-2010 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * 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
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "suricata-common.h"
+#include "tm-threads.h"
+#include "conf.h"
+#include "runmodes.h"
+#include "runmode-pfring.h"
+#include "source-pfring.h"
+#include "output.h"
+
+#include "util-debug.h"
+#include "util-time.h"
+#include "util-cpu.h"
+#include "util-affinity.h"
+#include "util-runmodes.h"
+#include "util-device.h"
+
+static const char *default_mode_autofp = NULL;
+
+
+#define PFRING_CONF_V1 1
+#define PFRING_CONF_V2 2
+
+const char *RunModeIdsPfringGetDefaultMode(void)
+{
+#ifdef HAVE_PFRING
+ return default_mode_autofp;
+#else
+ return NULL;
+#endif
+}
+
+void RunModeIdsPfringRegister(void)
+{
+ default_mode_autofp = "autofp";
+ RunModeRegisterNewRunMode(RUNMODE_PFRING, "autofp",
+ "Multi threaded pfring mode. Packets from "
+ "each flow are assigned to a single detect "
+ "thread, unlike \"pfring_auto\" where packets "
+ "from the same flow can be processed by any "
+ "detect thread",
+ RunModeIdsPfringAutoFp);
+ RunModeRegisterNewRunMode(RUNMODE_PFRING, "single",
+ "Single threaded pfring mode",
+ RunModeIdsPfringSingle);
+ RunModeRegisterNewRunMode(RUNMODE_PFRING, "workers",
+ "Workers pfring mode, each thread does all"
+ " tasks from acquisition to logging",
+ RunModeIdsPfringWorkers);
+ return;
+}
+
+void PfringDerefConfig(void *conf)
+{
+ PfringIfaceConfig *pfp = (PfringIfaceConfig *)conf;
+ if (SC_ATOMIC_SUB(pfp->ref, 1) == 0) {
+ if (pfp->bpf_filter) {
+ SCFree(pfp->bpf_filter);
+ }
+ SCFree(pfp);
+ }
+}
+
+/**
+ * \brief extract information from config file
+ *
+ * The returned structure will be freed by the thread init function.
+ * This is thus necessary to or copy the structure before giving it
+ * to thread or to reparse the file for each thread (and thus have
+ * new structure.
+ *
+ * If old config system is used, then return the smae parameters
+ * value for each interface.
+ *
+ * \return a PfringIfaceConfig corresponding to the interface name
+ */
+void *OldParsePfringConfig(const char *iface)
+{
+ char *threadsstr = NULL;
+ PfringIfaceConfig *pfconf = SCMalloc(sizeof(*pfconf));
+ char *tmpclusterid;
+#ifdef HAVE_PFRING
+ char *tmpctype = NULL;
+ cluster_type default_ctype = CLUSTER_ROUND_ROBIN;
+#endif
+
+ if (unlikely(pfconf == NULL)) {
+ return NULL;
+ }
+
+ if (iface == NULL) {
+ SCFree(pfconf);
+ return NULL;
+ }
+
+ strlcpy(pfconf->iface, iface, sizeof(pfconf->iface));
+ pfconf->threads = 1;
+ pfconf->cluster_id = 1;
+#ifdef HAVE_PFRING
+ pfconf->ctype = default_ctype;
+#endif
+ pfconf->DerefFunc = PfringDerefConfig;
+ pfconf->checksum_mode = CHECKSUM_VALIDATION_AUTO;
+ SC_ATOMIC_INIT(pfconf->ref);
+ (void) SC_ATOMIC_ADD(pfconf->ref, 1);
+
+ /* Find initial node */
+ if (ConfGet("pfring.threads", &threadsstr) != 1) {
+ pfconf->threads = 1;
+ } else {
+ if (threadsstr != NULL) {
+ pfconf->threads = (uint8_t)atoi(threadsstr);
+ }
+ }
+ if (pfconf->threads == 0) {
+ pfconf->threads = 1;
+ }
+
+ SC_ATOMIC_RESET(pfconf->ref);
+ (void) SC_ATOMIC_ADD(pfconf->ref, pfconf->threads);
+
+ if (strncmp(pfconf->iface, "zc", 2) == 0) {
+ SCLogInfo("ZC interface detected, not setting cluster-id");
+ }
+ else if ((pfconf->threads == 1) && (strncmp(pfconf->iface, "dna", 3) == 0)) {
+ SCLogInfo("DNA interface detected, not setting cluster-id");
+ } else if (ConfGet("pfring.cluster-id", &tmpclusterid) != 1) {
+ SCLogError(SC_ERR_INVALID_ARGUMENT,"Could not get cluster-id from config");
+ } else {
+ pfconf->cluster_id = (uint16_t)atoi(tmpclusterid);
+ SCLogDebug("Going to use cluster-id %" PRId32, pfconf->cluster_id);
+ }
+
+#ifdef HAVE_PFRING
+ if (strncmp(pfconf->iface, "zc", 2) == 0) {
+ SCLogInfo("ZC interface detected, not setting cluster type for PF_RING (iface %s)",
+ pfconf->iface);
+ } else if ((pfconf->threads == 1) && (strncmp(pfconf->iface, "dna", 3) == 0)) {
+ SCLogInfo("DNA interface detected, not setting cluster type for PF_RING (iface %s)",
+ pfconf->iface);
+ } else if (ConfGet("pfring.cluster-type", &tmpctype) != 1) {
+ SCLogError(SC_ERR_GET_CLUSTER_TYPE_FAILED,"Could not get cluster-type from config");
+ } else if (strcmp(tmpctype, "cluster_round_robin") == 0) {
+ SCLogInfo("Using round-robin cluster mode for PF_RING (iface %s)",
+ pfconf->iface);
+ pfconf->ctype = (cluster_type)tmpctype;
+ } else if (strcmp(tmpctype, "cluster_flow") == 0) {
+ SCLogInfo("Using flow cluster mode for PF_RING (iface %s)",
+ pfconf->iface);
+ pfconf->ctype = (cluster_type)tmpctype;
+ } else {
+ SCLogError(SC_ERR_INVALID_CLUSTER_TYPE,"invalid cluster-type %s",tmpctype);
+ SCFree(pfconf);
+ return NULL;
+ }
+#endif /* HAVE_PFRING */
+
+ return pfconf;
+}
+
+/**
+ * \brief extract information from config file
+ *
+ * The returned structure will be freed by the thread init function.
+ * This is thus necessary to or copy the structure before giving it
+ * to thread or to reparse the file for each thread (and thus have
+ * new structure.
+ *
+ * If old config system is used, then return the smae parameters
+ * value for each interface.
+ *
+ * \return a PfringIfaceConfig corresponding to the interface name
+ */
+void *ParsePfringConfig(const char *iface)
+{
+ char *threadsstr = NULL;
+ ConfNode *if_root;
+ ConfNode *if_default = NULL;
+ ConfNode *pf_ring_node;
+ PfringIfaceConfig *pfconf = SCMalloc(sizeof(*pfconf));
+ char *tmpclusterid;
+ char *tmpctype = NULL;
+#ifdef HAVE_PFRING
+ cluster_type default_ctype = CLUSTER_ROUND_ROBIN;
+ int getctype = 0;
+#endif
+ char *bpf_filter = NULL;
+
+ if (unlikely(pfconf == NULL)) {
+ return NULL;
+ }
+
+ if (iface == NULL) {
+ SCFree(pfconf);
+ return NULL;
+ }
+
+ memset(pfconf, 0, sizeof(PfringIfaceConfig));
+ strlcpy(pfconf->iface, iface, sizeof(pfconf->iface));
+ pfconf->threads = 1;
+ pfconf->cluster_id = 1;
+#ifdef HAVE_PFRING
+ pfconf->ctype = (cluster_type)default_ctype;
+#endif
+ pfconf->DerefFunc = PfringDerefConfig;
+ SC_ATOMIC_INIT(pfconf->ref);
+ (void) SC_ATOMIC_ADD(pfconf->ref, 1);
+
+ /* Find initial node */
+ pf_ring_node = ConfGetNode("pfring");
+ if (pf_ring_node == NULL) {
+ SCLogInfo("Unable to find pfring config using default value");
+ return pfconf;
+ }
+
+ if_root = ConfNodeLookupKeyValue(pf_ring_node, "interface", iface);
+
+ if_default = ConfNodeLookupKeyValue(pf_ring_node, "interface", "default");
+
+ if (if_root == NULL && if_default == NULL) {
+ SCLogInfo("Unable to find pfring config for "
+ "interface %s, using default value or 1.0 "
+ "configuration system. ",
+ iface);
+ return pfconf;
+ }
+
+ /* If there is no setting for current interface use default one as main iface */
+ if (if_root == NULL) {
+ if_root = if_default;
+ if_default = NULL;
+ }
+
+ if (ConfGetChildValueWithDefault(if_root, if_default, "threads", &threadsstr) != 1) {
+ pfconf->threads = 1;
+ } else {
+ if (threadsstr != NULL) {
+ pfconf->threads = (uint8_t)atoi(threadsstr);
+ }
+ }
+ if (pfconf->threads == 0) {
+ pfconf->threads = 1;
+ }
+
+ SC_ATOMIC_RESET(pfconf->ref);
+ (void) SC_ATOMIC_ADD(pfconf->ref, pfconf->threads);
+
+ /* command line value has precedence */
+ if (ConfGet("pfring.cluster-id", &tmpclusterid) == 1) {
+ pfconf->cluster_id = (uint16_t)atoi(tmpclusterid);
+ SCLogDebug("Going to use command-line provided cluster-id %" PRId32,
+ pfconf->cluster_id);
+ } else {
+
+ if (strncmp(pfconf->iface, "zc", 2) == 0) {
+ SCLogInfo("ZC interface detected, not setting cluster-id for PF_RING (iface %s)",
+ pfconf->iface);
+ } else if ((pfconf->threads == 1) && (strncmp(pfconf->iface, "dna", 3) == 0)) {
+ SCLogInfo("DNA interface detected, not setting cluster-id for PF_RING (iface %s)",
+ pfconf->iface);
+ } else if (ConfGetChildValueWithDefault(if_root, if_default, "cluster-id", &tmpclusterid) != 1) {
+ SCLogError(SC_ERR_INVALID_ARGUMENT,
+ "Could not get cluster-id from config");
+ } else {
+ pfconf->cluster_id = (uint16_t)atoi(tmpclusterid);
+ SCLogDebug("Going to use cluster-id %" PRId32, pfconf->cluster_id);
+ }
+ }
+
+ /*load pfring bpf filter*/
+ /* command line value has precedence */
+ if (ConfGet("bpf-filter", &bpf_filter) == 1) {
+ if (strlen(bpf_filter) > 0) {
+ pfconf->bpf_filter = SCStrdup(bpf_filter);
+ if (unlikely(pfconf->bpf_filter == NULL)) {
+ SCLogError(SC_ERR_MEM_ALLOC,
+ "Can't allocate BPF filter string");
+ } else {
+ SCLogDebug("Going to use command-line provided bpf filter %s",
+ pfconf->bpf_filter);
+ }
+ }
+ } else {
+ if (ConfGetChildValueWithDefault(if_root, if_default, "bpf-filter", &bpf_filter) == 1) {
+ if (strlen(bpf_filter) > 0) {
+ pfconf->bpf_filter = SCStrdup(bpf_filter);
+ if (unlikely(pfconf->bpf_filter == NULL)) {
+ SCLogError(SC_ERR_MEM_ALLOC,
+ "Can't allocate BPF filter string");
+ } else {
+ SCLogDebug("Going to use bpf filter %s",
+ pfconf->bpf_filter);
+ }
+ }
+ }
+ }
+
+#ifdef HAVE_PFRING
+ if (ConfGet("pfring.cluster-type", &tmpctype) == 1) {
+ SCLogDebug("Going to use command-line provided cluster-type");
+ getctype = 1;
+ } else {
+ if (strncmp(pfconf->iface, "zc", 2) == 0) {
+ SCLogInfo("ZC interface detected, not setting cluster type for PF_RING (iface %s)",
+ pfconf->iface);
+ } else if ((pfconf->threads == 1) && (strncmp(pfconf->iface, "dna", 3) == 0)) {
+ SCLogInfo("DNA interface detected, not setting cluster type for PF_RING (iface %s)",
+ pfconf->iface);
+ } else if (ConfGetChildValueWithDefault(if_root, if_default, "cluster-type", &tmpctype) != 1) {
+ SCLogError(SC_ERR_GET_CLUSTER_TYPE_FAILED,
+ "Could not get cluster-type from config");
+ } else {
+ getctype = 1;
+ }
+ }
+
+ if (getctype) {
+ if (strcmp(tmpctype, "cluster_round_robin") == 0) {
+ SCLogInfo("Using round-robin cluster mode for PF_RING (iface %s)",
+ pfconf->iface);
+ pfconf->ctype = CLUSTER_ROUND_ROBIN;
+ } else if (strcmp(tmpctype, "cluster_flow") == 0) {
+ SCLogInfo("Using flow cluster mode for PF_RING (iface %s)",
+ pfconf->iface);
+ pfconf->ctype = CLUSTER_FLOW;
+ } else {
+ SCLogError(SC_ERR_INVALID_CLUSTER_TYPE,
+ "invalid cluster-type %s",
+ tmpctype);
+ SCFree(pfconf);
+ return NULL;
+ }
+ }
+#endif /* HAVE_PFRING */
+ if (ConfGetChildValueWithDefault(if_root, if_default, "checksum-checks", &tmpctype) == 1) {
+ if (strcmp(tmpctype, "auto") == 0) {
+ pfconf->checksum_mode = CHECKSUM_VALIDATION_AUTO;
+ } else if (strcmp(tmpctype, "yes") == 0) {
+ pfconf->checksum_mode = CHECKSUM_VALIDATION_ENABLE;
+ } else if (strcmp(tmpctype, "no") == 0) {
+ pfconf->checksum_mode = CHECKSUM_VALIDATION_DISABLE;
+ } else if (strcmp(tmpctype, "rx-only") == 0) {
+ pfconf->checksum_mode = CHECKSUM_VALIDATION_RXONLY;
+ } else {
+ SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid value for checksum-checks for %s", pfconf->iface);
+ }
+ }
+
+ return pfconf;
+}
+
+int PfringConfigGeThreadsCount(void *conf)
+{
+ PfringIfaceConfig *pfp = (PfringIfaceConfig *)conf;
+ return pfp->threads;
+}
+
+int PfringConfLevel()
+{
+ char *def_dev;
+ /* 1.0 config should return a string */
+ if (ConfGet("pfring.interface", &def_dev) != 1) {
+ return PFRING_CONF_V2;
+ } else {
+ return PFRING_CONF_V1;
+ }
+ return PFRING_CONF_V2;
+}
+
+#ifdef HAVE_PFRING
+static int GetDevAndParser(char **live_dev, ConfigIfaceParserFunc *parser)
+{
+ ConfGet("pfring.live-interface", live_dev);
+
+ /* determine which config type we have */
+ if (PfringConfLevel() > PFRING_CONF_V1) {
+ *parser = ParsePfringConfig;
+ } else {
+ SCLogInfo("Using 1.0 style configuration for pfring");
+ *parser = OldParsePfringConfig;
+ /* In v1: try to get interface name from config */
+ if (*live_dev == NULL) {
+ if (ConfGet("pfring.interface", live_dev) == 1) {
+ SCLogInfo("Using interface %s", *live_dev);
+ LiveRegisterDevice(*live_dev);
+ } else {
+ SCLogInfo("No interface found, problem incoming");
+ *live_dev = NULL;
+ }
+ }
+ }
+
+ return 0;
+}
+#endif
+
+int RunModeIdsPfringAutoFp(void)
+{
+ SCEnter();
+
+/* We include only if pfring is enabled */
+#ifdef HAVE_PFRING
+ int ret;
+ char *live_dev = NULL;
+ ConfigIfaceParserFunc tparser;
+
+ RunModeInitialize();
+
+ TimeModeSetLive();
+
+ ret = GetDevAndParser(&live_dev, &tparser);
+ if (ret != 0) {
+ SCLogError(SC_ERR_MISSING_CONFIG_PARAM,
+ "Unable to get parser and interface params");
+ exit(EXIT_FAILURE);
+ }
+
+ ret = RunModeSetLiveCaptureAutoFp(tparser,
+ PfringConfigGeThreadsCount,
+ "ReceivePfring",
+ "DecodePfring", "RxPFR",
+ live_dev);
+ if (ret != 0) {
+ SCLogError(SC_ERR_RUNMODE, "Runmode start failed");
+ exit(EXIT_FAILURE);
+ }
+
+ SCLogInfo("RunModeIdsPfringAutoFp initialised");
+#endif /* HAVE_PFRING */
+
+ return 0;
+}
+
+int RunModeIdsPfringSingle(void)
+{
+ SCEnter();
+
+/* We include only if pfring is enabled */
+#ifdef HAVE_PFRING
+ int ret;
+ char *live_dev = NULL;
+ ConfigIfaceParserFunc tparser;
+
+ RunModeInitialize();
+
+ TimeModeSetLive();
+
+ ret = GetDevAndParser(&live_dev, &tparser);
+ if (ret != 0) {
+ SCLogError(SC_ERR_MISSING_CONFIG_PARAM,
+ "Unable to get parser and interface params");
+ exit(EXIT_FAILURE);
+ }
+
+ ret = RunModeSetLiveCaptureSingle(tparser,
+ PfringConfigGeThreadsCount,
+ "ReceivePfring",
+ "DecodePfring", "RxPFR",
+ live_dev);
+ if (ret != 0) {
+ SCLogError(SC_ERR_RUNMODE, "Runmode start failed");
+ exit(EXIT_FAILURE);
+ }
+
+ SCLogInfo("RunModeIdsPfringSingle initialised");
+#endif /* HAVE_PFRING */
+
+ return 0;
+}
+
+int RunModeIdsPfringWorkers(void)
+{
+ SCEnter();
+
+/* We include only if pfring is enabled */
+#ifdef HAVE_PFRING
+ int ret;
+ char *live_dev = NULL;
+ ConfigIfaceParserFunc tparser;
+
+ RunModeInitialize();
+
+ TimeModeSetLive();
+
+ ret = GetDevAndParser(&live_dev, &tparser);
+ if (ret != 0) {
+ SCLogError(SC_ERR_MISSING_CONFIG_PARAM,
+ "Unable to get parser and interface params");
+ exit(EXIT_FAILURE);
+ }
+
+ ret = RunModeSetLiveCaptureWorkers(tparser,
+ PfringConfigGeThreadsCount,
+ "ReceivePfring",
+ "DecodePfring", "RxPFR",
+ live_dev);
+ if (ret != 0) {
+ SCLogError(SC_ERR_RUNMODE, "Runmode start failed");
+ exit(EXIT_FAILURE);
+ }
+
+ SCLogInfo("RunModeIdsPfringWorkers initialised");
+#endif /* HAVE_PFRING */
+
+ return 0;
+}