]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
DAQng: Port Snort and its DAQ modules to DAQ3
authorMichael Altizer <mialtize@cisco.com>
Fri, 31 Aug 2018 18:40:41 +0000 (14:40 -0400)
committerMichael Altizer <mialtize@cisco.com>
Sun, 5 May 2019 16:02:46 +0000 (12:02 -0400)
- Massive refactoring of the Analyzer thread
- Handle multiple offloaded wire packets
- Port hext and file DAQ modules to DAQng
- Reimplement the RETRY verdict internal to Snort
- Revamp skip-n/exit-after-n/pause-after-n handling
- Update lua tweaks with new DAQ configuration format
- Update sfdaq unit tests for DAQng
- Update snort2lua to convert to new DAQ configuration

95 files changed:
CMakeLists.txt
cmake/FindDAQ.cmake
daqs/daq_file.c
daqs/daq_hext.c
daqs/daq_user.h
lua/inline.lua
lua/talos.lua
src/CMakeLists.txt
src/codecs/ip/cd_ipv4.cc
src/codecs/ip/cd_ipv6.cc
src/codecs/misc/cd_user.cc
src/codecs/root/cd_eth.cc
src/codecs/root/cd_raw.cc
src/detection/context_switcher.cc
src/detection/detection_engine.cc
src/detection/detection_engine.h
src/detection/detection_util.cc
src/detection/ips_context.h
src/detection/tag.cc
src/file_api/file_cache.cc
src/flow/expect_cache.cc
src/framework/codec.h
src/helpers/process.cc
src/log/log_text.cc
src/loggers/alert_csv.cc
src/loggers/alert_fast.cc
src/loggers/alert_full.cc
src/loggers/alert_json.cc
src/loggers/alert_syslog.cc
src/loggers/alert_talos.cc
src/loggers/alert_unixsock.cc
src/loggers/log_hext.cc
src/loggers/log_pcap.cc
src/loggers/unified2.cc
src/main.cc
src/main/CMakeLists.txt
src/main/analyzer.cc
src/main/analyzer.h
src/main/analyzer_command.cc
src/main/analyzer_command.h
src/main/help.cc
src/main/modules.cc [changed mode: 0755->0644]
src/main/oops_handler.cc [new file with mode: 0644]
src/main/oops_handler.h [new file with mode: 0644]
src/main/snort.cc
src/main/snort.h
src/main/snort_config.cc
src/main/snort_module.cc
src/main/swapper.cc
src/main/swapper.h
src/managers/action_manager.cc
src/network_inspectors/packet_capture/packet_capture.cc
src/network_inspectors/packet_tracer/packet_tracer.cc
src/network_inspectors/packet_tracer/packet_tracer.h
src/network_inspectors/perf_monitor/flow_ip_tracker.cc
src/network_inspectors/perf_monitor/flow_tracker.cc
src/packet_io/CMakeLists.txt
src/packet_io/active.cc
src/packet_io/active.h
src/packet_io/sfdaq.cc
src/packet_io/sfdaq.h
src/packet_io/sfdaq_config.cc
src/packet_io/sfdaq_config.h
src/packet_io/sfdaq_instance.cc [new file with mode: 0644]
src/packet_io/sfdaq_instance.h [new file with mode: 0644]
src/packet_io/sfdaq_module.cc
src/packet_io/sfdaq_module.h
src/packet_io/sfdaq_static_modules.h.in [new file with mode: 0644]
src/packet_io/test/sfdaq_module_test.cc
src/parser/config_file.cc
src/piglet_plugins/pp_codec_iface.cc
src/piglet_plugins/pp_daq_pkthdr_iface.cc
src/piglet_plugins/pp_daq_pkthdr_iface.h
src/piglet_plugins/pp_raw_buffer_iface.h
src/protocols/packet.h
src/protocols/packet_manager.cc
src/protocols/packet_manager.h
src/service_inspectors/dce_rpc/dce_smb_utils.cc
src/stream/file/file_session.cc
src/stream/ip/ip_defrag.cc
src/stream/tcp/segment_overlap_editor.cc
src/stream/tcp/tcp_normalizer.cc
src/stream/tcp/tcp_reassembler.cc
src/stream/user/user_session.cc
src/time/packet_time.cc
src/utils/stats.h
src/utils/util.cc
tools/snort2lua/config_states/CMakeLists.txt
tools/snort2lua/config_states/config_daq.cc [new file with mode: 0644]
tools/snort2lua/config_states/config_daq_mode.cc [new file with mode: 0644]
tools/snort2lua/config_states/config_daq_var.cc [new file with mode: 0644]
tools/snort2lua/config_states/config_deleted.cc
tools/snort2lua/config_states/config_no_option.cc
tools/snort2lua/config_states/config_one_string_option.cc
tools/snort2lua/data/data_types/dt_table.cc

index 8ba889448a5f3d57d74065e0d23496eb11c92a07..5be70a6262e22a2c3b6860fc6749bbdf86e88f5b 100644 (file)
@@ -93,6 +93,14 @@ Compiler options:
 Feature options:\
 ")
 
+if (ENABLE_STATIC_DAQ)
+    message("\
+    DAQ Modules:    Static (${DAQ_STATIC_MODULES})")
+else ()
+    message("\
+    DAQ Modules:    Dynamic")
+endif ()
+
 if (HAVE_FLATBUFFERS)
     message("\
     Flatbuffers:    ON")
index 7ff9df97dcaf514e7dde5cc6d5fb40e5cda4b0c4..357037c149d050aee927b9fa0426338238a91ea9 100644 (file)
@@ -1,65 +1,70 @@
-#
-#  Locate DAQ library
-#  This module defines
-#  DAQ_FOUND, if false, do not try to link to Lua
-# 
-#  DAQ_FOUND - system has libdaq
-#  DAQ_INCLUDE_DIR - the libdaq include directory
-#  DAQ_LIBRARIES - the libraries needed to use libdaq
-#
+#[=======================================================================[.rst:
+FindDAQ
+-------
 
-set (ERROR_MESSAGE 
-    "
-    ERROR! Cannot find LibDAQ.  Go get it from 
-    http://snort.org/snort-downloads or use the --with-daq-*
-    options if you have it installed in an unusual place.\n\n"
-)
+Locate LibDAQ include paths and library as well as static DAQ module libraries
 
-find_path(DAQ_INCLUDE_DIR
-    NAMES daq.h
-    HINTS ${DAQ_INCLUDE_DIR_HINT}
-    NO_SYSTEM_ENVIRONMENT_PATH
-)
+This module defines:
 
-# find any static libraries
-if (ENABLE_STATIC_DAQ)
-    execute_process(
-        COMMAND daq-modules-config --static --libs
-        OUTPUT_VARIABLE DAQ_STATIC_LIBRARIES
-        RESULT_VARIABLE result
-        OUTPUT_STRIP_TRAILING_WHITESPACE
-    )
+::
 
-    # This will be false if the exit status was 0 and true if the binary was not found
-    if (result)
-        message(SEND_ERROR 
-        "
-        ERROR! Cannot find LibDAQ's static libraries!  Make sure the binary
-        file `daq-modules-config` is in your path.\n\n")
-    endif()
+  DAQ_FOUND - system has libdaq
+  DAQ_INCLUDE_DIR - the libdaq include directory
+  DAQ_LIBRARIES - the libraries needed to use libdaq
+  DAQ_STATIC_MODULES - the static DAQ modules available
+  DAQ_STATIC_MODULE_LIBS - the set of additional libraries required by the available static DAQ modules
+#]=======================================================================]
 
-    set(DAQ_LIB daq_static)
-else()
-    set(DAQ_LIB daq)
-    set(DAQ_STATIC_LIBRARIES)
-endif()
+find_package(PkgConfig)
+pkg_check_modules(PC_DAQ libdaq>=3.0.0)
 
-find_library(DAQ_LIBRARY
-    NAMES ${DAQ_LIB}
-    HINTS ${DAQ_LIBRARIES_DIR_HINT}     # user-specified path in ./configure_cmake.sh
-    DOC "DAQ library directory"
+# Use DAQ_INCLUDE_DIR_HINT and DAQ_LIBRARIES_DIR_HINT from configure_cmake.sh as primary hints
+# and then package config information after that.
+find_path(DAQ_INCLUDE_DIR
+    NAMES daq.h
+    HINTS ${DAQ_INCLUDE_DIR_HINT} ${PC_DAQ_INCLUDEDIR} ${PC_DAQ_INCLUDE_DIRS}
+    NO_SYSTEM_ENVIRONMENT_PATH
+)
+find_library(DAQ_LIBRARIES
+    NAMES daq
+    HINTS ${DAQ_LIBRARIES_DIR_HINT} ${PC_DAQ_LIBDIR} ${PC_DAQ_LIBRARY_DIRS}
 )
-
-set(DAQ_LIBRARIES ${DAQ_LIBRARY} ${DAQ_STATIC_LIBRARIES})
 
 include(FindPackageHandleStandardArgs)
 find_package_handle_standard_args(DAQ
-    REQUIRED_VARS DAQ_LIBRARY DAQ_LIBRARIES DAQ_INCLUDE_DIR
+    REQUIRED_VARS DAQ_LIBRARIES DAQ_INCLUDE_DIR
     FAIL_MESSAGE "${ERROR_MESSAGE}"
 )
 
 mark_as_advanced(
     DAQ_INCLUDE_DIR
-    DAQ_LIBRARY 
     DAQ_LIBRARIES 
 )
+
+if (PKG_CONFIG_EXECUTABLE AND ENABLE_STATIC_DAQ)
+    execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --list-all
+                    OUTPUT_VARIABLE _pkgconfig_list_result
+                    OUTPUT_STRIP_TRAILING_WHITESPACE)
+    string(REGEX MATCHALL "libdaq_static_[^ ]+" AVAILABLE_STATIC_MODULES ${_pkgconfig_list_result})
+    list(REMOVE_DUPLICATES AVAILABLE_STATIC_MODULES)
+    foreach (STATIC_MODULE IN LISTS AVAILABLE_STATIC_MODULES)
+        string(REGEX REPLACE "^libdaq_static_" "" MODULE_NAME ${STATIC_MODULE})
+        list(APPEND DAQ_STATIC_MODULES ${MODULE_NAME})
+        pkg_check_modules(PC_${STATIC_MODULE} ${STATIC_MODULE})
+        foreach (STATIC_MODULE_LIBNAME IN LISTS PC_${STATIC_MODULE}_LIBRARIES)
+            find_library(STATIC_MODULE_LIB
+                NAMES ${STATIC_MODULE_LIBNAME}
+                HINTS ${PC_${STATIC_MODULE}_LIBRARY_DIRS})
+            if (STATIC_MODULE_LIB)
+                list(APPEND DAQ_STATIC_MODULE_LIBS ${STATIC_MODULE_LIB})
+                unset(STATIC_MODULE_LIB CACHE)
+            endif()
+        endforeach()
+    endforeach()
+    if (DAQ_STATIC_MODULE_LIBS)
+        list(REMOVE_DUPLICATES DAQ_STATIC_MODULE_LIBS)
+    endif()
+    if (DAQ_STATIC_MODULES)
+        list(SORT DAQ_STATIC_MODULES)
+    endif()
+endif()
index 6fe158653bd1c8c793f8213eb3dfd5e0268162a1..dbbd3ec5a54fc24c643090c7feed4963c476fc0a 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <daq_api.h>
-#include <sfbpf_dlt.h>
+#include <daq_module_api.h>
 
 #define DAQ_MOD_VERSION 0
 #define DAQ_NAME "file"
 #define DAQ_TYPE (DAQ_TYPE_FILE_CAPABLE|DAQ_TYPE_INTF_CAPABLE|DAQ_TYPE_MULTI_INSTANCE)
+
+#define FILE_DEFAULT_POOL_SIZE 16
 #define FILE_BUF_SZ 16384
 
-typedef struct {
-    char* name;
-    int fid;
+#define SET_ERROR(modinst, ...)    daq_base_api.set_errbuf(modinst, __VA_ARGS__)
+
+typedef struct _file_msg_desc
+{
+    DAQ_Msg_t msg;
+    DAQ_PktHdr_t pkthdr;
+    DAQ_UsrHdr_t pci;
+    uint8_t* data;
+    struct _file_msg_desc* next;
+} FileMsgDesc;
 
-    int start;
-    int stop;
-    int eof;
+typedef struct
+{
+    FileMsgDesc* pool;
+    FileMsgDesc* freelist;
+    DAQ_MsgPoolInfo_t info;
+} FileMsgPool;
 
+typedef struct
+{
+    /* Configuration */
+    char* filename;
     unsigned snaplen;
 
-    uint8_t* buf;
-    char error[DAQ_ERRBUF_SIZE];
+    /* State */
+    DAQ_ModuleInstance_h modinst;
+    FileMsgPool pool;
+    int fid;
+    volatile bool interrupted;
+
+    bool sof;
+    bool eof;
 
     DAQ_UsrHdr_t pci;
-    DAQ_State state;
     DAQ_Stats_t stats;
-} FileImpl;
+} FileContext;
+
+static DAQ_BaseAPI_t daq_base_api;
+
+//-------------------------------------------------------------------------
+// utility functions
+//-------------------------------------------------------------------------
+
+static void destroy_message_pool(FileContext* fc)
+{
+    FileMsgPool* pool = &fc->pool;
+    if (pool->pool)
+    {
+        while (pool->info.size > 0)
+            free(pool->pool[--pool->info.size].data);
+        free(pool->pool);
+        pool->pool = NULL;
+    }
+    pool->freelist = NULL;
+    pool->info.available = 0;
+    pool->info.mem_size = 0;
+}
+
+static int create_message_pool(FileContext* fc, unsigned size)
+{
+    FileMsgPool* pool = &fc->pool;
+    pool->pool = calloc(sizeof(FileMsgDesc), size);
+    if (!pool->pool)
+    {
+        SET_ERROR(fc->modinst, "%s: Could not allocate %zu bytes for a packet descriptor pool!",
+                __func__, sizeof(FileMsgDesc) * size);
+        return DAQ_ERROR_NOMEM;
+    }
+    pool->info.mem_size = sizeof(FileMsgDesc) * size;
+    while (pool->info.size < size)
+    {
+        /* Allocate packet data and set up descriptor */
+        FileMsgDesc *desc = &pool->pool[pool->info.size];
+        desc->data = malloc(fc->snaplen);
+        if (!desc->data)
+        {
+            SET_ERROR(fc->modinst, "%s: Could not allocate %d bytes for a packet descriptor message buffer!",
+                    __func__, fc->snaplen);
+            return DAQ_ERROR_NOMEM;
+        }
+        pool->info.mem_size += fc->snaplen;
+
+        /* Initialize non-zero invariant packet header fields. */
+        DAQ_PktHdr_t *pkthdr = &desc->pkthdr;
+        pkthdr->address_space_id = 0;
+        pkthdr->ingress_index = DAQ_PKTHDR_UNKNOWN;
+        pkthdr->ingress_group = DAQ_PKTHDR_UNKNOWN;
+        pkthdr->egress_index = DAQ_PKTHDR_UNKNOWN;
+        pkthdr->egress_group = DAQ_PKTHDR_UNKNOWN;
+        pkthdr->flags = 0;
+
+        /* Initialize non-zero invariant message header fields. */
+        DAQ_Msg_t *msg = &desc->msg;
+        msg->owner = fc->modinst;
+        msg->priv = desc;
+
+        /* Place it on the free list */
+        desc->next = pool->freelist;
+        pool->freelist = desc;
+
+        pool->info.size++;
+    }
+    pool->info.available = pool->info.size;
+    return DAQ_SUCCESS;
+}
 
 //-------------------------------------------------------------------------
 // file functions
 //-------------------------------------------------------------------------
 
-static int file_setup(FileImpl* impl)
+static int file_setup(FileContext* fc)
 {
-    if ( !strcmp(impl->name, "tty") )
+    if ( !strcmp(fc->filename, "tty") )
     {
-        impl->fid = STDIN_FILENO;
+        fc->fid = STDIN_FILENO;
     }
-    else if ( (impl->fid = open(impl->name, O_RDONLY|O_NONBLOCK)) < 0 )
+    else if ( (fc->fid = open(fc->filename, O_RDONLY|O_NONBLOCK)) < 0 )
     {
         char error_msg[1024] = {0};
         if (strerror_r(errno, error_msg, sizeof(error_msg)) == 0)
-            DPE(impl->error, "%s: can't open file (%s)\n", DAQ_NAME, error_msg);
+            SET_ERROR(fc->modinst, "%s: can't open file (%s)", DAQ_NAME, error_msg);
         else
-            DPE(impl->error, "%s: can't open file: %d\n", DAQ_NAME, errno);
+            SET_ERROR(fc->modinst, "%s: can't open file: %d", DAQ_NAME, errno);
         return -1;
     }
-    impl->start = 1;
+
+    fc->sof = true;
+    fc->eof = false;
 
     return 0;
 }
 
-static void file_cleanup(FileImpl* impl)
+static void file_cleanup(FileContext* fc)
 {
-    if ( impl->fid > STDIN_FILENO )
-        close(impl->fid);
+    if ( fc->fid > STDIN_FILENO )
+        close(fc->fid);
 
-    impl->fid = -1;
-}
-
-static int file_read(FileImpl* impl)
-{
-    int n = read(impl->fid, impl->buf, impl->snaplen);
-
-    if ( !n )
-    {
-        if ( !impl->eof )
-        {
-            impl->eof = 1;
-            return 1;  // <= zero won't make it :(
-        }
-        return DAQ_READFILE_EOF;
-    }
-
-    if ( n < 0 )
-    {
-        if (errno != EINTR)
-        {
-            char error_msg[1024] = {0};
-            if (strerror_r(errno, error_msg, sizeof(error_msg)) == 0)
-                DPE(impl->error, "%s: can't read from file (%s)\n",
-                    DAQ_NAME, error_msg);
-            else
-                DPE(impl->error, "%s: can't read from file: %d\n",
-                    DAQ_NAME, errno);
-        }
-        return DAQ_ERROR;
-    }
-    return n;
+    fc->fid = -1;
 }
 
 //-------------------------------------------------------------------------
 // daq utilities
 //-------------------------------------------------------------------------
 
-static void set_pkt_hdr(FileImpl* impl, DAQ_PktHdr_t* phdr, ssize_t len)
+static void init_packet_message(FileContext* fc, FileMsgDesc* desc)
 {
-    struct timeval t;
-    gettimeofday(&t, NULL);
+    DAQ_PktHdr_t *pkthdr = &desc->pkthdr;
 
-    phdr->ts.tv_sec = t.tv_sec;
-    phdr->ts.tv_usec = t.tv_usec;
-    phdr->caplen = phdr->pktlen = len;
+    desc->msg.type = DAQ_MSG_TYPE_PACKET;
+    desc->msg.hdr_len = sizeof(*pkthdr);
+    desc->msg.hdr = pkthdr;
+    desc->msg.data_len = 0;
+    desc->msg.data = desc->data;
 
-    phdr->ingress_index = phdr->egress_index = -1;
-    phdr->ingress_group = phdr->egress_group = -1;
+    struct timeval t;
+    gettimeofday(&t, NULL);
 
-    phdr->flags = 0;
-    phdr->address_space_id = 0;
-    phdr->opaque = 0;
+    pkthdr->ts.tv_sec = t.tv_sec;
+    pkthdr->ts.tv_usec = t.tv_usec;
 
-    if ( impl->start )
+    desc->pci = fc->pci;
+    if (fc->sof)
     {
-        impl->pci.flags = DAQ_USR_FLAG_START_FLOW;
-        impl->start = 0;
+        desc->pci.flags |= DAQ_USR_FLAG_START_FLOW;
+        fc->sof = false;
     }
-    else if ( impl->eof )
-        impl->pci.flags = DAQ_USR_FLAG_END_FLOW;
-
-    else
-        impl->pci.flags = 0;
-
-    phdr->priv_ptr = &impl->pci;
 }
 
-static int file_daq_process(
-    FileImpl* impl, DAQ_Analysis_Func_t cb, void* user)
+static DAQ_RecvStatus file_read_message(FileContext* fc, FileMsgDesc* desc)
 {
-    DAQ_PktHdr_t hdr;
-    int n = file_read(impl);
+    desc->msg.data = NULL;
+    int n = read(fc->fid, desc->data, fc->snaplen);
 
-    if ( n < 1 )
-        return n;
-
-    set_pkt_hdr(impl, &hdr, n);
-    DAQ_Verdict verdict = cb(user, &hdr, impl->buf);
+    if ( n )
+    {
+        init_packet_message(fc, desc);
+        desc->msg.data_len = n;
+    }
+    else
+    {
+        // create an empty packet message to convey the End of Flow
+        if (!fc->eof)
+        {
+            init_packet_message(fc, desc);
+            desc->pci.flags |= DAQ_USR_FLAG_END_FLOW;
+            fc->eof = true;
+            return DAQ_RSTAT_EOF;
+        }
+    }
 
-    if ( verdict >= MAX_DAQ_VERDICT )
-        verdict = DAQ_VERDICT_BLOCK;
+    if ( n < 0 )
+    {
+        if (errno != EINTR)
+        {
+            char error_msg[1024] = {0};
+            if (strerror_r(errno, error_msg, sizeof(error_msg)) == 0)
+                SET_ERROR(fc->modinst, "%s: can't read from file (%s)", DAQ_NAME, error_msg);
+            else
+                SET_ERROR(fc->modinst, "%s: can't read from file: %d", DAQ_NAME, errno);
+            return DAQ_RSTAT_ERROR;
+        }
+    }
 
-    impl->stats.verdicts[verdict]++;
-    return n;
+    return DAQ_RSTAT_OK;
 }
 
 //-------------------------------------------------------------------------
 // daq
 //-------------------------------------------------------------------------
 
-static void file_daq_shutdown (void* handle)
+static int file_daq_module_load(const DAQ_BaseAPI_t* base_api)
 {
-    FileImpl* impl = (FileImpl*)handle;
-
-    if ( impl->name )
-        free(impl->name);
+    if (base_api->api_version != DAQ_BASE_API_VERSION || base_api->api_size != sizeof(DAQ_BaseAPI_t))
+        return DAQ_ERROR;
 
-    if ( impl->buf )
-        free(impl->buf);
+    daq_base_api = *base_api;
 
-    free(impl);
+    return DAQ_SUCCESS;
 }
 
-//-------------------------------------------------------------------------
-
-static int file_daq_initialize (
-    const DAQ_Config_t* cfg, void** handle, char* errBuf, size_t errMax)
+static int file_daq_instantiate(const DAQ_ModuleConfig_h modcfg, DAQ_ModuleInstance_h modinst, void** ctxt_ptr)
 {
-    FileImpl* impl = calloc(1, sizeof(*impl));
+    FileContext* fc;
+    int rval = DAQ_ERROR;
 
-    if ( !impl )
+    fc = calloc(1, sizeof(*fc));
+    if (!fc)
     {
-        snprintf(errBuf, errMax, "%s: failed to allocate the ipfw context", DAQ_NAME);
-        return DAQ_ERROR_NOMEM;
+        SET_ERROR(modinst, "%s: Couldn't allocate memory for the new File context!", DAQ_NAME);
+        rval = DAQ_ERROR_NOMEM;
+        goto err;
     }
+    fc->modinst = modinst;
 
-    impl->fid = -1;
-    impl->start = impl->stop = 0;
-    impl->snaplen = cfg->snaplen ? cfg->snaplen : FILE_BUF_SZ;
+    fc->snaplen = daq_base_api.config_get_snaplen(modcfg) ? daq_base_api.config_get_snaplen(modcfg) : FILE_BUF_SZ;
+    fc->fid = -1;
 
-    if ( cfg->name )
+    const char* filename = daq_base_api.config_get_input(modcfg);
+    if (filename)
     {
-        if ( !(impl->name = strdup(cfg->name)) )
+        if (!(fc->filename = strdup(filename)))
         {
-            snprintf(errBuf, errMax, "%s: failed to allocate the filename", DAQ_NAME);
-            free(impl);
-            return DAQ_ERROR_NOMEM;
+            SET_ERROR(modinst, "%s: Couldn't allocate memory for the filename!", DAQ_NAME);
+            rval = DAQ_ERROR_NOMEM;
+            goto err;
         }
     }
 
-    if ( !(impl->buf = malloc(impl->snaplen)) )
-    {
-        snprintf(errBuf, errMax, "%s: failed to allocate the ipfw buffer", DAQ_NAME);
-        file_daq_shutdown(impl);
-        return DAQ_ERROR_NOMEM;
-    }
+    uint32_t pool_size = daq_base_api.config_get_msg_pool_size(modcfg);
+    rval = create_message_pool(fc, pool_size ? pool_size : FILE_DEFAULT_POOL_SIZE);
+    if (rval != DAQ_SUCCESS)
+        goto err;
 
-    impl->state = DAQ_STATE_INITIALIZED;
+    *ctxt_ptr = fc;
 
-    *handle = impl;
     return DAQ_SUCCESS;
+
+err:
+    if (fc)
+    {
+        if (fc->filename)
+            free(fc->filename);
+        destroy_message_pool(fc);
+        free(fc);
+    }
+    return rval;
 }
 
-//-------------------------------------------------------------------------
+static void file_daq_destroy(void* handle)
+{
+    FileContext* fc = (FileContext*) handle;
 
-static int file_daq_start (void* handle)
+    if (fc->filename)
+        free(fc->filename);
+    destroy_message_pool(fc);
+    free(fc);
+}
+
+static int file_daq_start(void* handle)
 {
-    FileImpl* impl = (FileImpl*)handle;
+    FileContext* fc = (FileContext*) handle;
 
-    if ( file_setup(impl) )
+    if (file_setup(fc))
         return DAQ_ERROR;
 
-    impl->state = DAQ_STATE_STARTED;
     return DAQ_SUCCESS;
 }
 
-static int file_daq_stop (void* handle)
+static int file_daq_interrupt(void* handle)
 {
-    FileImpl* impl = (FileImpl*)handle;
-    file_cleanup(impl);
-    impl->state = DAQ_STATE_STOPPED;
+    FileContext* fc = (FileContext*) handle;
+    fc->interrupted = true;
     return DAQ_SUCCESS;
 }
 
-//-------------------------------------------------------------------------
-
-static int file_daq_inject (
-    void* handle, const DAQ_PktHdr_t* hdr, const uint8_t* buf, uint32_t len,
-    int rev)
+static int file_daq_stop (void* handle)
 {
-    (void)handle;
-    (void)hdr;
-    (void)buf;
-    (void)len;
-    (void)rev;
-    return DAQ_ERROR;
+    FileContext* fc = (FileContext*) handle;
+    file_cleanup(fc);
+    return DAQ_SUCCESS;
 }
 
-//-------------------------------------------------------------------------
-
-static int file_daq_acquire (
-    void* handle, int cnt, DAQ_Analysis_Func_t callback, DAQ_Meta_Func_t meta, void* user)
+static int file_daq_ioctl(void* handle, DAQ_IoctlCmd cmd, void* arg, size_t arglen)
 {
-    (void)meta;
+    (void) handle;
 
-    FileImpl* impl = (FileImpl*)handle;
-    int hit = 0, miss = 0;
-    impl->stop = 0;
-
-    while ( (hit < cnt || cnt <= 0) && !impl->stop )
+    if (cmd == DIOCTL_QUERY_USR_PCI)
     {
-        int status = file_daq_process(impl, callback, user);
-
-        if ( status > 0 )
-        {
-            hit++;
-            miss = 0;
-        }
-        else if ( status < 0 )
-            return status;
-
-        else if ( ++miss == 2 )
-            break;
+        if (arglen != sizeof(DIOCTL_QueryUsrPCI))
+            return DAQ_ERROR_INVAL;
+        DIOCTL_QueryUsrPCI* qup = (DIOCTL_QueryUsrPCI*) arg;
+        if (!qup->msg)
+            return DAQ_ERROR_INVAL;
+        FileMsgDesc* desc = (FileMsgDesc*) qup->msg->priv;
+        qup->pci = &desc->pci;
+        return DAQ_SUCCESS;
     }
-    return DAQ_SUCCESS;
-}
-
-//-------------------------------------------------------------------------
-
-static int file_daq_breakloop (void* handle)
-{
-    FileImpl* impl = (FileImpl*)handle;
-    impl->stop = 1;
-    return DAQ_SUCCESS;
-}
-
-static DAQ_State file_daq_check_status (void* handle)
-{
-    FileImpl* impl = (FileImpl*)handle;
-    return impl->state;
+    return DAQ_ERROR_NOTSUP;
 }
 
-static int file_daq_get_stats (void* handle, DAQ_Stats_t* stats)
+static int file_daq_get_stats(void* handle, DAQ_Stats_t* stats)
 {
-    FileImpl* impl = (FileImpl*)handle;
-    *stats = impl->stats;
+    FileContext* fc = (FileContext*) handle;
+    memcpy(stats, &fc->stats, sizeof(DAQ_Stats_t));
     return DAQ_SUCCESS;
 }
 
-static void file_daq_reset_stats (void* handle)
+static void file_daq_reset_stats(void* handle)
 {
-    FileImpl* impl = (FileImpl*)handle;
-    memset(&impl->stats, 0, sizeof(impl->stats));
+    FileContext* fc = (FileContext*) handle;
+    memset(&fc->stats, 0, sizeof(fc->stats));
 }
 
 static int file_daq_get_snaplen (void* handle)
 {
-    FileImpl* impl = (FileImpl*)handle;
-    return impl->snaplen;
+    FileContext* fc = (FileContext*) handle;
+    return fc->snaplen;
 }
 
-static uint32_t file_daq_get_capabilities (void* handle)
+static uint32_t file_daq_get_capabilities(void* handle)
 {
-    (void)handle;
+    (void) handle;
     return DAQ_CAPA_BLOCK | DAQ_CAPA_REPLACE | DAQ_CAPA_INJECT | DAQ_CAPA_INJECT_RAW
-        | DAQ_CAPA_BREAKLOOP | DAQ_CAPA_UNPRIV_START;
+        | DAQ_CAPA_INTERRUPT | DAQ_CAPA_UNPRIV_START;
 }
 
 static int file_daq_get_datalink_type(void *handle)
@@ -343,82 +395,111 @@ static int file_daq_get_datalink_type(void *handle)
     return DLT_USER;
 }
 
-static const char* file_daq_get_errbuf (void* handle)
+static unsigned file_daq_msg_receive(void* handle, const unsigned max_recv, const DAQ_Msg_t* msgs[], DAQ_RecvStatus* rstat)
 {
-    FileImpl* impl = (FileImpl*)handle;
-    return impl->error;
-}
+    FileContext* fc = (FileContext*) handle;
+    DAQ_RecvStatus status = DAQ_RSTAT_OK;
+    unsigned idx = 0;
 
-static void file_daq_set_errbuf (void* handle, const char* s)
-{
-    FileImpl* impl = (FileImpl*)handle;
-    DPE(impl->error, "%s", s ? s : "");
-}
+    while (idx < max_recv)
+    {
+        /* Check to see if the receive has been canceled.  If so, reset it and return appropriately. */
+        if (fc->interrupted)
+        {
+            fc->interrupted = false;
+            status = DAQ_RSTAT_INTERRUPTED;
+            break;
+        }
 
-static int file_daq_get_device_index(void* handle, const char* device)
-{
-    (void)handle;
-    (void)device;
-    return DAQ_ERROR_NOTSUP;
+        /* Make sure that we have a message descriptor available to populate. */
+        FileMsgDesc* desc = fc->pool.freelist;
+        if (!desc)
+        {
+            status = DAQ_RSTAT_NOBUF;
+            break;
+        }
+
+        /* Attempt to read a message into the descriptor. */
+        status = file_read_message(fc, desc);
+        if (status != DAQ_RSTAT_OK)
+            break;
+
+        /* Last, but not least, extract this descriptor from the free list and
+           place the message in the return vector. */
+        fc->pool.freelist = desc->next;
+        desc->next = NULL;
+        fc->pool.info.available--;
+        msgs[idx] = &desc->msg;
+
+        idx++;
+    }
+
+    *rstat = status;
+
+    return idx;
 }
 
-static int file_daq_set_filter (void* handle, const char* filter)
+static int file_daq_msg_finalize(void* handle, const DAQ_Msg_t* msg, DAQ_Verdict verdict)
 {
-    (void)handle;
-    (void)filter;
-    return DAQ_ERROR_NOTSUP;
+    FileContext* fc = (FileContext*) handle;
+    FileMsgDesc* desc = (FileMsgDesc *) msg->priv;
+
+    if (verdict >= MAX_DAQ_VERDICT)
+        verdict = DAQ_VERDICT_PASS;
+    fc->stats.verdicts[verdict]++;
+
+    /* Toss the descriptor back on the free list for reuse. */
+    desc->next = fc->pool.freelist;
+    fc->pool.freelist = desc;
+    fc->pool.info.available++;
+
+    return DAQ_SUCCESS;
 }
 
-static int file_query_flow(void* handle, const DAQ_PktHdr_t* hdr, DAQ_QueryFlow_t* query)
+static int file_daq_get_msg_pool_info(void* handle, DAQ_MsgPoolInfo_t* info)
 {
-    FileImpl* impl = (FileImpl*)handle;
+    FileContext* fc = (FileContext*) handle;
 
-    if ( hdr->priv_ptr != &impl->pci )  // sanity check
-        return DAQ_ERROR_INVAL;
+    *info = fc->pool.info;
 
-    if ( query->type == DAQ_USR_QUERY_PCI )
-    {
-        query->value = &impl->pci;
-        query->length = sizeof(impl->pci);
-        return DAQ_SUCCESS;
-    }
-    return DAQ_ERROR_NOTSUP;
+    return DAQ_SUCCESS;
 }
 
 //-------------------------------------------------------------------------
 
 #ifdef BUILDING_SO
-DAQ_SO_PUBLIC DAQ_Module_t DAQ_MODULE_DATA =
+DAQ_SO_PUBLIC const DAQ_ModuleAPI_t DAQ_MODULE_DATA =
 #else
-DAQ_Module_t file_daq_module_data =
+const DAQ_ModuleAPI_t file_daq_module_data =
 #endif
 {
-    .api_version = DAQ_API_VERSION,
-    .module_version = DAQ_MOD_VERSION,
-    .name = DAQ_NAME,
-    .type = DAQ_TYPE,
-    .initialize = file_daq_initialize,
-    .set_filter = file_daq_set_filter,
-    .start = file_daq_start,
-    .acquire = file_daq_acquire,
-    .inject = file_daq_inject,
-    .breakloop = file_daq_breakloop,
-    .stop = file_daq_stop,
-    .shutdown = file_daq_shutdown,
-    .check_status = file_daq_check_status,
-    .get_stats = file_daq_get_stats,
-    .reset_stats = file_daq_reset_stats,
-    .get_snaplen = file_daq_get_snaplen,
-    .get_capabilities = file_daq_get_capabilities,
-    .get_datalink_type = file_daq_get_datalink_type,
-    .get_errbuf = file_daq_get_errbuf,
-    .set_errbuf = file_daq_set_errbuf,
-    .get_device_index = file_daq_get_device_index,
-    .modify_flow = NULL,
-    .hup_prep = NULL,
-    .hup_apply = NULL,
-    .hup_post = NULL,
-    .dp_add_dc = NULL,
-    .query_flow = file_query_flow
+    /* .api_version = */ DAQ_MODULE_API_VERSION,
+    /* .api_size = */ sizeof(DAQ_ModuleAPI_t),
+    /* .module_version = */ DAQ_MOD_VERSION,
+    /* .name = */ DAQ_NAME,
+    /* .type = */ DAQ_TYPE,
+    /* .load = */ file_daq_module_load,
+    /* .unload = */ NULL,
+    /* .get_variable_descs = */ NULL,
+    /* .instantiate = */ file_daq_instantiate,
+    /* .destroy = */ file_daq_destroy,
+    /* .set_filter = */ NULL,
+    /* .start = */ file_daq_start,
+    /* .inject = */ NULL,
+    /* .inject_relative = */ NULL,
+    /* .interrupt = */ file_daq_interrupt,
+    /* .stop = */ file_daq_stop,
+    /* .ioctl = */ file_daq_ioctl,
+    /* .get_stats = */ file_daq_get_stats,
+    /* .reset_stats = */ file_daq_reset_stats,
+    /* .get_snaplen = */ file_daq_get_snaplen,
+    /* .get_capabilities = */ file_daq_get_capabilities,
+    /* .get_datalink_type = */ file_daq_get_datalink_type,
+    /* .config_load = */ NULL,
+    /* .config_swap = */ NULL,
+    /* .config_free = */ NULL,
+    /* .msg_receive = */ file_daq_msg_receive,
+    /* .msg_finalize = */ file_daq_msg_finalize,
+    /* .get_msg_pool_info = */ file_daq_get_msg_pool_info,
 };
 
index a735089d2324312d8e47dc4b3c59e30b3bc3262b..e3aac549c32b937a613c3a962751468daa1a8ae6 100644 (file)
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <daq_api.h>
-#include <sfbpf_dlt.h>
+#include <daq_module_api.h>
 
-#define DAQ_MOD_VERSION 0
+#define DAQ_MOD_VERSION 1
 #define DAQ_NAME "hext"
 #define DAQ_TYPE (DAQ_TYPE_FILE_CAPABLE|DAQ_TYPE_INTF_CAPABLE|DAQ_TYPE_MULTI_INSTANCE)
 
+#define HEXT_DEFAULT_POOL_SIZE 16
 #define DEF_BUF_SZ 16384
 #define MAX_LINE_SZ  128
 
-typedef struct {
-    char* name;
-    FILE* fyle;
+#define SET_ERROR(modinst, ...)    daq_base_api.set_errbuf(modinst, __VA_ARGS__)
 
-    bool start;
-    bool stop;
-    bool eof;
-    int dlt;
+typedef struct _hext_msg_desc
+{
+    DAQ_Msg_t msg;
+    DAQ_PktHdr_t pkthdr;
+    Flow_Stats_t flowstats;
+    DAQ_UsrHdr_t pci;
+    uint8_t* data;
+    struct _hext_msg_desc* next;
+} HextMsgDesc;
 
+typedef struct
+{
+    HextMsgDesc* pool;
+    HextMsgDesc* freelist;
+    DAQ_MsgPoolInfo_t info;
+} HextMsgPool;
+
+typedef struct
+{
+    /* Configuration */
+    char* filename;
     unsigned snaplen;
-    unsigned idx;
+    int dlt;
 
-    uint8_t* buf;
-    char line[MAX_LINE_SZ];
-    char error[DAQ_ERRBUF_SIZE];
+    /* State */
+    DAQ_ModuleInstance_h modinst;
+    HextMsgPool pool;
+    FILE* fp;
+    volatile bool interrupted;
+
+    bool sof;
+    bool eof;
 
     DAQ_UsrHdr_t pci;
     DAQ_UsrHdr_t cfg;
 
-    DAQ_State state;
     DAQ_Stats_t stats;
+} HextContext;
+
+static DAQ_VariableDesc_t hext_variable_descriptions[] = {
+    { "dlt", "Data link type to report to the application instead of DLT_USER (integer)", DAQ_VAR_DESC_REQUIRES_ARGUMENT },
+};
 
-    bool meta;
-    DAQ_MetaHdr_t hdr;
-    Flow_Stats_t flow;
-} HextImpl;
+static DAQ_BaseAPI_t daq_base_api;
 
 //-------------------------------------------------------------------------
 // utility functions
 //-------------------------------------------------------------------------
 
-static void set_c2s(HextImpl* impl, int c2s)
+static void destroy_message_pool(HextContext* hc)
 {
-    if ( c2s )
+    HextMsgPool* pool = &hc->pool;
+    if (pool->pool)
     {
-        impl->pci = impl->cfg;
+        while (pool->info.size > 0)
+            free(pool->pool[--pool->info.size].data);
+        free(pool->pool);
+        pool->pool = NULL;
+    }
+    pool->freelist = NULL;
+    pool->info.available = 0;
+    pool->info.mem_size = 0;
+}
+
+static int create_message_pool(HextContext* hc, unsigned size)
+{
+    HextMsgPool* pool = &hc->pool;
+    pool->pool = calloc(sizeof(HextMsgDesc), size);
+    if (!pool->pool)
+    {
+        SET_ERROR(hc->modinst, "%s: Could not allocate %zu bytes for a packet descriptor pool!",
+                __func__, sizeof(HextMsgDesc) * size);
+        return DAQ_ERROR_NOMEM;
+    }
+    pool->info.mem_size = sizeof(HextMsgDesc) * size;
+    while (pool->info.size < size)
+    {
+        /* Allocate packet data and set up descriptor */
+        HextMsgDesc *desc = &pool->pool[pool->info.size];
+        desc->data = malloc(hc->snaplen);
+        if (!desc->data)
+        {
+            SET_ERROR(hc->modinst, "%s: Could not allocate %d bytes for a packet descriptor message buffer!",
+                    __func__, hc->snaplen);
+            return DAQ_ERROR_NOMEM;
+        }
+        pool->info.mem_size += hc->snaplen;
+
+        /* Initialize non-zero invariant packet header fields. */
+        DAQ_PktHdr_t *pkthdr = &desc->pkthdr;
+        pkthdr->address_space_id = 0;
+        pkthdr->ingress_index = DAQ_PKTHDR_UNKNOWN;
+        pkthdr->ingress_group = DAQ_PKTHDR_UNKNOWN;
+        pkthdr->egress_index = DAQ_PKTHDR_UNKNOWN;
+        pkthdr->egress_group = DAQ_PKTHDR_UNKNOWN;
+        pkthdr->flags = 0;
+
+        /* Initialize non-zero invariant message header fields. */
+        DAQ_Msg_t *msg = &desc->msg;
+        msg->owner = hc->modinst;
+        msg->priv = desc;
+
+        /* Place it on the free list */
+        desc->next = pool->freelist;
+        pool->freelist = desc;
+
+        pool->info.size++;
+    }
+    pool->info.available = pool->info.size;
+    return DAQ_SUCCESS;
+}
+
+static void set_c2s(HextContext* hc, int c2s)
+{
+    if (c2s)
+    {
+        hc->pci = hc->cfg;
     }
     else
     {
-        impl->pci.src_addr = impl->cfg.dst_addr;
-        impl->pci.dst_addr = impl->cfg.src_addr;
-        impl->pci.src_port = impl->cfg.dst_port;
-        impl->pci.dst_port = impl->cfg.src_port;
-        impl->pci.flags &= ~DAQ_USR_FLAG_TO_SERVER;
+        hc->pci.src_addr = hc->cfg.dst_addr;
+        hc->pci.dst_addr = hc->cfg.src_addr;
+        hc->pci.src_port = hc->cfg.dst_port;
+        hc->pci.dst_port = hc->cfg.src_port;
+        hc->pci.flags &= ~DAQ_USR_FLAG_TO_SERVER;
     }
 }
 
@@ -98,13 +181,13 @@ static void parse_host(const char* s, uint32_t* addr, uint16_t* port)
     char buf[32];  // oversize so pton() errors out if too long
     unsigned c = 0;
 
-    while ( isspace(*s) )
+    while (isspace(*s))
         s++;
 
-    while ( *s && !isspace(*s) && c < sizeof(buf) )
+    while (*s && !isspace(*s) && c < sizeof(buf))
         buf[c++] = *s++;
 
-    if ( c == sizeof(buf) )
+    if (c == sizeof(buf))
         --c;
 
     buf[c] = '\0';
@@ -113,30 +196,30 @@ static void parse_host(const char* s, uint32_t* addr, uint16_t* port)
     *port = atoi(s);
 }
 
-static void parse_pci(HextImpl* impl, const char* s)
+static void parse_pci(HextContext* hc, const char* s)
 {
-    parse_host(s, &impl->pci.src_addr, &impl->pci.src_port);
+    parse_host(s, &hc->pci.src_addr, &hc->pci.src_port);
 
     s = strstr(s, "->");
 
-    if ( !s )
+    if (!s)
         return;
 
-    parse_host(s+2, &impl->pci.dst_addr, &impl->pci.dst_port);
+    parse_host(s+2, &hc->pci.dst_addr, &hc->pci.dst_port);
 
     // hack until client / server is resolved:
-    if ( impl->pci.src_port >= impl->pci.dst_port )
-        impl->pci.flags |= DAQ_USR_FLAG_TO_SERVER;
+    if (hc->pci.src_port >= hc->pci.dst_port)
+        hc->pci.flags |= DAQ_USR_FLAG_TO_SERVER;
     else
-        impl->pci.flags &= ~DAQ_USR_FLAG_TO_SERVER;
+        hc->pci.flags &= ~DAQ_USR_FLAG_TO_SERVER;
 }
 
 static bool is_ipv4(char const* src)
 {
     struct in6_addr temp;
-    if ( inet_pton(AF_INET, src, &temp) == 1 )
+    if (inet_pton(AF_INET, src, &temp) == 1)
         return true;
-    else if ( inet_pton(AF_INET6, src, &temp) == 1 )
+    else if (inet_pton(AF_INET6, src, &temp) == 1)
         return false;
 
     return false;
@@ -144,200 +227,53 @@ static bool is_ipv4(char const* src)
 
 static void IpAddr(uint32_t* addr, char const* ip)
 {
-    if ( is_ipv4(ip) ) {
+    if (is_ipv4(ip))
+    {
         addr[0] = 0;
         addr[1] = 0;
         addr[2] = htonl(0xffff);
         inet_pton(AF_INET, ip, &addr[3]);
     }
-    else {
+    else
         inet_pton(AF_INET6, ip, addr);
-    }
 }
 
-enum Search {
-    I_ZONE,
-    E_ZONE,
-    I_INT,
-    E_INT,
-    SRC_HOST,
-    SRC_PORT,
-    DST_HOST,
-    DST_PORT,
-    OPAQUE,
-    I_PKTS,
-    R_PKTS,
-    I_DROPPED,
-    R_DROPPED,
-    I_BYTES,
-    R_BYTES,
-    IS_QOS,
-    SOF_TIME,
-    EOF_TIME,
-    VLAN_TAG,
-    ADDR_SPACE,
-    PROTO,
-    END
-};
-
-static void set_flowstats(Flow_Stats_t* f, enum Search state, const char* s)
+static bool parse_flowstats(DAQ_MsgType type, const char* line, HextMsgDesc *desc)
 {
-    switch (state)
-    {
-        case I_ZONE:
-            f->ingressZone = atoi(s);
-            break;
-
-        case E_ZONE:
-            f->egressZone = atoi(s);
-            break;
-
-        case I_INT:
-            f->ingressIntf = atoi(s);
-            break;
-
-        case E_INT:
-            f->egressIntf = atoi(s);
-            break;
-
-        case SRC_HOST:
-            IpAddr((uint32_t*)&f->initiatorIp, s);
-            break;
-
-        case SRC_PORT:
-            f->initiatorPort = htons(atoi(s));
-            break;
-
-        case DST_HOST:
-            IpAddr((uint32_t*)&f->responderIp, s);
-            break;
-
-        case DST_PORT:
-            f->responderPort = htons(atoi(s));
-            break;
-
-        case OPAQUE:
-            f->opaque = atoi(s);
-            break;
-
-        case I_PKTS:
-            f->initiatorPkts = atoi(s);
-            break;
-
-        case R_PKTS:
-            f->responderPkts = atoi(s);
-            break;
-
-        case I_DROPPED:
-            f->initiatorPktsDropped = atoi(s);
-            break;
-
-        case R_DROPPED:
-            f->responderPktsDropped = atoi(s);
-            break;
-
-        case I_BYTES:
-            f->initiatorBytesDropped = atoi(s);
-            break;
-
-        case R_BYTES:
-            f->responderBytesDropped = atoi(s);
-            break;
-
-        case IS_QOS:
-            f->isQoSAppliedOnSrcIntf = atoi(s);
-            break;
-
-        case SOF_TIME:
-            f->sof_timestamp.tv_sec = atoi(s);
-            f->sof_timestamp.tv_usec = 0;
-            break;
-
-        case EOF_TIME:
-            f->eof_timestamp.tv_sec = atoi(s);
-            f->sof_timestamp.tv_usec = 0;
-            break;
-
-        case VLAN_TAG:
-            f->vlan_tag = atoi(s);
-            if (f->vlan_tag == 0)
-                f->vlan_tag = 0xfff;
-            break;
-
-        case ADDR_SPACE:
-            f->address_space_id = atoi(s);
-            break;
-
-        case PROTO:
-            f->protocol = atoi(s);
-            break;
-
-        default:
-            break;
-    }
-}
-
-static void parse_flowstats(HextImpl* impl, bool sof, const char* line)
-{
-    DAQ_MetaHdr_t* h = &impl->hdr;
-    Flow_Stats_t* f = &impl->flow;
-
-    char token[INET6_ADDRSTRLEN];
-    memset(token, 0, sizeof(token));
-
-    char* t = token;
-    const char* p = line;
-
-    if ( sof )
-        h->type = DAQ_METAHDR_TYPE_SOF;
-    else
-        h->type = DAQ_METAHDR_TYPE_EOF;
-
-    enum Search search;
-    for (search = I_ZONE; search != END; p++)
-    {
-        if (p[0] == '\0')
-            return;
-
-        if ((size_t)(t - token) >= sizeof(token) - 1)
-            return;
-
-        if (isspace(p[0]))
-        {
-            if (t != token)
-            {
-                set_flowstats(f, search, token);
-                memset(token, 0, sizeof(token));
-                t = token;
-                search++;
-            }
-
-            continue;
-        }
-        else
-        {
-            *t = *p;
-            t++;
-        }
-    }
+#define FLOWSTATS_FORMAT "%d %d %d %d %s %hu %s %hu %u %lu %lu %lu %lu %lu %lu %hhu %ld %ld %hu %hu %hhu"
+#define FLOWSTATS_ITEMS 21
+    Flow_Stats_t* f = &desc->flowstats;
+    char srcaddr[INET6_ADDRSTRLEN], dstaddr[INET6_ADDRSTRLEN];
+    int rval = sscanf(line, FLOWSTATS_FORMAT, &f->ingressZone, &f->egressZone, &f->ingressIntf,
+            &f->egressIntf, srcaddr, &f->initiatorPort, dstaddr, &f->responderPort, &f->opaque,
+            &f->initiatorPkts, &f->responderPkts, &f->initiatorPktsDropped, &f->responderPktsDropped,
+            &f->initiatorBytesDropped, &f->responderBytesDropped, &f->isQoSAppliedOnSrcIntf,
+            &f->sof_timestamp.tv_sec, &f->eof_timestamp.tv_sec, &f->vlan_tag, &f->address_space_id,
+            &f->protocol);
+    if (rval != FLOWSTATS_ITEMS)
+        return false;
 
-    if (t != token)
-        set_flowstats(f, search-1, token);
+    desc->msg.type = type;
+    desc->msg.hdr_len = sizeof(desc->flowstats);
+    desc->msg.hdr = &desc->flowstats;
+    desc->msg.data_len = 0;
+    desc->msg.data = NULL;
 
-    impl->meta = true;
-    impl->line[0] = '\0';
-}
+    IpAddr((uint32_t*)&f->initiatorIp, srcaddr);
+    f->initiatorPort = htons(f->initiatorPort);
+    IpAddr((uint32_t*)&f->responderIp, dstaddr);
+    f->responderPort = htons(f->responderPort);
+    f->sof_timestamp.tv_usec = 0;
+    f->eof_timestamp.tv_usec = 0;
+    if (f->vlan_tag == 0)
+        f->vlan_tag = 0xfff;
 
-static unsigned flush(HextImpl* impl)
-{
-    unsigned n = impl->idx;
-    impl->idx = 0;
-    return n;
+    return true;
 }
 
 static uint8_t xlat(char c)
 {
-    switch ( c )
+    switch (c)
     {
     case 'r': return '\r';
     case 'n': return '\n';
@@ -350,12 +286,12 @@ static uint8_t xlat(char c)
 static int unescape(char c, char* u)
 {
     static int esc = 0;
-    if ( !esc && c == '\\' )
+    if (!esc && c == '\\')
     {
         esc = 1;
         return 0;
     }
-    else if ( esc )
+    else if (esc)
     {
         esc = 0;
         *u = xlat(c);
@@ -375,505 +311,496 @@ static int unescape(char c, char* u)
 // $packet -> server
 // $client <addr> <port>
 // $server <addr> <port>
-static void parse_command(HextImpl* impl, char* s)
+static bool parse_command(HextContext* hc, const char* s, HextMsgDesc *desc)
 {
-    if ( !strncmp(s, "packet -> client", 16) )
-        set_c2s(impl, 0);
+    bool msg = false;
 
-    else if ( !strncmp(s, "packet -> server", 16) )
-        set_c2s(impl, 1);
+    if (!strncmp(s, "packet -> client", 16))
+        set_c2s(hc, 0);
 
-    else if ( !strncmp(s, "packet ", 7) )
-        parse_pci(impl, s+7);
+    else if (!strncmp(s, "packet -> server", 16))
+        set_c2s(hc, 1);
 
-    else if ( !strncmp(s, "client ", 7) )
-        parse_host(s+7, &impl->cfg.src_addr, &impl->cfg.src_port);
+    else if (!strncmp(s, "packet ", 7))
+        parse_pci(hc, s+7);
 
-    else if ( !strncmp(s, "server ", 7) )
-        parse_host(s+7, &impl->cfg.dst_addr, &impl->cfg.dst_port);
+    else if (!strncmp(s, "client ", 7))
+        parse_host(s+7, &hc->cfg.src_addr, &hc->cfg.src_port);
 
-    else if ( !strncmp(s, "sof ", 4) )
-        parse_flowstats(impl, true, s+4);
+    else if (!strncmp(s, "server ", 7))
+        parse_host(s+7, &hc->cfg.dst_addr, &hc->cfg.dst_port);
 
-    else if ( !strncmp(s, "eof ", 4) )
-        parse_flowstats(impl, false, s+4);
+    else if (!strncmp(s, "sof ", 4))
+        msg = parse_flowstats(DAQ_MSG_TYPE_SOF, s+4, desc);
+
+    else if (!strncmp(s, "eof ", 4))
+        msg = parse_flowstats(DAQ_MSG_TYPE_EOF, s+4, desc);
+
+    return msg;
 }
 
 // load quoted string data into buffer up to snaplen
-static void parse_string(HextImpl* impl, char* s)
+static void parse_string(HextContext* hc, char* s, HextMsgDesc *desc)
 {
     char t;
 
-    while ( *s && *s != '"' && impl->idx < impl->snaplen )
+    while (*s && *s != '"' && desc->msg.data_len < hc->snaplen)
     {
-        if ( unescape(*s++, &t) )
-            impl->buf[impl->idx++] = t;
+        if (unescape(*s++, &t))
+            desc->data[desc->msg.data_len++] = t;
     }
+    desc->pkthdr.pktlen = desc->msg.data_len;
 }
 
 // load hex data into buffer up to snaplen
-static void parse_hex(HextImpl* impl, char* s)
+static void parse_hex(HextContext* hc, char* s, HextMsgDesc *desc)
 {
     char* t = s;
     long x = strtol(t, &s, 16);
 
-    while ( *s && s != t && impl->idx < impl->snaplen )
+    while (*s && s != t && desc->msg.data_len  < hc->snaplen)
     {
-        impl->buf[impl->idx++] = (uint8_t)x;
+        desc->data[desc->msg.data_len++] = (uint8_t) x;
         x = strtol(t=s, &s, 16);
     }
+    desc->pkthdr.pktlen = desc->msg.data_len;
+}
+
+static void init_packet_message(HextContext* hc, HextMsgDesc* desc)
+{
+    DAQ_PktHdr_t *pkthdr = &desc->pkthdr;
+
+    desc->msg.type = DAQ_MSG_TYPE_PACKET;
+    desc->msg.hdr_len = sizeof(*pkthdr);
+    desc->msg.hdr = pkthdr;
+    desc->msg.data_len = 0;
+    desc->msg.data = desc->data;
+
+    struct timeval t;
+    gettimeofday(&t, NULL);
+
+    pkthdr->ts.tv_sec = t.tv_sec;
+    pkthdr->ts.tv_usec = t.tv_usec;
+
+    desc->pci = hc->pci;
+    if (hc->sof)
+    {
+        desc->pci.flags |= DAQ_USR_FLAG_START_FLOW;
+        hc->sof = false;
+    }
 }
 
-static int parse(HextImpl* impl)
+static bool parse(HextContext* hc, char* line, HextMsgDesc* desc)
 {
-    char* s = impl->line;
+    char* s = line;
+    bool got_msg = false;
 
-    while ( isspace(*s) )
+    while (isspace(*s))
         s++;
 
-    switch ( *s )
+    // Force a flush of the current packet message if we hit a blank line or command
+    switch (*s)
     {
     case '\0':
-        impl->line[0] = '\0';
-        return flush(impl);
+        if (desc->msg.data)
+            got_msg = true;
+        break;
 
     case '#':
         break;
 
     case '$':
-        if ( impl->idx )
-            return flush(impl);
+        // Do not reset the line buffer so that we can parse the command the next time through
+        if (desc->msg.data)
+            return true;
 
-        parse_command(impl, s+1);
+        got_msg = parse_command(hc, s+1, desc);
         break;
 
     case '"':
-        parse_string(impl, s+1);
+        if (!desc->msg.data)
+            init_packet_message(hc, desc);
+        parse_string(hc, s+1, desc);
         break;
 
     case 'x':
-        parse_hex(impl, s+1);
+        if (!desc->msg.data)
+            init_packet_message(hc, desc);
+        parse_hex(hc, s+1, desc);
         break;
     }
-    impl->line[0] = '\0';
-    return 0;
+    line[0] = '\0';
+    return got_msg;
 }
 
-//-------------------------------------------------------------------------
-// file functions
-//-------------------------------------------------------------------------
-
-static int hext_setup(HextImpl* impl)
+static DAQ_RecvStatus hext_read_message(HextContext* hc, HextMsgDesc* desc)
 {
-    if ( !strcmp(impl->name, "tty") )
-    {
-        impl->fyle = stdin;
-    }
-    else if ( !(impl->fyle = fopen(impl->name, "r")) )
-    {
-        char error_msg[1024] = {0};
-        if (strerror_r(errno, error_msg, sizeof(error_msg)) == 0)
-            DPE(impl->error, "%s: can't open file (%s)\n",
-                DAQ_NAME, error_msg);
-        else
-            DPE(impl->error, "%s: can't open file: %d\n",
-                DAQ_NAME, errno);
-        return -1;
-    }
-    parse_host("192.168.1.2 12345", &impl->cfg.src_addr, &impl->cfg.src_port);
-    parse_host("10.1.2.3 80", &impl->cfg.dst_addr, &impl->cfg.dst_port);
-
-    impl->cfg.ip_proto = impl->pci.ip_proto = IPPROTO_TCP;
-    impl->cfg.flags = impl->pci.flags = DAQ_USR_FLAG_TO_SERVER;
-    impl->start = true;
-
-    return 0;
-}
-
-static void hext_cleanup(HextImpl* impl)
-{
-    if ( impl->fyle != stdin )
-        fclose(impl->fyle);
-
-    impl->fyle = NULL;
-}
-
-static int hext_read(HextImpl* impl)
-{
-    int n = 0;
+    char line[MAX_LINE_SZ];
+    char* s = NULL;
 
-    while ( impl->line[0] || fgets(impl->line, sizeof(impl->line), impl->fyle) )
+    desc->msg.data = NULL;
+    line[0] = '\0';
+    while (line[0] != '\0' || (s = fgets(line, sizeof(line), hc->fp)) != NULL)
     {
-        if ( (n = parse(impl)) )
+        // FIXIT-L Currently no error checking, just ignores bad lines
+        if (parse(hc, line, desc))
             break;
-
-        if (impl->meta)
-            return 0;
     }
 
-    if ( !n )
-        n = flush(impl);
-
-    if ( !n )
+    if (!s)
     {
-        if ( (impl->dlt == DLT_USER) && !impl->eof )
+        if (feof(hc->fp))
         {
-            impl->eof = true;
-            return 1;  // <= zero won't make it :(
+            // If there is still pending data in a packet message, mark it as End of Flow and flush it
+            // Otherwise, create an empty packet message to convey the End of Flow
+            // FIXIT-M - Make this actually the case, for now Snort can't handle data on packets marked EoF
+            /*
+            if (!hc->eof)
+            {
+                if (!desc->msg.data)
+                    init_packet_message(hc, desc);
+                desc->pci.flags |= DAQ_USR_FLAG_END_FLOW;
+                hc->eof = true;
+                return DAQ_RSTAT_OK;
+            }
+            */
+            if (desc->msg.data)
+                return DAQ_RSTAT_OK;
+            if (!hc->eof)
+            {
+                init_packet_message(hc, desc);
+                desc->pci.flags |= DAQ_USR_FLAG_END_FLOW;
+                hc->eof = true;
+                return DAQ_RSTAT_OK;
+            }
+            return DAQ_RSTAT_EOF;
         }
-        return DAQ_READFILE_EOF;
-    }
 
-    if ( n < 0 )
-    {
-        if (errno != EINTR)
+        if (ferror(hc->fp))
         {
             char error_msg[1024] = {0};
             if (strerror_r(errno, error_msg, sizeof(error_msg)) == 0)
-                DPE(impl->error, "%s: can't read from file (%s)\n",
-                    DAQ_NAME, error_msg);
+                SET_ERROR(hc->modinst, "%s: can't read from file (%s)\n", DAQ_NAME, error_msg);
             else
-                DPE(impl->error, "%s: can't read from file: %d\n",
-                    DAQ_NAME, errno);
+                SET_ERROR(hc->modinst, "%s: can't read from file: %d\n", DAQ_NAME, errno);
+            return DAQ_RSTAT_ERROR;
         }
-        return DAQ_ERROR;
     }
-    return n;
+
+    return DAQ_RSTAT_OK;
 }
 
 //-------------------------------------------------------------------------
-// daq utilities
+// file functions
 //-------------------------------------------------------------------------
 
-static int get_vars (
-    HextImpl* impl, const DAQ_Config_t* cfg, char* errBuf, size_t errMax
-) {
-    const char* s = NULL;
-    DAQ_Dict* entry;
-
-    for ( entry = cfg->values; entry; entry = entry->next)
-    {
-        if ( !strcmp(entry->key, "dlt") )
-            s = entry->value;
-
-        else
-        {
-            snprintf(errBuf, errMax, "unknown var (%s)", s);
-            return 0;
-        }
-    }
-    if ( s )
-        impl->dlt = atoi(s);
-
-    return 1;
-}
-
-static void set_pkt_hdr(HextImpl* impl, DAQ_PktHdr_t* phdr, ssize_t len)
+static int hext_setup(HextContext* hc)
 {
-    struct timeval t;
-    gettimeofday(&t, NULL);
-
-    phdr->ts.tv_sec = t.tv_sec;
-    phdr->ts.tv_usec = t.tv_usec;
-    phdr->caplen = phdr->pktlen = len;
-
-    phdr->ingress_index = phdr->egress_index = -1;
-    phdr->ingress_group = phdr->egress_group = -1;
-
-    phdr->flags = 0;
-    phdr->address_space_id = 0;
-    phdr->opaque = 0;
-
-    if ( impl->dlt != DLT_USER )
-    {
-        phdr->priv_ptr = NULL;
-        return;
-    }
-    impl->pci.flags &= ~(DAQ_USR_FLAG_START_FLOW|DAQ_USR_FLAG_END_FLOW);
-
-    if ( impl->start )
+    if (!strcmp(hc->filename, "tty"))
     {
-        impl->pci.flags |= DAQ_USR_FLAG_START_FLOW;
-        impl->start = false;
+        hc->fp = stdin;
     }
-    else if ( impl->eof )
-        impl->pci.flags |= DAQ_USR_FLAG_END_FLOW;
-
-    phdr->priv_ptr = &impl->pci;
-}
-
-static int hext_daq_process(
-    HextImpl* impl, DAQ_Analysis_Func_t cb, DAQ_Meta_Func_t mb, void* user)
-{
-    DAQ_PktHdr_t hdr;
-    int n = hext_read(impl);
-
-    if (impl->meta && mb)
+    else if (!(hc->fp = fopen(hc->filename, "r")))
     {
-        mb(user, (const DAQ_MetaHdr_t*)&impl->hdr, (const uint8_t*)&impl->flow);
-        impl->meta = false;
-        return 0;
+        char error_msg[1024] = {0};
+        if (strerror_r(errno, error_msg, sizeof(error_msg)) == 0)
+            SET_ERROR(hc->modinst, "%s: can't open file (%s)\n", DAQ_NAME, error_msg);
+        else
+            SET_ERROR(hc->modinst, "%s: can't open file: %d\n", DAQ_NAME, errno);
+        return -1;
     }
+    parse_host("192.168.1.2 12345", &hc->cfg.src_addr, &hc->cfg.src_port);
+    parse_host("10.1.2.3 80", &hc->cfg.dst_addr, &hc->cfg.dst_port);
 
-    if ( n < 1 )
-        return n;
-
-    set_pkt_hdr(impl, &hdr, n);
-    DAQ_Verdict verdict = cb(user, &hdr, impl->buf);
+    hc->cfg.ip_proto = hc->pci.ip_proto = IPPROTO_TCP;
+    hc->cfg.flags = hc->pci.flags = DAQ_USR_FLAG_TO_SERVER;
+    hc->sof = true;
+    hc->eof = false;
 
-    if ( verdict >= MAX_DAQ_VERDICT )
-        verdict = DAQ_VERDICT_BLOCK;
-
-    impl->stats.verdicts[verdict]++;
-    return n;
+    return 0;
 }
 
+
 //-------------------------------------------------------------------------
 // daq
 //-------------------------------------------------------------------------
 
-static void hext_daq_shutdown (void* handle)
+static int hext_daq_module_load(const DAQ_BaseAPI_t* base_api)
 {
-    HextImpl* impl = (HextImpl*)handle;
-
-    if ( impl->name )
-        free(impl->name);
+    if (base_api->api_version != DAQ_BASE_API_VERSION || base_api->api_size != sizeof(DAQ_BaseAPI_t))
+        return DAQ_ERROR;
 
-    if ( impl->buf )
-        free(impl->buf);
+    daq_base_api = *base_api;
 
-    free(impl);
+    return DAQ_SUCCESS;
 }
 
-//-------------------------------------------------------------------------
+static int hext_daq_get_variable_descs(const DAQ_VariableDesc_t** var_desc_table)
+{
+    *var_desc_table = hext_variable_descriptions;
 
-static int hext_daq_initialize (
-    const DAQ_Config_t* cfg, void** handle, char* errBuf, size_t errMax)
+    return sizeof(hext_variable_descriptions) / sizeof(DAQ_VariableDesc_t);
+}
+
+static int hext_daq_instantiate(const DAQ_ModuleConfig_h modcfg, DAQ_ModuleInstance_h modinst, void** ctxt_ptr)
 {
-    HextImpl* impl = calloc(1, sizeof(*impl));
+    HextContext* hc;
+    int rval = DAQ_ERROR;
 
-    if ( !impl )
+    hc = calloc(1, sizeof(*hc));
+    if (!hc)
     {
-        snprintf(errBuf, errMax, "%s: failed to allocate the ipfw context", DAQ_NAME);
-        return DAQ_ERROR_NOMEM;
+        SET_ERROR(modinst, "%s: Couldn't allocate memory for the new Hext context!", DAQ_NAME);
+        rval = DAQ_ERROR_NOMEM;
+        goto err;
     }
+    hc->modinst = modinst;
 
-    impl->snaplen = cfg->snaplen ? cfg->snaplen : DEF_BUF_SZ;
-    impl->dlt = DLT_USER;
+    hc->snaplen = daq_base_api.config_get_snaplen(modcfg) ? daq_base_api.config_get_snaplen(modcfg) : DEF_BUF_SZ;
+    hc->dlt = DLT_USER;
 
-    if ( !get_vars(impl, cfg, errBuf, errMax) )
+    const char* varKey, * varValue;
+    daq_base_api.config_first_variable(modcfg, &varKey, &varValue);
+    while (varKey)
     {
-        free(impl);
-        return DAQ_ERROR;
+        /* Retrieve the requested buffer size (default = 0) */
+        if (!strcmp(varKey, "dlt"))
+            hc->dlt = strtol(varValue, NULL, 10);
+        else
+        {
+            SET_ERROR(modinst, "%s: Unknown variable name: '%s'", DAQ_NAME, varKey);
+            rval = DAQ_ERROR_INVAL;
+            goto err;
+        }
+
+        daq_base_api.config_next_variable(modcfg, &varKey, &varValue);
     }
 
-    if ( cfg->name )
+    const char* filename = daq_base_api.config_get_input(modcfg);
+    if (filename)
     {
-        if ( !(impl->name = strdup(cfg->name)) )
+        if (!(hc->filename = strdup(filename)))
         {
-            snprintf(errBuf, errMax, "%s: failed to allocate the filename", DAQ_NAME);
-            free(impl);
-            return DAQ_ERROR_NOMEM;
+            SET_ERROR(modinst, "%s: Couldn't allocate memory for the filename!", DAQ_NAME);
+            rval = DAQ_ERROR_NOMEM;
+            goto err;
         }
     }
 
-    if ( !(impl->buf = malloc(impl->snaplen)) )
-    {
-        snprintf(errBuf, errMax, "%s: failed to allocate the ipfw buffer", DAQ_NAME);
-        hext_daq_shutdown(impl);
-        return DAQ_ERROR_NOMEM;
-    }
+    uint32_t pool_size = daq_base_api.config_get_msg_pool_size(modcfg);
+    rval = create_message_pool(hc, pool_size ? pool_size : HEXT_DEFAULT_POOL_SIZE);
+    if (rval != DAQ_SUCCESS)
+        goto err;
 
-    impl->state = DAQ_STATE_INITIALIZED;
+    *ctxt_ptr = hc;
 
-    *handle = impl;
     return DAQ_SUCCESS;
+
+err:
+    if (hc)
+    {
+        if (hc->filename)
+            free(hc->filename);
+        destroy_message_pool(hc);
+        free(hc);
+    }
+    return rval;
 }
 
-//-------------------------------------------------------------------------
+static void hext_daq_destroy(void* handle)
+{
+    HextContext* hc = (HextContext*) handle;
 
-static int hext_daq_start (void* handle)
+    if (hc->filename)
+        free(hc->filename);
+    destroy_message_pool(hc);
+    free(hc);
+}
+
+static int hext_daq_start(void* handle)
 {
-    HextImpl* impl = (HextImpl*)handle;
+    HextContext* hc = (HextContext*) handle;
 
-    if ( hext_setup(impl) )
+    if (hext_setup(hc))
         return DAQ_ERROR;
 
-    impl->state = DAQ_STATE_STARTED;
     return DAQ_SUCCESS;
 }
 
-static int hext_daq_stop (void* handle)
+static int hext_daq_interrupt(void* handle)
 {
-    HextImpl* impl = (HextImpl*)handle;
-    hext_cleanup(impl);
-    impl->state = DAQ_STATE_STOPPED;
+    HextContext* hc = (HextContext*) handle;
+    hc->interrupted = true;
     return DAQ_SUCCESS;
 }
 
-//-------------------------------------------------------------------------
-
-static int hext_daq_inject (
-    void* handle, const DAQ_PktHdr_t* hdr, const uint8_t* buf, uint32_t len, int rev)
+static int hext_daq_stop(void* handle)
 {
-    (void)handle;
-    (void)hdr;
-    (void)buf;
-    (void)len;
-    (void)rev;
-    return DAQ_ERROR;
-}
-
-//-------------------------------------------------------------------------
-
-static int hext_daq_acquire (
-    void* handle, int cnt, DAQ_Analysis_Func_t callback, DAQ_Meta_Func_t meta, void* user)
-{
-    HextImpl* impl = (HextImpl*)handle;
-    int hit = 0, miss = 0;
-    impl->stop = false;
+    HextContext* hc = (HextContext*) handle;
 
-    while ( hit < cnt || cnt <= 0 )
-    {
-        int status = hext_daq_process(impl, callback, meta, user);
+    if (hc->fp != stdin)
+        fclose(hc->fp);
 
-        if ( status > 0 )
-        {
-            hit++;
-            miss = 0;
-        }
-        else if ( status < 0 )
-            return status;
+    hc->fp = NULL;
 
-        else if ( ++miss == 2 || impl->stop )
-            break;
-    }
     return DAQ_SUCCESS;
 }
 
-//-------------------------------------------------------------------------
-
-static int hext_daq_breakloop (void* handle)
+static int hext_daq_ioctl(void* handle, DAQ_IoctlCmd cmd, void* arg, size_t arglen)
 {
-    HextImpl* impl = (HextImpl*)handle;
-    impl->stop = true;
-    return DAQ_SUCCESS;
-}
+    (void) handle;
 
-static DAQ_State hext_daq_check_status (void* handle)
-{
-    HextImpl* impl = (HextImpl*)handle;
-    return impl->state;
+    if (cmd == DIOCTL_QUERY_USR_PCI)
+    {
+        if (arglen != sizeof(DIOCTL_QueryUsrPCI))
+            return DAQ_ERROR_INVAL;
+        DIOCTL_QueryUsrPCI* qup = (DIOCTL_QueryUsrPCI*) arg;
+        if (!qup->msg)
+            return DAQ_ERROR_INVAL;
+        HextMsgDesc* desc = (HextMsgDesc*) qup->msg->priv;
+        qup->pci = &desc->pci;
+        return DAQ_SUCCESS;
+    }
+    return DAQ_ERROR_NOTSUP;
 }
 
-static int hext_daq_get_stats (void* handle, DAQ_Stats_t* stats)
+static int hext_daq_get_stats(void* handle, DAQ_Stats_t* stats)
 {
-    HextImpl* impl = (HextImpl*)handle;
-    *stats = impl->stats;
+    HextContext* hc = (HextContext*) handle;
+    memcpy(stats, &hc->stats, sizeof(DAQ_Stats_t));
     return DAQ_SUCCESS;
 }
 
-static void hext_daq_reset_stats (void* handle)
+static void hext_daq_reset_stats(void* handle)
 {
-    HextImpl* impl = (HextImpl*)handle;
-    memset(&impl->stats, 0, sizeof(impl->stats));
+    HextContext* hc = (HextContext*) handle;
+    memset(&hc->stats, 0, sizeof(hc->stats));
 }
 
 static int hext_daq_get_snaplen (void* handle)
 {
-    HextImpl* impl = (HextImpl*)handle;
-    return impl->snaplen;
+    HextContext* hc = (HextContext*) handle;
+    return hc->snaplen;
 }
 
-static uint32_t hext_daq_get_capabilities (void* handle)
+static uint32_t hext_daq_get_capabilities(void* handle)
 {
-    (void)handle;
+    (void) handle;
     return DAQ_CAPA_BLOCK | DAQ_CAPA_REPLACE | DAQ_CAPA_INJECT | DAQ_CAPA_INJECT_RAW
-        | DAQ_CAPA_BREAKLOOP | DAQ_CAPA_UNPRIV_START;
+        | DAQ_CAPA_INTERRUPT | DAQ_CAPA_UNPRIV_START;
 }
 
-static int hext_daq_get_datalink_type(void *handle)
+static int hext_daq_get_datalink_type(voidhandle)
 {
-    HextImpl* impl = (HextImpl*)handle;
-    return impl->dlt;
+    HextContext* hc = (HextContext*) handle;
+    return hc->dlt;
 }
 
-static const char* hext_daq_get_errbuf (void* handle)
+static unsigned hext_daq_msg_receive(void* handle, const unsigned max_recv, const DAQ_Msg_t* msgs[], DAQ_RecvStatus* rstat)
 {
-    HextImpl* impl = (HextImpl*)handle;
-    return impl->error;
-}
+    HextContext* hc = (HextContext*) handle;
+    DAQ_RecvStatus status = DAQ_RSTAT_OK;
+    unsigned idx = 0;
 
-static void hext_daq_set_errbuf (void* handle, const char* s)
-{
-    HextImpl* impl = (HextImpl*)handle;
-    DPE(impl->error, "%s", s ? s : "");
-}
+    while (idx < max_recv)
+    {
+        /* Check to see if the receive has been canceled.  If so, reset it and return appropriately. */
+        if (hc->interrupted)
+        {
+            hc->interrupted = false;
+            status = DAQ_RSTAT_INTERRUPTED;
+            break;
+        }
 
-static int hext_daq_get_device_index(void* handle, const char* device)
-{
-    (void)handle;
-    (void)device;
-    return DAQ_ERROR_NOTSUP;
+        /* Make sure that we have a message descriptor available to populate. */
+        HextMsgDesc* desc = hc->pool.freelist;
+        if (!desc)
+        {
+            status = DAQ_RSTAT_NOBUF;
+            break;
+        }
+
+        /* Attempt to read a message into the descriptor. */
+        status = hext_read_message(hc, desc);
+        if (status != DAQ_RSTAT_OK)
+            break;
+
+        /* Last, but not least, extract this descriptor from the free list and
+           place the message in the return vector. */
+        hc->pool.freelist = desc->next;
+        desc->next = NULL;
+        hc->pool.info.available--;
+        msgs[idx] = &desc->msg;
+
+        idx++;
+    }
+
+    *rstat = status;
+
+    return idx;
 }
 
-static int hext_daq_set_filter (void* handle, const char* filter)
+static int hext_daq_msg_finalize(void* handle, const DAQ_Msg_t* msg, DAQ_Verdict verdict)
 {
-    (void)handle;
-    (void)filter;
-    return DAQ_ERROR_NOTSUP;
+    HextContext* hc = (HextContext*) handle;
+    HextMsgDesc* desc = (HextMsgDesc *) msg->priv;
+
+    if (verdict >= MAX_DAQ_VERDICT)
+        verdict = DAQ_VERDICT_PASS;
+    hc->stats.verdicts[verdict]++;
+
+    /* Toss the descriptor back on the free list for reuse. */
+    desc->next = hc->pool.freelist;
+    hc->pool.freelist = desc;
+    hc->pool.info.available++;
+
+    return DAQ_SUCCESS;
 }
 
-static int hext_query_flow(void* handle, const DAQ_PktHdr_t* hdr, DAQ_QueryFlow_t* query)
+static int hext_daq_get_msg_pool_info(void* handle, DAQ_MsgPoolInfo_t* info)
 {
-    HextImpl* impl = (HextImpl*)handle;
+    HextContext* hc = (HextContext*) handle;
 
-    if ( hdr->priv_ptr != &impl->pci )  // sanity check
-        return DAQ_ERROR_INVAL;
+    *info = hc->pool.info;
 
-    if ( query->type == DAQ_USR_QUERY_PCI )
-    {
-        query->value = &impl->pci;
-        query->length = sizeof(impl->pci);
-        return DAQ_SUCCESS;
-    }
-    return DAQ_ERROR_NOTSUP;
+    return DAQ_SUCCESS;
 }
 
 //-------------------------------------------------------------------------
 
 #ifdef BUILDING_SO
-DAQ_SO_PUBLIC DAQ_Module_t DAQ_MODULE_DATA =
+DAQ_SO_PUBLIC const DAQ_ModuleAPI_t DAQ_MODULE_DATA =
 #else
-DAQ_Module_t hext_daq_module_data =
+const DAQ_ModuleAPI_t hext_daq_module_data =
 #endif
 {
-    .api_version = DAQ_API_VERSION,
-    .module_version = DAQ_MOD_VERSION,
-    .name = DAQ_NAME,
-    .type = DAQ_TYPE,
-    .initialize = hext_daq_initialize,
-    .set_filter = hext_daq_set_filter,
-    .start = hext_daq_start,
-    .acquire = hext_daq_acquire,
-    .inject = hext_daq_inject,
-    .breakloop = hext_daq_breakloop,
-    .stop = hext_daq_stop,
-    .shutdown = hext_daq_shutdown,
-    .check_status = hext_daq_check_status,
-    .get_stats = hext_daq_get_stats,
-    .reset_stats = hext_daq_reset_stats,
-    .get_snaplen = hext_daq_get_snaplen,
-    .get_capabilities = hext_daq_get_capabilities,
-    .get_datalink_type = hext_daq_get_datalink_type,
-    .get_errbuf = hext_daq_get_errbuf,
-    .set_errbuf = hext_daq_set_errbuf,
-    .get_device_index = hext_daq_get_device_index,
-    .modify_flow = NULL,
-    .hup_prep = NULL,
-    .hup_apply = NULL,
-    .hup_post = NULL,
-    .dp_add_dc = NULL,
-    .query_flow = hext_query_flow
+    /* .api_version = */ DAQ_MODULE_API_VERSION,
+    /* .api_size = */ sizeof(DAQ_ModuleAPI_t),
+    /* .module_version = */ DAQ_MOD_VERSION,
+    /* .name = */ DAQ_NAME,
+    /* .type = */ DAQ_TYPE,
+    /* .load = */ hext_daq_module_load,
+    /* .unload = */ NULL,
+    /* .get_variable_descs = */ hext_daq_get_variable_descs,
+    /* .instantiate = */ hext_daq_instantiate,
+    /* .destroy = */ hext_daq_destroy,
+    /* .set_filter = */ NULL,
+    /* .start = */ hext_daq_start,
+    /* .inject = */ NULL,
+    /* .inject_relative = */ NULL,
+    /* .interrupt = */ hext_daq_interrupt,
+    /* .stop = */ hext_daq_stop,
+    /* .ioctl = */ hext_daq_ioctl,
+    /* .get_stats = */ hext_daq_get_stats,
+    /* .reset_stats = */ hext_daq_reset_stats,
+    /* .get_snaplen = */ hext_daq_get_snaplen,
+    /* .get_capabilities = */ hext_daq_get_capabilities,
+    /* .get_datalink_type = */ hext_daq_get_datalink_type,
+    /* .config_load = */ NULL,
+    /* .config_swap = */ NULL,
+    /* .config_free = */ NULL,
+    /* .msg_receive = */ hext_daq_msg_receive,
+    /* .msg_finalize = */ hext_daq_msg_finalize,
+    /* .get_msg_pool_info = */ hext_daq_get_msg_pool_info,
 };
 
index 5f62c13257107fa102c6013a0ae93f4391184e32..afaada6eff5ad6927dbdca94ee3d9452ef213374 100644 (file)
 #define DAQ_USER_H
 
 #include <stdint.h>
+#include <daq_common.h>
 
 /* for raw payload only */
 #define DLT_USER 230
 
-/* in: DAQ_QueryFlow_t.type */
-#define DAQ_USR_QUERY_PCI       1000
-
 /* DAQ_UsrHdr_t.flags */
 #define DAQ_USR_FLAG_TO_SERVER  0x01
 #define DAQ_USR_FLAG_START_FLOW 0x02
 #define DAQ_USR_FLAG_END_FLOW   0x04
 
-/* out: DAQ_QueryFlow_t.value */
 typedef struct
 {
     uint32_t src_addr;
@@ -46,5 +43,12 @@ typedef struct
     uint8_t flags;
 } DAQ_UsrHdr_t;
 
+#define DIOCTL_QUERY_USR_PCI    (DAQ_IoctlCmd) 2048
+typedef struct
+{
+    DAQ_Msg_h msg;
+    DAQ_UsrHdr_t* pci;
+} DIOCTL_QueryUsrPCI;
+
 #endif
 
index c9ea01edc4f5ca4ed604ee7a24f23826e9e6ecc2..902334408a0ac22ed0b7051faa76868455d08111 100644 (file)
@@ -5,8 +5,17 @@
 
 daq =
 {
-    module = 'dump',
-    variables = { "load-mode=read-file", "output=none" }
+    modules =
+    {
+        {
+            name = 'pcap',
+            mode = 'read-file'
+        },
+        {
+            name = 'dump',
+            variables = { 'output = none' }
+        },
+    },
 }
 
 normalizer = { tcp = { ips = true } }
index 42a57c5ed6477835826e8e53565b819f759e8a5d..c3262bc4b51f8fed0ba48e94ca8cb8d028bc4583 100644 (file)
@@ -5,9 +5,19 @@
 
 daq =
 {
-    module = 'dump',
-    variables = { "load-mode=read-file", "output=none" }
+    modules =
+    {
+        {
+            name = 'pcap',
+            mode = 'read-file'
+        },
+        {
+            name = 'dump',
+            variables = { 'output = none' }
+        },
+    },
 }
+
 normalizer = { tcp = { ips = true } }
 
 ips.include = 'local.rules'
index 679bfdc22f13d3a2da9bdeb6ddd8f5a876f855f0..327c512b207e50396520697f250565e2a6b4d702 100644 (file)
@@ -48,6 +48,10 @@ if ( USE_TIRPC )
     LIST(APPEND EXTERNAL_INCLUDES ${TIRPC_INCLUDE_DIRS})
 endif ()
 
+if ( ENABLE_STATIC_DAQ )
+    LIST(APPEND EXTERNAL_LIBRARIES ${DAQ_STATIC_MODULE_LIBS})
+endif ()
+
 include_directories(BEFORE ${LUAJIT_INCLUDE_DIR})
 include_directories(AFTER ${EXTERNAL_INCLUDES})
 
index 9fc599325a856ceab24cf4ac0e69995068eeb35f..f47d11a0f6d2f2022e6c41b1226acb1fa0e392e3 100644 (file)
@@ -22,7 +22,7 @@
 #include "config.h"
 #endif
 
-#include <sfbpf_dlt.h>
+#include <daq_dlt.h>
 
 #include <random>
 
index 7dadfd86d3b93196c9c0b5ad9fd8b1e9ebdc0953..72b12400039b8cb927e2b9e317fffe6d247c8ff6 100644 (file)
@@ -22,7 +22,7 @@
 #include "config.h"
 #endif
 
-#include <sfbpf_dlt.h>
+#include <daq_dlt.h>
 
 #include "codecs/codec_module.h"
 #include "framework/codec.h"
index 5a4d069f2f0233a2eb9eaacd00c84e69346ddda2..54e4a3c12eea56b30e6411038f01448f43b7fe73 100644 (file)
@@ -26,6 +26,7 @@
 #include "daqs/daq_user.h"
 #include "framework/codec.h"
 #include "packet_io/sfdaq.h"
+#include "packet_io/sfdaq_instance.h"
 
 using namespace snort;
 
@@ -98,15 +99,12 @@ static void set_flags(
 
 bool UserCodec::decode(const RawData& raw, CodecData& codec, DecodeData& snort)
 {
-    DAQ_QueryFlow_t query { DAQ_USR_QUERY_PCI, 0, nullptr };
+    DIOCTL_QueryUsrPCI qup = { raw.daq_msg, nullptr };
 
-    if ( SFDAQ::get_local_instance()->query_flow(raw.pkth, &query) != DAQ_SUCCESS or
-        query.length != sizeof(DAQ_UsrHdr_t) )
-    {
+    if ( SFDAQ::get_local_instance()->ioctl(DIOCTL_QUERY_USR_PCI, &qup, sizeof(qup)) != DAQ_SUCCESS )
         return false;
-    }
 
-    const DAQ_UsrHdr_t* pci = (DAQ_UsrHdr_t*)query.value;
+    const DAQ_UsrHdr_t* pci = qup.pci;
 
     if ( !pci )
         return false;
index a602af2c705e90b3d9aa68cf672cb6e03302e8a8..531689b98c1b75d1b538d1404d931a189dd4cb83 100644 (file)
@@ -22,7 +22,7 @@
 #include "config.h"
 #endif
 
-#include <sfbpf_dlt.h>
+#include <daq_dlt.h>
 
 #include "codecs/codec_module.h"
 #include "framework/codec.h"
index 776c089e7d8c6cfdf6a69a17ed0e4d8baa753388..c106ee90cea8f328e0af1ac876b91a1a39d11293 100644 (file)
@@ -21,7 +21,7 @@
 #include "config.h"
 #endif
 
-#include <sfbpf_dlt.h>
+#include <daq_dlt.h>
 
 #include "framework/codec.h"
 
index 5a0b91885978136836b896f6809b2dd532e6cce7..46b53c0ab136ffc74c4d5d600c77a56f2f2f49aa 100644 (file)
@@ -87,24 +87,21 @@ void ContextSwitcher::start()
 
 void ContextSwitcher::stop()
 {
-    assert(busy.size() == 1);
-
     IpsContext* c = busy.back();
+    assert(c);
     assert(c->state == IpsContext::BUSY);
-
     assert(!c->has_callbacks());
     assert(!c->dependencies());
 
     trace_logf(detection, TRACE_DETECTION_ENGINE, "(wire) %" PRIu64 " cs::stop %" PRIu64 " (i=%zu, b=%zu)\n",
         get_packet_number(), c->context_num, idle.size(), busy.size());
 
-    busy.pop_back();
-
     c->clear_context_data();
     c->packet->active = nullptr;
     c->packet->action = nullptr;
     c->state = IpsContext::IDLE;
 
+    busy.pop_back();
     idle.emplace_back(c);
 }
 
index 1c0522497cedb193f106ed0343ee8007c0507291..67eee2d1f3f5c2fde5f8b8600635438f804badf0 100644 (file)
@@ -30,8 +30,8 @@
 #include "framework/endianness.h"
 #include "helpers/ring.h"
 #include "latency/packet_latency.h"
+#include "main/analyzer.h"
 #include "main/modules.h"
-#include "main/snort.h"
 #include "main/snort_config.h"
 #include "main/snort_debug.h"
 #include "main/thread.h"
@@ -101,40 +101,44 @@ void DetectionEngine::thread_term()
 
 DetectionEngine::DetectionEngine()
 {
-    context = Snort::get_switcher()->interrupt();
+    context = Analyzer::get_switcher()->interrupt();
     context->file_data = { nullptr, 0 };
     reset();
 }
 
 DetectionEngine::~DetectionEngine()
 {
-    if ( context == Snort::get_switcher()->get_context() )
+    if ( context == Analyzer::get_switcher()->get_context() )
     {
         // finish_packet is called here so that we clear wire packets at the right time
+        // FIXIT-L if might not be needed anymore with wire packet checks in finish_packet
         finish_packet(context->packet, true);
     }
 }
 
 void DetectionEngine::reset()
 {
-    IpsContext* c = Snort::get_switcher()->get_context();
+    IpsContext* c = Analyzer::get_switcher()->get_context();
     c->alt_data.len = 0;  // FIXIT-H need context::reset()
 }
 
 IpsContext* DetectionEngine::get_context()
-{ return Snort::get_switcher()->get_context(); }
+{ return Analyzer::get_switcher()->get_context(); }
 
 SF_EVENTQ* DetectionEngine::get_event_queue()
-{ return Snort::get_switcher()->get_context()->equeue; }
+{ return Analyzer::get_switcher()->get_context()->equeue; }
 
 Packet* DetectionEngine::get_current_packet()
-{ return Snort::get_switcher()->get_context()->packet; }
+{ return Analyzer::get_switcher()->get_context()->packet; }
+
+Packet* DetectionEngine::get_current_wire_packet()
+{ return Analyzer::get_switcher()->get_context()->wire_packet; }
 
 void DetectionEngine::set_encode_packet(Packet* p)
-{ Snort::get_switcher()->get_context()->encode_packet = p; }
+{ Analyzer::get_switcher()->get_context()->encode_packet = p; }
 
 Packet* DetectionEngine::get_encode_packet()
-{ return Snort::get_switcher()->get_context()->encode_packet; }
+{ return Analyzer::get_switcher()->get_context()->encode_packet; }
 
 // we need to stay in the current context until rebuild is successful
 // any events while rebuilding will be logged against the current packet
@@ -145,14 +149,18 @@ Packet* DetectionEngine::set_next_packet(Packet* parent)
     static THREAD_LOCAL IpsAction* shutdown_action = nullptr;
 
     wait_for_context();
-    IpsContext* c = Snort::get_switcher()->get_next();
-    if ( parent ) // FIXIT-L parent can probably be determined by busy queue
+    IpsContext* c = Analyzer::get_switcher()->get_next();
+    if ( parent )
     {
         c->snapshot_flow(parent->flow);
         c->packet_number = parent->context->packet_number;
+        c->wire_packet = parent->context->wire_packet;
     }
     else
+    {
         c->packet_number = get_packet_number();
+        c->wire_packet = nullptr;
+    }
 
     Packet* p = c->packet;
 
@@ -163,13 +171,17 @@ Packet* DetectionEngine::set_next_packet(Packet* parent)
     // normal rebuild
     if ( parent )
     {
+        p->daq_msg = parent->daq_msg;
+        p->daq_instance = parent->daq_instance;
         p->active = parent->active;
         p->action = parent->action;
     }
     
     // processing but parent is already gone (flow cache flush etc..)
-    else if ( Snort::get_switcher()->get_context() )
+    else if ( Analyzer::get_switcher()->get_context() )
     {
+        p->daq_msg = nullptr;
+        p->daq_instance = nullptr;
         p->active = get_current_packet()->active;
         p->action = get_current_packet()->action;
     }
@@ -177,6 +189,8 @@ Packet* DetectionEngine::set_next_packet(Packet* parent)
     // shutdown, so use a dummy so null checking is not needed everywhere
     else
     {
+        p->daq_msg = nullptr;
+        p->daq_instance = nullptr;
         p->action = &shutdown_action;
         p->active = &shutdown_active;
         shutdown_active.reset();
@@ -221,7 +235,7 @@ void DetectionEngine::finish_inspect(Packet* p, bool inspected)
 
 void DetectionEngine::finish_packet(Packet* p, bool flow_deletion)
 {
-    ContextSwitcher* sw = Snort::get_switcher();
+    ContextSwitcher* sw = Analyzer::get_switcher();
 
     log_events(p);
     clear_events(p);
@@ -236,27 +250,18 @@ void DetectionEngine::finish_packet(Packet* p, bool flow_deletion)
 
     if ( flow_deletion or p->is_rebuilt() )
         sw->complete();
-
-    // FIXIT-H enable for daqng
-#if 0
-    if ( !p->is_rebuilt() )
-    {
-        sw->stop();
-        queue for daq msg finalize
-    }
-#endif
 }
 
 uint8_t* DetectionEngine::get_buffer(unsigned& max)
 {
     max = IpsContext::buf_size;
-    return Snort::get_switcher()->get_context()->buf;
+    return Analyzer::get_switcher()->get_context()->buf;
 }
 
 uint8_t* DetectionEngine::get_next_buffer(unsigned& max)
 {
     max = IpsContext::buf_size;
-    return Snort::get_switcher()->get_next()->buf;
+    return Analyzer::get_switcher()->get_next()->buf;
 }
 
 DataBuffer& DetectionEngine::get_alt_buffer(Packet* p)
@@ -266,23 +271,23 @@ DataBuffer& DetectionEngine::get_alt_buffer(Packet* p)
 }
 
 void DetectionEngine::set_file_data(const DataPointer& dp)
-{ Snort::get_switcher()->get_context()->file_data = dp; }
+{ Analyzer::get_switcher()->get_context()->file_data = dp; }
 
 DataPointer& DetectionEngine::get_file_data(IpsContext* c)
 { return c->file_data; }
 
 void DetectionEngine::set_data(unsigned id, IpsContextData* p)
-{ Snort::get_switcher()->get_context()->set_context_data(id, p); }
+{ Analyzer::get_switcher()->get_context()->set_context_data(id, p); }
 
 IpsContextData* DetectionEngine::get_data(unsigned id)
-{ return Snort::get_switcher()->get_context()->get_context_data(id); }
+{ return Analyzer::get_switcher()->get_context()->get_context_data(id); }
 
 IpsContextData* DetectionEngine::get_data(unsigned id, IpsContext* context)
 {
     if ( context )
         return context->get_context_data(id);
 
-    ContextSwitcher* sw = Snort::get_switcher();
+    ContextSwitcher* sw = Analyzer::get_switcher();
 
     if ( !sw )
         return nullptr;
@@ -296,26 +301,26 @@ void DetectionEngine::add_replacement(const std::string& s, unsigned off)
 
     r.data = s;
     r.offset = off;
-    Snort::get_switcher()->get_context()->rpl.emplace_back(r); 
+    Analyzer::get_switcher()->get_context()->rpl.emplace_back(r); 
 }
 
 bool DetectionEngine::get_replacement(std::string& s, unsigned& off)
 { 
-    if ( Snort::get_switcher()->get_context()->rpl.empty() )
+    if ( Analyzer::get_switcher()->get_context()->rpl.empty() )
         return false;
 
-    auto rep = Snort::get_switcher()->get_context()->rpl.back();
+    auto rep = Analyzer::get_switcher()->get_context()->rpl.back();
 
     s = rep.data;
     off = rep.offset;
 
-    Snort::get_switcher()->get_context()->rpl.pop_back();
+    Analyzer::get_switcher()->get_context()->rpl.pop_back();
     return true;
 }
 
 void DetectionEngine::clear_replacement()
 {
-    Snort::get_switcher()->get_context()->rpl.clear();
+    Analyzer::get_switcher()->get_context()->rpl.clear();
 }
 
 void DetectionEngine::disable_all(Packet* p)
@@ -346,10 +351,10 @@ void DetectionEngine::set_detects(Packet* p, IpsContext::ActiveRules ar)
 { p->context->active_rules = ar; }
 
 void DetectionEngine::set_check_tags(bool enable)
-{ Snort::get_switcher()->get_context()->check_tags = enable; }
+{ Analyzer::get_switcher()->get_context()->check_tags = enable; }
 
 bool DetectionEngine::get_check_tags()
-{ return Snort::get_switcher()->get_context()->check_tags; }
+{ return Analyzer::get_switcher()->get_context()->check_tags; }
 
 //--------------------------------------------------------------------------
 // offload / onload
@@ -357,7 +362,7 @@ bool DetectionEngine::get_check_tags()
 
 bool DetectionEngine::do_offload(Packet* p)
 {
-    ContextSwitcher* sw = Snort::get_switcher();
+    ContextSwitcher* sw = Analyzer::get_switcher();
 
     assert(p == p->context->packet);
     assert(p->context == sw->get_context());
@@ -401,7 +406,7 @@ bool DetectionEngine::do_offload(Packet* p)
 
 bool DetectionEngine::offload(Packet* p)
 {
-    ContextSwitcher* sw = Snort::get_switcher();
+    ContextSwitcher* sw = Analyzer::get_switcher();
 
     bool depends_on_suspended = p->flow ? p->flow->context_chain.front() : sw->non_flow_chain.front();
     bool can_offload = offloader->available();
@@ -458,14 +463,15 @@ void DetectionEngine::onload(Flow* flow)
 
 void DetectionEngine::onload()
 {
-    for( Packet* p; offloader->count() and offloader->get(p); )
+    Packet* p;
+    while (offloader->count() and offloader->get(p))
     {
         trace_logf(detection, TRACE_DETECTION_ENGINE, "%" PRIu64 " de::onload %" PRIu64 " (r=%d)\n",
             p->context->packet_number, p->context->context_num, offloader->count());
         
         p->clear_offloaded();
         
-        IpsContextChain& chain = p->flow ? p->flow->context_chain : Snort::get_switcher()->non_flow_chain;
+        IpsContextChain& chain = p->flow ? p->flow->context_chain : Analyzer::get_switcher()->non_flow_chain;
         
         resume_ready_suspends(chain);
     }
@@ -482,17 +488,25 @@ void DetectionEngine::resume(Packet* p)
     trace_logf(detection, TRACE_DETECTION_ENGINE, "%" PRIu64 " de::resume %" PRIu64 " (r=%d)\n",
         p->context->packet_number, p->context->context_num, offloader->count());
 
-    Snort::get_switcher()->resume(p->context);
+    ContextSwitcher* sw = Analyzer::get_switcher();
+    sw->resume(p->context);
     
     fp_complete(p);
     finish_inspect_with_latency(p); // FIXIT-L should latency be evaluated here?
     finish_inspect(p, true);
     finish_packet(p);
+
+    if ( !p->is_rebuilt() )
+    {
+        // This happens here to ensure needed contexts are available ASAP as
+        // not directly forwarding leads to deadlocking waiting on new contexts
+        Analyzer::get_local_analyzer()->post_process_packet(p);
+    }
 }
 
 void DetectionEngine::wait_for_context()
 {
-    ContextSwitcher* sw = Snort::get_switcher();
+    ContextSwitcher* sw = Analyzer::get_switcher();
 
     if ( !sw->idle_count() )
     {
@@ -576,6 +590,7 @@ bool DetectionEngine::inspect(Packet* p)
         finish_inspect_with_latency(p);
     }
     finish_inspect(p, inspected);
+
     return true;
 }
 
index 07665cb25a8233bb9d56d61f960c371546b417c5..c533a25daeebe31cf2306defd36ac5db32550947 100644 (file)
@@ -56,6 +56,7 @@ public:
     static IpsContext* get_context();
 
     static Packet* get_current_packet();
+    static Packet* get_current_wire_packet();
     static Packet* set_next_packet(Packet* parent = nullptr);
     static uint8_t* get_next_buffer(unsigned& max);
 
@@ -101,6 +102,8 @@ public:
     static void set_check_tags(bool enable = true);
     static bool get_check_tags();
 
+    static void wait_for_context();
+
 private:
     static struct SF_EVENTQ* get_event_queue();
     static bool do_offload(snort::Packet*);
@@ -113,7 +116,6 @@ private:
     static void finish_inspect_with_latency(Packet*);
     static void finish_inspect(Packet*, bool inspected);
     static void finish_packet(Packet*, bool flow_deletion = false);
-    static void wait_for_context();
 
 private:
     IpsContext* context;
index 4bc4060c52d73eaece6836ed5c5c1a72721573ad..8481fdfba4162b91eaa1fd7af5fd3b5bf1f6bfd5 100644 (file)
@@ -86,7 +86,7 @@ void EventTrace_Log(const Packet* p, const OptTreeNode* otn, int action)
     TextLog_Print(tlog,
         "Pkt=" STDu64 ", Sec=%lu.%6lu, Len=%u, Cap=%u\n",
         p->context->packet_number, (long)p->pkth->ts.tv_sec, (long)p->pkth->ts.tv_usec,
-        p->pkth->pktlen, p->pkth->caplen);
+        p->pkth->pktlen, p->pktlen);
 
     TextLog_Print(tlog,
         "Pkt Bits: Flags=0x%X, Proto=0x%X, Err=0x%X\n",
index a501e13f9513fef97e0baf70bbd8fd63e0ac916a..5793699e48d794b04a22c85012e224fdf5dde7b4 100644 (file)
@@ -135,6 +135,7 @@ public:
     std::vector<Replacement> rpl;
 
     Packet* packet;
+    Packet* wire_packet;
     Packet* encode_packet;
     DAQ_PktHdr_t* pkth;
     uint8_t* buf;
index 3a299c751d740f14179ddef53cb24a94337f8751..bdca30db0faaf1b7cd2621e941b9df99732c1629 100644 (file)
@@ -516,7 +516,7 @@ int CheckTagList(Packet* p, Event& event, void** log_list)
 
         if ( returned->metric & TAG_METRIC_BYTES )
         {
-            int n = p->pkth->caplen;
+            int n = p->pktlen;
             if ( n < returned->bytes )
                 returned->bytes -= n;
             else
index df1670329a67f9b5ea35543951f65d645d58813b..3d7a018452b08afa73efc4ce5ed261bd0b8e0044 100644 (file)
@@ -325,8 +325,7 @@ bool FileCache::apply_verdict(Packet* p, FileContext* file_ctx, FileVerdict verd
                 //  Won't add packet to retry queue if it is a retransmit
                 //  and not from the retry queue since it should already
                 //  be there.
-                if (!(p->packet_flags & PKT_RETRANSMIT) or
-                    p->pkth->flags & DAQ_PKT_FLAG_RETRY_PACKET)
+                if (!(p->packet_flags & PKT_RETRANSMIT) or p->is_retry())
                 {
                     PacketTracer::log("File signature lookup: adding packet to retry queue. Resume=%d, Waited %" PRIi64 "ms.\n", resume, time_elapsed_ms(&now, &file_ctx->pending_expire_time, lookup_timeout));
                 }
index 2e5b968bbbd77a79b619def7784b80a6659fd9bb..7299374a1e7eb3a41dcaaa47195be541fb44dc9a 100644 (file)
@@ -24,7 +24,7 @@
 #include "expect_cache.h"
 
 #include "hash/zhash.h"
-#include "packet_io/sfdaq.h"
+#include "packet_io/sfdaq_instance.h"
 #include "protocols/packet.h"
 #include "protocols/vlan.h"
 #include "pub_sub/expect_events.h"
@@ -402,7 +402,7 @@ int ExpectCache::add_flow(const Packet *ctrlPkt,
         last = nullptr;
         /* Only add TCP and UDP expected flows for now via the DAQ module. */
         if (ip_proto == IpProtocol::TCP || ip_proto == IpProtocol::UDP)
-            SFDAQ::get_local_instance()->add_expected(ctrlPkt, cliIP, cliPort, srvIP, srvPort,
+            ctrlPkt->daq_instance->add_expected(ctrlPkt, cliIP, cliPort, srvIP, srvPort,
                     ip_proto, 1000, 0);
     }
 
index 18415362c748c7913aaeafb93f19676d19242080..e23a33b5902a50825c06bb44f6aa31f086611736 100644 (file)
@@ -31,7 +31,8 @@
 #include "utils/cpp_macros.h"
 
 struct TextLog;
-struct _daq_pkthdr;
+struct _daq_msg;
+struct _daq_pkt_hdr;
 
 namespace snort
 {
@@ -65,11 +66,13 @@ constexpr uint8_t MAX_TTL = 255;
 
 struct RawData
 {
-    const _daq_pkthdr* pkth;
+    const struct _daq_msg* daq_msg;
+    const _daq_pkt_hdr* pkth;
     const uint8_t* data;
     uint32_t len;
 
-    RawData(const _daq_pkthdr*, const uint8_t*);
+    RawData(const struct _daq_msg* daq_msg, const _daq_pkt_hdr* pkth, const uint8_t* data, uint32_t len) :
+        daq_msg(daq_msg), pkth(pkth), data(data), len(len) { }
 };
 
 /*  Decode Flags */
index 5663945b4baf02f0ffbe32709a7a75d48bf1e31d..78d35ef2a63d3146168ba17103ceb4f4fcc04187 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "log/messages.h"
 #include "main.h"
-#include "main/snort.h"
+#include "main/oops_handler.h"
 #include "main/snort_config.h"
 #include "utils/stats.h"
 #include "utils/util.h"
@@ -159,7 +159,7 @@ static void oops_handler(int signal)
 {
     // FIXIT-L what should we capture if this is the main thread?
     if ( !is_main_thread )
-        snort::Snort::capture_packet();
+        OopsHandler::handle_crash();
 
     add_signal(signal, SIG_DFL, false);
     raise(signal);
index d4e2b3f77834cd47e18cd89e67790bbec71eee3a..bba61b109c300d869bb2181ae75cc32d01627237 100644 (file)
@@ -26,7 +26,7 @@
 
 #include "log_text.h"
 
-#include <sfbpf_dlt.h>
+#include <daq_dlt.h>
 
 #include "detection/detection_engine.h"
 #include "detection/signature.h"
@@ -1383,7 +1383,7 @@ void LogPayload(TextLog* log, Packet* p)
     }
     else if (SnortConfig::verbose_byte_dump())
     {
-        LogNetData(log, p->pkt, p->pkth->caplen, p);
+        LogNetData(log, p->pkt, p->pktlen, p);
     }
 }
 } // namespace snort
index 778a3acdd4d74f8b773ca32b92c1b28f730a9096..92c4a2085664a5975922882b1a3dbb2a3ed00fee 100644 (file)
@@ -222,7 +222,7 @@ static void ff_icmp_type(Args& a)
 
 static void ff_iface(Args&)
 {
-    TextLog_Print(csv_log, "%s", SFDAQ::get_interface_spec());
+    TextLog_Print(csv_log, "%s", SFDAQ::get_input_spec());
 }
 
 static void ff_ip_id(Args& a)
index 96c5f8b961ff142bc1086c5c98b314c9d4a7d6b7..39da8279ea09d07add14c37fc71b85eda9ad5cfc 100644 (file)
@@ -225,7 +225,7 @@ void FastLogger::alert(Packet* p, const char* msg, const Event& event)
         event.sig_info->gid, event.sig_info->sid, event.sig_info->rev);
 
     if (SnortConfig::alert_interface())
-        TextLog_Print(fast_log, " <%s> ", SFDAQ::get_interface_spec());
+        TextLog_Print(fast_log, " <%s> ", SFDAQ::get_input_spec());
 
     if ( msg )
         TextLog_Puts(fast_log, msg);
index 163ae03eda7fa02320f6e1821b7a75116ee242c7..5a508b658aa8b13762198a7436fb8f4274afcdfd 100644 (file)
@@ -157,7 +157,7 @@ void FullLogger::alert(Packet* p, const char* msg, const Event& event)
 
     if (SnortConfig::alert_interface())
     {
-        const char* iface = SFDAQ::get_interface_spec();
+        const char* iface = SFDAQ::get_input_spec();
         TextLog_Print(full_log, " <%s> ", iface);
     }
 
index a5ac7dde8e8d7b809af6a7189ed3dfdcfa746dc3..b5cb461237e2d8c3c34bcb67f63767455333ee67 100644 (file)
@@ -288,7 +288,7 @@ static bool ff_icmp_type(Args& a)
 static bool ff_iface(Args& a)
 {
     print_label(a, "iface");
-    TextLog_Quote(json_log, SFDAQ::get_interface_spec());
+    TextLog_Quote(json_log, SFDAQ::get_input_spec());
     return true;
 }
 
index 3342b31a37834c220f0fd0d99e751e55aa89162a..aa0217f582a0e087dcb0657f09eec824d0dbaae0 100644 (file)
@@ -226,7 +226,7 @@ static void AlertSyslog(
         if (SnortConfig::alert_interface())
         {
             SnortSnprintfAppend(event_string, sizeof(event_string),
-                "<%s> ", SFDAQ::get_interface_spec());
+                "<%s> ", SFDAQ::get_input_spec());
         }
     }
     if ((p != nullptr) && p->ptrs.ip_api.is_ip())
index db6bff1d7b09f1d83da365c6db2e04458f1e7906..a5dccd6727ecffbaec73d728c9543210246e40e8 100644 (file)
@@ -119,7 +119,7 @@ void TalosLogger::open()
 {
     talos_log = new AlertLog;
 
-    string ifname = string(SFDAQ::get_interface_spec());
+    string ifname = string(SFDAQ::get_input_spec());
     size_t sep_pos = ifname.find_last_of("/\\");
 
     if ( sep_pos != string::npos )
index 2f0ac7644d5f4c384951d65d32ac027824ed5f7a..8e1679da341249fbd00a9e8f600176c8b4f18ecb 100644 (file)
@@ -135,7 +135,7 @@ static void get_alert_pkt(
     {
         us.alert.pkth.ts.tv_sec = (uint32_t)p->pkth->ts.tv_sec;
         us.alert.pkth.ts.tv_usec = (uint32_t)p->pkth->ts.tv_usec;
-        us.alert.pkth.caplen = p->pkth->caplen;
+        us.alert.pkth.caplen = p->pktlen;
         us.alert.pkth.len = p->pkth->pktlen;
         memmove(us.alert.pkt, (const void*)p->pkt, us.alert.pkth.caplen);
     }
index a06a6da10e85afcb00a2fc587acd8f7cdb435a9a..b3c46c70d32c9320b4bc59b290c498dd793da183 100644 (file)
@@ -55,8 +55,8 @@ void DaqMetaEventHandler::handle(DataEvent& event, Flow*)
 
     const char* cmd;
     switch (ev->get_type()) {
-        case DAQ_METAHDR_TYPE_SOF: cmd = "sof"; break;
-        case DAQ_METAHDR_TYPE_EOF: cmd = "eof"; break;
+        case DAQ_MSG_TYPE_SOF: cmd = "sof"; break;
+        case DAQ_MSG_TYPE_EOF: cmd = "eof"; break;
         default: return;
     }
 
@@ -106,7 +106,7 @@ void DaqMetaEventHandler::handle(DataEvent& event, Flow*)
 static void log_raw(const Packet* p)
 {
     TextLog_Print(hext_log, "\n# %u [%u]\n",
-        s_pkt_num++, p->pkth->caplen);
+        s_pkt_num++, p->pktlen);
 }
 
 static void log_header(const Packet* p)
@@ -271,7 +271,7 @@ void HextLogger::log(Packet* p, const char*, Event*)
     if ( raw )
     {
         log_raw(p);
-        log_data(p->pkt, p->pkth->caplen, width);
+        log_data(p->pkt, p->pktlen, width);
     }
     else if ( p->has_tcp_data() )
     {
index 9ad6f807507f6d3d3525fff29df0de0de2eada29..b4228f9857f5d6506e65bf8d6364419b95fddd8e 100644 (file)
@@ -28,8 +28,9 @@
 #include "framework/module.h"
 #include "log/messages.h"
 #include "main/snort_config.h"
-#include "protocols/packet.h"
 #include "packet_io/sfdaq.h"
+#include "packet_io/sfdaq_config.h"
+#include "protocols/packet.h"
 #include "utils/util.h"
 
 using namespace snort;
@@ -119,22 +120,22 @@ bool TcpdumpModule::begin(const char*, int, SnortConfig*)
 // api stuff
 //-------------------------------------------------------------------------
 
-static inline size_t SizeOf(const DAQ_PktHdr_t* pkth)
+static inline size_t SizeOf(const Packet* p)
 {
-    return PCAP_PKT_HDR_SZ + pkth->caplen;
+    return PCAP_PKT_HDR_SZ + p->pktlen;
 }
 
 static void LogTcpdumpSingle(
     LtdConfig* data, Packet* p, const char*, Event*)
 {
-    size_t dumpSize = SizeOf(p->pkth);
+    size_t dumpSize = SizeOf(p);
 
     if ( data->limit && (context.size + dumpSize > data->limit) )
         TcpdumpRollLogFile(data);
 
     struct pcap_pkthdr pcaphdr;
     pcaphdr.ts = p->pkth->ts;
-    pcaphdr.caplen = p->pkth->caplen;
+    pcaphdr.caplen = p->pktlen;
     pcaphdr.len = p->pkth->pktlen;
     pcap_dump((uint8_t*)context.dumpd, &pcaphdr, p->pkt);
     context.size += dumpSize;
@@ -177,7 +178,7 @@ static void TcpdumpInitLogFile(LtdConfig*, bool no_timestamp)
         dlt = DLT_RAW;
 
     pcap_t* pcap;
-    pcap = pcap_open_dead(dlt, SFDAQ::get_snap_len());
+    pcap = pcap_open_dead(dlt, SnortConfig::get_conf()->daq_config->get_mru_size());
 
     if ( !pcap )
         FatalError("%s: can't get pcap context\n", S_NAME);
index 0ba6026866e4f479d87d90d77222dd2e5b7674a6..4f2cec023139f4b809c9a972018eb1d0e2e5aaca 100644 (file)
@@ -359,7 +359,7 @@ static void _Unified2LogPacketAlert(
     {
         logheader.packet_second = htonl((uint32_t)p->pkth->ts.tv_sec);
         logheader.packet_microsecond = htonl((uint32_t)p->pkth->ts.tv_usec);
-        pkt_length = ( p->is_rebuilt() ) ? p->dsize : p->pkth->caplen;
+        pkt_length = ( p->is_rebuilt() ) ? p->dsize : p->pktlen;
         logheader.packet_length = htonl(pkt_length + u2h_len);
         write_len += pkt_length + u2h_len;
     }
index 004c07a4e44ddeacc464cc57d60690186ce05c3a..c16b8a546f04bde1514a25ca28a418fc6824629b 100644 (file)
@@ -45,6 +45,8 @@
 #include "managers/module_manager.h"
 #include "managers/plugin_manager.h"
 #include "packet_io/sfdaq.h"
+#include "packet_io/sfdaq_config.h"
+#include "packet_io/sfdaq_instance.h"
 #include "packet_io/trough.h"
 #include "target_based/sftarget_reader.h"
 #include "time/periodic.h"
@@ -120,30 +122,44 @@ static int current_fd = -1;
 class Pig
 {
 public:
-    Analyzer* analyzer;
-    bool awaiting_privilege_change = false;
-
-    Pig() { analyzer = nullptr; athread = nullptr; idx = (unsigned)-1; }
+    Pig() = default;
 
     void set_index(unsigned index) { idx = index; }
 
-    void prep(const char* source);
+    bool prep(const char* source);
     void start();
     void stop();
 
     bool queue_command(AnalyzerCommand*, bool orphan = false);
     void reap_commands();
 
+    Analyzer* analyzer = nullptr;
+    bool awaiting_privilege_change = false;
+    bool requires_privileged_start = true;
+
 private:
     void reap_command(AnalyzerCommand* ac);
 
-    std::thread* athread;
-    unsigned idx;
+    std::thread* athread = nullptr;
+    unsigned idx = (unsigned)-1;
 };
 
-void Pig::prep(const char* source)
+bool Pig::prep(const char* source)
 {
-    analyzer = new Analyzer(idx, source);
+    SnortConfig* sc = SnortConfig::get_conf();
+    SFDAQInstance *instance = new SFDAQInstance(source, sc->daq_config);
+    if (!SFDAQ::init_instance(instance, sc->bpf_filter))
+    {
+        delete instance;
+        return false;
+    }
+    requires_privileged_start = instance->can_start_unprivileged();
+    analyzer = new Analyzer(instance, idx, source, sc->pkt_cnt);
+    analyzer->set_skip_cnt(sc->pkt_skip);
+#ifdef REG_TEST
+    analyzer->set_pause_after_cnt(sc->pkt_pause_cnt);
+#endif
+    return true;
 }
 
 void Pig::start()
@@ -545,15 +561,14 @@ int main_pause(lua_State* L)
 
 int main_resume(lua_State* L)
 {
-    const bool from_shell = ( L != nullptr );
-
-    int pkt_num = 0;
+    bool from_shell = ( L != nullptr );
+    uint64_t pkt_num = 0;
     if (from_shell)
     {
         const int num_of_args = lua_gettop(L);
         if (num_of_args)
         {
-            pkt_num = lua_tonumber(L, 1);
+            pkt_num = lua_tointeger(L, 1);
             if (pkt_num < 1)
             {
                 current_request->respond("Invalid usage of resume(n), n should be a number > 0\n");
@@ -714,14 +729,12 @@ static bool just_validate()
     if ( use_shell(SnortConfig::get_conf()) )
         return false;
 
-    /* FIXIT-L X This should really check if the DAQ module was unset as it could be explicitly
-        set to the default value */
-    if ( !strcmp(SFDAQ::get_type(), SFDAQ::default_type()) )
+    if ( SnortConfig::get_conf()->daq_config->module_configs.empty() )
     {
         if ( SnortConfig::read_mode() && !Trough::get_queue_size() )
             return true;
 
-        if ( !SnortConfig::read_mode() && !SFDAQ::get_input_spec(SnortConfig::get_conf(), 0) )
+        if ( !SnortConfig::read_mode() && !SFDAQ::get_input_spec(SnortConfig::get_conf()->daq_config, 0) )
             return true;
     }
 
@@ -795,7 +808,7 @@ static void handle(Pig& pig, unsigned& swine, unsigned& pending_privileges)
         break;
 
     case Analyzer::State::INITIALIZED:
-        if (pig.analyzer->requires_privileged_start() && pending_privileges &&
+        if (pig.requires_privileged_start && pending_privileges &&
             !Snort::has_dropped_privileges())
         {
             if (!pig.awaiting_privilege_change)
@@ -820,7 +833,7 @@ static void handle(Pig& pig, unsigned& swine, unsigned& pending_privileges)
         break;
 
     case Analyzer::State::STARTED:
-        if (!pig.analyzer->requires_privileged_start() && pending_privileges &&
+        if (!pig.requires_privileged_start && pending_privileges &&
             !Snort::has_dropped_privileges())
         {
             if (!pig.awaiting_privilege_change)
@@ -864,8 +877,11 @@ static void main_loop()
     // Preemptively prep all pigs in live traffic mode
     if (!SnortConfig::read_mode())
     {
-        for (swine = 0; swine < max_pigs; swine++)
-            pigs[swine].prep(SFDAQ::get_input_spec(SnortConfig::get_conf(), swine));
+        for (unsigned i = 0; i < max_pigs; i++)
+        {
+            if (pigs[i].prep(SFDAQ::get_input_spec(SnortConfig::get_conf()->daq_config, i)))
+                swine++;
+        }
     }
 
     // Iterate over the drove, spawn them as allowed, and handle their deaths.
@@ -911,8 +927,8 @@ static void main_loop()
         if ( !exit_requested and (swine < max_pigs) and (src = Trough::get_next()) )
         {
             Pig* pig = get_lazy_pig(max_pigs);
-            pig->prep(src);
-            ++swine;
+            if (pig->prep(src))
+                ++swine;
             continue;
         }
         service_check();
index 2dbea989157378bba5619d9e3d1025dc666f0440..fefd44e1782d8cf73a79b00f2115867fb3191b5b 100644 (file)
@@ -25,6 +25,8 @@ add_library (main OBJECT
     help.h
     modules.cc
     modules.h
+    oops_handler.cc
+    oops_handler.h
     policy.cc
     request.cc
     request.h
index ebda8a2d1f247012273d24b470d73acff805e4b7..4b3df8818b691cefd7b00dd29abc82ea7c3460b4 100644 (file)
@@ -16,7 +16,7 @@
 // with this program; if not, write to the Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //--------------------------------------------------------------------------
-// analyzer.cc author Russ Combs <rucombs@cisco.com>
+// analyzer.cc author Michael Altizer <mialtize@cisco.com>
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 
 #include "analyzer.h"
 
+#include <daq.h>
+
 #include <thread>
 
+#include "detection/context_switcher.h"
+#include "detection/detect.h"
+#include "detection/detection_engine.h"
+#include "detection/ips_context.h"
+#include "detection/tag.h"
+#include "file_api/file_service.h"
+#include "filters/detection_filter.h"
+#include "filters/sfthreshold.h"
+#include "flow/ha.h"
+#include "framework/data_bus.h"
+#include "latency/packet_latency.h"
+#include "latency/rule_latency.h"
 #include "log/messages.h"
 #include "main/swapper.h"
 #include "main.h"
+#include "managers/action_manager.h"
+#include "managers/inspector_manager.h"
+#include "managers/ips_manager.h"
+#include "managers/event_manager.h"
+#include "managers/module_manager.h"
+#include "packet_io/active.h"
 #include "packet_io/sfdaq.h"
+#include "packet_io/sfdaq_config.h"
+#include "packet_io/sfdaq_instance.h"
+#include "packet_tracer/packet_tracer.h"
+#include "profiler/profiler.h"
+#include "side_channel/side_channel.h"
+#include "stream/stream.h"
+#include "time/packet_time.h"
+#include "utils/stats.h"
 
 #include "analyzer_command.h"
+#include "oops_handler.h"
 #include "snort.h"
-#include "thread.h"
+#include "snort_config.h"
+#include "thread_config.h"
 
 using namespace snort;
 using namespace std;
 
-typedef DAQ_Verdict
-(* PacketCallback)(void*, const DAQ_PktHdr_t*, const uint8_t*);
+static MainHook_f main_hook = snort_ignore;
+
+THREAD_LOCAL ProfileStats totalPerfStats;
+static THREAD_LOCAL Analyzer* local_analyzer = nullptr;
+
+//-------------------------------------------------------------------------
+
+class RetryQueue
+{
+    struct Entry
+    {
+        Entry(const struct timeval& next_try, DAQ_Msg_h msg) : next_try(next_try), msg(msg) { }
+
+        struct timeval next_try;
+        DAQ_Msg_h msg;
+    };
+
+public:
+    RetryQueue(unsigned interval_ms)
+    {
+        assert(interval_ms > 0);
+        interval = { interval_ms / 1000, (interval_ms % 1000) * 1000 };
+    }
+
+    ~RetryQueue()
+    {
+        assert(empty());
+    }
+
+    void put(DAQ_Msg_h msg)
+    {
+        struct timeval now, next_try;
+        packet_gettimeofday(&now);
+        timeradd(&now, &interval, &next_try);
+        queue.emplace_back(next_try, msg);
+    }
+
+    DAQ_Msg_h get(const struct timeval* now = nullptr)
+    {
+        if (!empty())
+        {
+            const Entry& entry = queue.front();
+            if (!now || !timercmp(now, &entry.next_try, <))
+            {
+                DAQ_Msg_h msg = entry.msg;
+                queue.pop_front();
+                return msg;
+            }
+        }
+        return nullptr;
+    }
+
+    bool empty() const
+    {
+        return queue.empty();
+    }
+
+private:
+    deque<Entry> queue;
+    struct timeval interval;
+};
+
+//-------------------------------------------------------------------------
+
+/*
+ * Static Class Methods
+ */
+Analyzer* Analyzer::get_local_analyzer()
+{
+    return local_analyzer;
+}
+
+ContextSwitcher* Analyzer::get_switcher()
+{
+    assert(local_analyzer != nullptr);
+    return local_analyzer->switcher;
+}
+
+void Analyzer::set_main_hook(MainHook_f f)
+{
+    main_hook = f;
+}
+
+//-------------------------------------------------------------------------
+// message processing
+//-------------------------------------------------------------------------
+
+static void process_daq_sof_eof_msg(DAQ_Msg_h msg)
+{
+    const Flow_Stats_t *stats = (const Flow_Stats_t *) daq_msg_get_hdr(msg);
+
+    if (msg->type == DAQ_MSG_TYPE_EOF)
+        packet_time_update(&stats->eof_timestamp);
+    else
+        packet_time_update(&stats->sof_timestamp);
+
+    DataBus::publish(DAQ_META_EVENT, nullptr, daq_msg_get_type(msg), (const uint8_t*) stats);
+}
+
+static bool process_packet(Packet* p)
+{
+    assert(p->pkth && p->pkt);
+
+    aux_counts.rx_bytes += p->pktlen;
+
+    PacketTracer::activate(*p);
+
+    // FIXIT-M should not need to set policies here
+    set_default_policy();
+    p->user_inspection_policy_id = get_inspection_policy()->user_policy_id;
+    p->user_ips_policy_id = get_ips_policy()->user_policy_id;
+    p->user_network_policy_id = get_network_policy()->user_policy_id;
+
+    if ( !(p->packet_flags & PKT_IGNORE) )
+    {
+        clear_file_data();
+        // return incomplete status if the main hook indicates not all work was done
+        if (!main_hook(p))
+            return false;
+    }
+
+    return true;
+}
+
+// Finalize DAQ message verdict
+static DAQ_Verdict distill_verdict(Packet* p)
+{
+    DAQ_Verdict verdict = DAQ_VERDICT_PASS;
+    Active* act = p->active;
+
+    // First Pass
+    if ( act->packet_retry_requested() )
+    {
+        verdict = DAQ_VERDICT_RETRY;
+    }
+    else if ( act->session_was_blocked() )
+    {
+        if ( !act->can_block() )
+            verdict = DAQ_VERDICT_PASS;
+        else if ( act->get_tunnel_bypass() )
+        {
+            aux_counts.internal_blacklist++;
+            verdict = DAQ_VERDICT_BLOCK;
+        }
+        else if ( SnortConfig::inline_mode() || act->packet_force_dropped() )
+            verdict = DAQ_VERDICT_BLACKLIST;
+        else
+            verdict = DAQ_VERDICT_IGNORE;
+    }
+
+    // Second Pass, now with more side effects
+    if ( act->packet_was_dropped() && act->can_block() )
+    {
+        if ( verdict == DAQ_VERDICT_PASS )
+            verdict = DAQ_VERDICT_BLOCK;
+    }
+    else if ( verdict == DAQ_VERDICT_RETRY )
+    {
+    }
+    else if ( p->packet_flags & PKT_RESIZED )
+    {
+        // we never increase, only trim, but daq doesn't support resizing wire packet
+        PacketManager::encode_update(p);
+
+        if ( p->daq_instance->inject(p->daq_msg, 0, p->pkt, p->pktlen) == DAQ_SUCCESS )
+            verdict = DAQ_VERDICT_BLOCK;
+        // FIXIT-M X Should we be blocking the wire packet even if the injection fails?
+    }
+    else if ( p->packet_flags & PKT_MODIFIED )
+    {
+        // this packet was normalized and/or has replacements
+        PacketManager::encode_update(p);
+        verdict = DAQ_VERDICT_REPLACE;
+    }
+    else if ( (p->packet_flags & PKT_IGNORE) ||
+        (p->flow && p->flow->get_ignore_direction() == SSN_DIR_BOTH) )
+    {
+        if ( !act->get_tunnel_bypass() )
+        {
+            verdict = DAQ_VERDICT_WHITELIST;
+        }
+        else
+        {
+            verdict = DAQ_VERDICT_PASS;
+            aux_counts.internal_whitelist++;
+        }
+    }
+    else if ( p->ptrs.decode_flags & DECODE_PKT_TRUST )
+    {
+        if (p->flow)
+            p->flow->set_ignore_direction(SSN_DIR_BOTH);
+        verdict = DAQ_VERDICT_WHITELIST;
+    }
+    else
+        verdict = DAQ_VERDICT_PASS;
+
+    return verdict;
+}
+
+/*
+ * Private message processing methods
+ */
+void Analyzer::post_process_daq_pkt_msg(Packet* p)
+{
+    ActionManager::execute(p);
+
+    DAQ_Verdict verdict = distill_verdict(p);
+
+    if (PacketTracer::is_active())
+    {
+        PacketTracer::log("Policies: Network %u, Inspection %u, Detection %u\n",
+            get_network_policy()->user_policy_id, get_inspection_policy()->user_policy_id,
+            get_ips_policy()->user_policy_id);
+        PacketTracer::log("Verdict: %s\n", SFDAQ::verdict_to_string(verdict));
+
+        PacketTracer::dump(p);
+    }
+
+    HighAvailabilityManager::process_update(p->flow, p->pkth);
+
+    p->pkth = nullptr;  // no longer avail upon sig segv
+
+    if (verdict == DAQ_VERDICT_RETRY)
+        retry_queue->put(p->daq_msg);
+    else
+        p->daq_instance->finalize_message(p->daq_msg, verdict);
+}
+
+void Analyzer::process_daq_pkt_msg(DAQ_Msg_h msg, bool retry)
+{
+    const DAQ_PktHdr_t* pkthdr = daq_msg_get_pkthdr(msg);
+
+    set_default_policy();
+    Profile profile(totalPerfStats);
+
+    if (!retry)
+    {
+        pc.total_from_daq++;
+        packet_time_update(&pkthdr->ts);
+    }
+
+    DetectionEngine::wait_for_context();
+    switcher->start();
+    Packet* p = switcher->get_context()->packet;
+    oops_handler->set_current_packet(p);
+    p->context->wire_packet = p;
+    p->context->packet_number = pc.total_from_daq;
+
+    DetectionEngine::reset();
+
+    sfthreshold_reset();
+    ActionManager::reset_queue(p);
+
+    p->daq_msg = msg;
+    p->daq_instance = daq_instance;
+    PacketManager::decode(p, pkthdr, daq_msg_get_data(msg), daq_msg_get_data_len(msg), false, retry);
+    if (process_packet(p))
+    {
+        post_process_daq_pkt_msg(p);
+        switcher->stop();
+    }
+
+    Stream::timeout_flows(packet_time());
+    HighAvailabilityManager::process_receive();
+}
+
+void Analyzer::process_daq_msg(DAQ_Msg_h msg, bool retry)
+{
+    switch (daq_msg_get_type(msg))
+    {
+        case DAQ_MSG_TYPE_PACKET:
+            process_daq_pkt_msg(msg, retry);
+            // process_daq_pkt_msg() handles finalizing the message (or tracking it if offloaded)
+            return;
+        case DAQ_MSG_TYPE_SOF:
+        case DAQ_MSG_TYPE_EOF:
+            process_daq_sof_eof_msg(msg);
+            break;
+        default:
+            break;
+    }
+    daq_instance->finalize_message(msg, DAQ_VERDICT_PASS);
+}
+
+void Analyzer::process_retry_queue()
+{
+    if (!retry_queue->empty())
+    {
+        struct timeval now;
+        packet_gettimeofday(&now);
+        DAQ_Msg_h msg;
+        while ((msg = retry_queue->get(&now)) != nullptr)
+            process_daq_msg(msg, true);
+    }
+}
+
+/*
+ * Public packet processing methods
+ */
+bool Analyzer::inspect_rebuilt(Packet* p)
+{
+    // Need to include this b/c call is outside the detect tree
+    Profile detect_profile(detectPerfStats);
+    DeepProfile rebuilt_profile(rebuiltPacketPerfStats);
+
+    DetectionEngine de;
+    return main_hook(p);
+}
 
-// FIXIT-M add fail open capability
-static THREAD_LOCAL PacketCallback main_func = Snort::packet_callback;
+bool Analyzer::process_rebuilt_packet(Packet* p, const DAQ_PktHdr_t* pkthdr, const uint8_t* pkt, uint32_t pktlen)
+{
+    PacketManager::decode(p, pkthdr, pkt, pktlen, true);
+
+    p->packet_flags |= (PKT_PSEUDO | PKT_REBUILT_FRAG);
+    p->pseudo_type = PSEUDO_PKT_IP;
+
+    return process_packet(p);
+}
+
+void Analyzer::post_process_packet(Packet* p)
+{
+    post_process_daq_pkt_msg(p);
+    // FIXIT-? There is an assumption that this is being called on the active context...
+    switcher->stop();
+}
 
 //-------------------------------------------------------------------------
-// analyzer
+// Utility
 //-------------------------------------------------------------------------
 
+void Analyzer::show_source()
+{
+    const char* pcap = source.c_str();
+
+    if (!strcmp(pcap, "-"))
+        pcap = "stdin";
+
+    if (get_run_num() != 1)
+        fprintf(stdout, "%s", "\n");
+
+    fprintf(stdout, "Reading network traffic from \"%s\" with snaplen = %u\n",
+        pcap, SnortConfig::get_conf()->daq_config->get_mru_size());
+}
+
 void Analyzer::set_state(State s)
 {
     state = s;
@@ -60,47 +424,174 @@ const char* Analyzer::get_state_string()
 
     switch ( s )
     {
-    case State::NEW:         return "NEW";
-    case State::INITIALIZED: return "INITIALIZED";
-    case State::STARTED:     return "STARTED";
-    case State::RUNNING:     return "RUNNING";
-    case State::PAUSED:      return "PAUSED";
-    case State::STOPPED:     return "STOPPED";
-    default: assert(false);
+        case State::NEW:         return "NEW";
+        case State::INITIALIZED: return "INITIALIZED";
+        case State::STARTED:     return "STARTED";
+        case State::RUNNING:     return "RUNNING";
+        case State::PAUSED:      return "PAUSED";
+        case State::STOPPED:     return "STOPPED";
+        default: assert(false);
     }
 
     return "UNKNOWN";
 }
 
-Analyzer::Analyzer(unsigned i, const char* s)
+//-------------------------------------------------------------------------
+// Thread life cycle
+//-------------------------------------------------------------------------
+
+void Analyzer::idle()
+{
+    // FIXIT-L this whole thing could be pub-sub
+    DataBus::publish(THREAD_IDLE_EVENT, nullptr);
+    if (SnortConfig::read_mode())
+        Stream::timeout_flows(packet_time());
+    else
+        Stream::timeout_flows(time(nullptr));
+    aux_counts.idle++;
+    HighAvailabilityManager::process_receive();
+}
+
+/*
+ * Perform all packet thread initialization actions that can be taken with dropped privileges
+ * and/or must be called after the DAQ module has been started.
+ */
+void Analyzer::init_unprivileged()
+{
+    // using dummy values until further integration
+    const unsigned max_contexts = 20;
+
+    switcher = new ContextSwitcher;
+
+    for ( unsigned i = 0; i < max_contexts; ++i )
+        switcher->push(new IpsContext);
+
+    SnortConfig* sc = SnortConfig::get_conf();
+
+    CodecManager::thread_init(sc);
+
+    // this depends on instantiated daq capabilities
+    // so it is done here instead of init()
+    Active::thread_init(sc);
+
+    InitTag();
+    EventTrace_Init();
+    detection_filter_init(sc->detection_filter_config);
+    DetectionEngine::thread_init();
+
+    EventManager::open_outputs();
+    IpsManager::setup_options();
+    ActionManager::thread_init(sc);
+    FileService::thread_init();
+    SideChannelManager::thread_init();
+    HighAvailabilityManager::thread_init(); // must be before InspectorManager::thread_init();
+    InspectorManager::thread_init(sc);
+    PacketTracer::thread_init();
+
+    // in case there are HA messages waiting, process them first
+    HighAvailabilityManager::process_receive();
+    PacketManager::thread_init();
+}
+
+void Analyzer::reinit(SnortConfig* sc)
+{
+    InspectorManager::thread_reinit(sc);
+    ActionManager::thread_reinit(sc);
+}
+
+void Analyzer::term()
+{
+    SnortConfig* sc = SnortConfig::get_conf();
+
+    HighAvailabilityManager::thread_term_beginning();
+
+    if ( !sc->dirty_pig )
+        Stream::purge_flows();
+
+    DetectionEngine::idle();
+    InspectorManager::thread_stop(sc);
+    ModuleManager::accumulate(sc);
+    InspectorManager::thread_term(sc);
+    ActionManager::thread_term(sc);
+
+    IpsManager::clear_options();
+    EventManager::close_outputs();
+    CodecManager::thread_term();
+    HighAvailabilityManager::thread_term();
+    SideChannelManager::thread_term();
+
+    oops_handler->set_current_packet(nullptr);
+
+    if ( daq_instance->was_started() )
+    {
+        DAQ_Msg_h msg;
+        while ((msg = retry_queue->get()) != nullptr)
+            daq_instance->finalize_message(msg, DAQ_VERDICT_BLOCK);
+        daq_instance->stop();
+    }
+    SFDAQ::set_local_instance(nullptr);
+
+    PacketLatency::tterm();
+    RuleLatency::tterm();
+
+    Profiler::consolidate_stats();
+
+    DetectionEngine::thread_term();
+    detection_filter_term();
+    EventTrace_Term();
+    CleanupTag();
+    FileService::thread_term();
+    PacketTracer::thread_term();
+    PacketManager::thread_term();
+
+    Active::thread_term();
+    delete switcher;
+}
+
+Analyzer::Analyzer(SFDAQInstance* instance, unsigned i, const char* s, uint64_t msg_cnt)
 {
     id = i;
+    exit_after_cnt = msg_cnt;
     source = s ? s : "";
-    daq_instance = nullptr;
-    privileged_start = false;
-    exit_requested = false;
+    daq_instance = instance;
+    retry_queue = new RetryQueue(200);
     set_state(State::NEW);
 }
 
+Analyzer::~Analyzer()
+{
+    delete daq_instance;
+    delete oops_handler;
+    delete retry_queue;
+}
+
 void Analyzer::operator()(Swapper* ps, uint16_t run_num)
 {
+    oops_handler = new OopsHandler();
+
     set_thread_type(STHREAD_TYPE_PACKET);
     set_instance_id(id);
     set_run_num(run_num);
+    local_analyzer = this;
 
-    ps->apply();
+    ps->apply(*this);
     delete ps;
 
-    if (Snort::thread_init_privileged(source.c_str()))
-    {
-        daq_instance = SFDAQ::get_local_instance();
-        privileged_start = daq_instance->can_start_unprivileged();
-        set_state(State::INITIALIZED);
+    if (SnortConfig::pcap_show())
+        show_source();
 
-        analyze();
+    // Perform all packet thread initialization actions that need to be taken with escalated
+    // privileges prior to starting the DAQ module.
+    SnortConfig::get_conf()->thread_config->implement_thread_affinity(STHREAD_TYPE_PACKET,
+        get_instance_id());
 
-        Snort::thread_term();
-    }
+    SFDAQ::set_local_instance(daq_instance);
+    set_state(State::INITIALIZED);
+
+    // Start the main loop
+    analyze();
+
+    term();
 
     set_state(State::STOPPED);
 }
@@ -115,8 +606,8 @@ void Analyzer::execute(AnalyzerCommand* ac)
 
     /* Break out of the DAQ acquire loop so that the command will be processed.
         This is explicitly safe to call from another thread. */
-    if ( state == State::RUNNING and daq_instance )
-        daq_instance->break_loop(0);
+    if ( state >= State::STARTED and state < State::STOPPED and daq_instance )
+        daq_instance->interrupt();
 }
 
 bool Analyzer::handle_command()
@@ -143,38 +634,100 @@ bool Analyzer::handle_command()
     return true;
 }
 
-void Analyzer::analyze()
+void Analyzer::handle_commands()
 {
-    // The main analyzer loop is terminated by a command returning false or an error during acquire
-    while (!exit_requested)
+    while (handle_command())
+        ;
+}
+
+DAQ_RecvStatus Analyzer::process_messages()
+{
+    // Max receive becomes the minimum of the configured batch size, the remaining exit_after
+    // count (if requested), and the remaining pause_after count (if requested).
+    unsigned max_recv = daq_instance->get_batch_size();
+    if (exit_after_cnt && exit_after_cnt < max_recv)
+        max_recv = exit_after_cnt;
+    if (pause_after_cnt && pause_after_cnt < max_recv)
+        max_recv = pause_after_cnt;
+
+    DAQ_RecvStatus rstat = daq_instance->receive_messages(max_recv);
+
+    unsigned num_recv = 0;
+    DAQ_Msg_h msg;
+    while ((msg = daq_instance->next_message()) != nullptr)
     {
-        TestPause& s_pause = Snort::get_test_pause();
-        if (s_pause.get_pause())
+        // Dispose of any messages to be skipped first.
+        if (skip_cnt > 0)
         {
-            pause();
-            s_pause.clear_pause();
-            s_pause.set_pause_cnt(0);
-            snort::LogMessage("== paused\n");
-        }
-        if (handle_command())
+            aux_counts.skipped++;
+            skip_cnt--;
+            daq_instance->finalize_message(msg, DAQ_VERDICT_PASS);
             continue;
+        }
+        // FIXIT-M add fail open capability
+        // IMPORTANT: process_daq_msg() is responsible for finalizing the messages.
+        num_recv++;
+        process_daq_msg(msg, false);
+        DetectionEngine::onload();
+        process_retry_queue();
+    }
 
+    if (exit_after_cnt && (exit_after_cnt -= num_recv) == 0)
+        stop();
+    if (pause_after_cnt && (pause_after_cnt -= num_recv) == 0)
+        pause();
+    return rstat;
+}
+
+void Analyzer::analyze()
+{
+    while (!exit_requested)
+    {
         // If we're not in the running state (usually either pre-start or paused),
         // just keep stalling until something else comes up.
         if (state != State::RUNNING)
         {
-            chrono::milliseconds ms(10);
-            this_thread::sleep_for(ms);
+            if (!handle_command())
+            {
+                chrono::milliseconds ms(10);
+                this_thread::sleep_for(ms);
+            }
             continue;
         }
-        if (daq_instance->acquire(0, main_func))
-            break;
 
-        // FIXIT-L acquire(0) makes idle processing unlikely under high traffic
-        // because it won't return until no packets, signal, etc.  that means
-        // the idle processing may not be useful or that we need a hook to do
-        // things periodically even when traffic is available
-        Snort::thread_idle();
+        // Receive and process a batch of messages.  Evaluate the receive status after processing
+        // the returned messages to determine if we should immediately continue, take the opportunity
+        // to deal with some house cleaning work, or terminate the analyzer thread.
+        DAQ_RecvStatus rstat = process_messages();
+        if (rstat != DAQ_RSTAT_OK && rstat != DAQ_RSTAT_WOULD_BLOCK)
+        {
+            if (rstat == DAQ_RSTAT_TIMEOUT)
+            {
+                // If the receive timed out, let's do some idle work before continuing.
+                // FIXIT-L Hitting a one second timeout when attached to any real traffic source
+                // is extremely unlikely, so relying on anything in thread_idle() ever being
+                // called is dangerous.
+                idle();
+            }
+            else if (rstat == DAQ_RSTAT_INTERRUPTED)
+            {
+                // If the status reports INTERRUPTED because of an interrupt() call, exit_requested should
+                // be set for the next pass through the main loop.  Use this as a hint to check for analyzer
+                // commands.
+                handle_commands();
+            }
+            else
+            {
+                if (rstat == DAQ_RSTAT_NOBUF)
+                    ErrorMessage("Exhausted the DAQ message pool!\n");
+                else if (rstat == DAQ_RSTAT_ERROR)
+                    ErrorMessage("Error receiving message from the DAQ instance: %s\n", daq_instance->get_error());
+                // Implicitly handled:
+                // DAQ_RSTAT_EOF - File readback completed, job well done; let's get out of here.
+                // DAQ_RSTAT_INVALID - This really shouldn't happen.
+                break;
+            }
+        }
     }
 }
 
@@ -193,7 +746,7 @@ void Analyzer::start()
 void Analyzer::run(bool paused)
 {
     assert(state == State::STARTED);
-    Snort::thread_init_unprivileged();
+    init_unprivileged();
     if ( paused )
         set_state(State::PAUSED);
     else
@@ -217,12 +770,11 @@ void Analyzer::pause()
             get_state_string());
 }
 
-void Analyzer::resume(int pkt_cnt)
+void Analyzer::resume(uint64_t msg_cnt)
 {
     if (state == State::PAUSED)
     {
-        TestPause& s_pause = Snort::get_test_pause();
-        s_pause.set_pause_cnt(pkt_cnt);
+        set_pause_after_cnt(msg_cnt);
         set_state(State::RUNNING);
     }
     else
@@ -236,3 +788,8 @@ void Analyzer::reload_daq()
         daq_instance->reload();
 }
 
+void Analyzer::rotate()
+{
+    DataBus::publish(THREAD_ROTATE_EVENT, nullptr);
+}
+
index 9fb6a552e2e9ccc73aa3dd3808565f449f5a9d2f..b8a4c66708267fb64cc1a51a3e11c0437c887850 100644 (file)
@@ -15,7 +15,7 @@
 // with this program; if not, write to the Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //--------------------------------------------------------------------------
-// analyzer.h author Russ Combs <rucombs@cisco.com>
+// analyzer.h author Michael Altizer <mialtize@cisco.com>
 
 #ifndef ANALYZER_H
 #define ANALYZER_H
 // runs in a different thread, it also provides a command facility so that
 // to control the thread and swap configuration.
 
+#include <daq_common.h>
+
 #include <atomic>
 #include <mutex>
 #include <queue>
 #include <string>
 
+#include "thread.h"
+
 class AnalyzerCommand;
+class ContextSwitcher;
+class OopsHandler;
+class RetryQueue;
 class Swapper;
 
 namespace snort
 {
 class SFDAQInstance;
+struct Packet;
+struct SnortConfig;
+struct ProfileStats;
 }
 
+typedef bool (* MainHook_f)(snort::Packet*);
+
 class Analyzer
 {
 public:
@@ -49,7 +61,13 @@ public:
         STOPPED,
         NUM_STATES
     };
-    Analyzer(unsigned id, const char* source);
+
+    static Analyzer* get_local_analyzer();
+    static ContextSwitcher* get_switcher();
+    static void set_main_hook(MainHook_f);
+
+    Analyzer(snort::SFDAQInstance*, unsigned id, const char* source, uint64_t msg_cnt = 0);
+    ~Analyzer();
 
     void operator()(Swapper*, uint16_t run_num);
 
@@ -57,22 +75,40 @@ public:
     const char* get_state_string();
     const char* get_source() { return source.c_str(); }
 
+    void set_pause_after_cnt(uint64_t msg_cnt) { pause_after_cnt = msg_cnt; }
+    void set_skip_cnt(uint64_t msg_cnt) { skip_cnt = msg_cnt; }
+
     void execute(AnalyzerCommand*);
 
-    bool requires_privileged_start() { return privileged_start; }
+    void post_process_packet(snort::Packet*);
+    bool process_rebuilt_packet(snort::Packet*, const DAQ_PktHdr_t*, const uint8_t* pkt, uint32_t pktlen);
+    bool inspect_rebuilt(snort::Packet*);
 
     // Functions called by analyzer commands
     void start();
     void run(bool paused = false);
     void stop();
     void pause();
-    void resume(int pkt_cnt);
+    void resume(uint64_t msg_cnt);
     void reload_daq();
+    void reinit(snort::SnortConfig*);
+    void rotate();
 
 private:
     void analyze();
     bool handle_command();
+    void handle_commands();
+    DAQ_RecvStatus process_messages();
+    void process_daq_msg(DAQ_Msg_h, bool retry);
+    void process_daq_pkt_msg(DAQ_Msg_h, bool retry);
+    void post_process_daq_pkt_msg(snort::Packet*);
+    void process_retry_queue();
     void set_state(State);
+    void idle();
+    bool init_privileged();
+    void init_unprivileged();
+    void term();
+    void show_source();
 
 public:
     std::queue<AnalyzerCommand*> completed_work_queue;
@@ -81,16 +117,24 @@ public:
 
 private:
     std::atomic<State> state;
-    std::atomic<bool> privileged_start;
 
     unsigned id;
-    bool exit_requested;
+    bool exit_requested = false;
+
+    uint64_t exit_after_cnt;
+    uint64_t pause_after_cnt = 0;
+    uint64_t skip_cnt = 0;
 
     std::string source;
     snort::SFDAQInstance* daq_instance;
+    RetryQueue* retry_queue = nullptr;
+    OopsHandler* oops_handler = nullptr;
+    ContextSwitcher* switcher = nullptr;
 
     std::mutex pending_work_queue_mutex;
 };
 
+extern THREAD_LOCAL snort::ProfileStats totalPerfStats;
+
 #endif
 
index 479f1228362d3f3d5f7498ecbdce8eb362640a3d..ae2323bbaefb72660c951f6caf9d7732ca9f7107 100644 (file)
@@ -58,12 +58,12 @@ void ACPause::execute(Analyzer& analyzer)
 
 void ACResume::execute(Analyzer& analyzer)
 {
-    analyzer.resume(pkt_count);
+    analyzer.resume(msg_cnt);
 }
 
-void ACRotate::execute(Analyzer&)
+void ACRotate::execute(Analyzer& analyzer)
 {
-    snort::Snort::thread_rotate();
+    analyzer.rotate();
 }
 
 void ACGetStats::execute(Analyzer&)
@@ -89,10 +89,10 @@ ACSwap::ACSwap(Swapper* ps, Request* req, bool from_shell) : ps(ps), request(req
     Swapper::set_reload_in_progress(true);
 }
 
-void ACSwap::execute(Analyzer&)
+void ACSwap::execute(Analyzer& analyzer)
 {
     if (ps)
-        ps->apply();
+        ps->apply(analyzer);
 }
 
 ACSwap::~ACSwap()
index 79da9151e2da058d022cb2d36745355d0f79db58..ea91dd08b27e3be7d979879337dbb941d517217d 100644 (file)
@@ -56,11 +56,11 @@ public:
 class ACResume : public AnalyzerCommand
 {
 public:
-    ACResume(int n): pkt_count(n){}
+    ACResume(uint64_t msg_cnt): msg_cnt(msg_cnt) { }
     void execute(Analyzer&) override;
     const char* stringify() override { return "RESUME"; }
 private:
-    int pkt_count;
+    uint64_t msg_cnt;
 };
 
 class ACRotate : public AnalyzerCommand
index 2fae1613bd543511635c3d67bc6bc474dea52d97..fb069049d838ca09c132df4a83cc504b9a15385a 100644 (file)
@@ -280,7 +280,7 @@ void config_markup(SnortConfig*, const char*)
 
 [[noreturn]] void list_daqs(SnortConfig* sc)
 {
-    SFDAQ::load(sc);
+    SFDAQ::load(sc->daq_config);
     SFDAQ::print_types(cout);
     SFDAQ::unload();
     exit(0);
old mode 100755 (executable)
new mode 100644 (file)
diff --git a/src/main/oops_handler.cc b/src/main/oops_handler.cc
new file mode 100644 (file)
index 0000000..59af4ef
--- /dev/null
@@ -0,0 +1,60 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// 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 along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+// oops_handler.cc author Michael Altizer <mialtize@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "oops_handler.h"
+
+#include "protocols/packet.h"
+
+static THREAD_LOCAL OopsHandler* local_oops_handler = nullptr;
+
+void OopsHandler::handle_crash()
+{
+    if (local_oops_handler)
+        local_oops_handler->eternalize();
+}
+
+OopsHandler::OopsHandler()
+{
+    assert(local_oops_handler == nullptr);
+    local_oops_handler = this;
+}
+
+OopsHandler::~OopsHandler()
+{
+    local_oops_handler = nullptr;
+}
+
+void OopsHandler::eternalize()
+{
+    // Copy the crashed thread's data.  C++11 specs ensure the
+    // thread that segfaulted will still be running.
+    if (packet && packet->pkth)
+    {
+        pkth = *(packet->pkth);
+        if (packet->pkt)
+        {
+            memcpy(data, packet->pkt, 0xFFFF & packet->pktlen);
+            packet->pkt = data;
+        }
+    }
+}
diff --git a/src/main/oops_handler.h b/src/main/oops_handler.h
new file mode 100644 (file)
index 0000000..ceda708
--- /dev/null
@@ -0,0 +1,47 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// 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 along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+// oops_handler.h author Michael Altizer <mialtize@cisco.com>
+
+#ifndef OOPS_HANDLER_H
+#define OOPS_HANDLER_H
+
+#include <daq_common.h>
+
+namespace snort
+{
+struct Packet;
+}
+
+class OopsHandler
+{
+public:
+    static void handle_crash();
+
+    OopsHandler();
+    ~OopsHandler();
+    void set_current_packet(snort::Packet* p) { packet = p; }
+    void eternalize();
+
+private:
+    DAQ_PktHdr_t pkth = { };
+    uint8_t data[65535] = { };
+    snort::Packet* packet = nullptr;
+};
+
+#endif
+
index fe8e4397f974af51bef0b8e5ed489852dffc8188..9222314017e375e2bfba24db3da9fea2198f24d0 100644 (file)
 
 #include "snort.h"
 
+#include <daq.h>
 #include <sys/stat.h>
 #include <syslog.h>
 
 #include "actions/ips_actions.h"
 #include "codecs/codec_api.h"
 #include "connectors/connectors.h"
-#include "decompress/file_decomp.h"
-#include "detection/context_switcher.h"
 #include "detection/detect.h"
-#include "detection/detection_engine.h"
-#include "detection/detection_util.h"
 #include "detection/fp_config.h"
 #include "detection/fp_detect.h"
-#include "detection/ips_context.h"
-#include "detection/tag.h"
 #include "file_api/file_service.h"
-#include "filters/detection_filter.h"
 #include "filters/rate_filter.h"
 #include "filters/sfthreshold.h"
 #include "flow/ha.h"
-#include "framework/endianness.h"
 #include "framework/mpse.h"
-#include "helpers/base64_encoder.h"
 #include "helpers/process.h"
 #include "host_tracker/host_cache.h"
-#include "ips_options/ips_flowbits.h"
 #include "ips_options/ips_options.h"
-#include "latency/packet_latency.h"
-#include "latency/rule_latency.h"
 #include "log/log.h"
 #include "log/messages.h"
 #include "loggers/loggers.h"
 #include "main.h"
 #include "main/shell.h"
-#include "main/thread_config.h"
-#include "managers/action_manager.h"
 #include "managers/codec_manager.h"
 #include "managers/inspector_manager.h"
 #include "managers/ips_manager.h"
 #include "packet_io/active.h"
 #include "packet_io/sfdaq.h"
 #include "packet_io/trough.h"
-#include "packet_tracer/packet_tracer.h"
 #include "parser/cmd_line.h"
 #include "parser/parser.h"
 #include "profiler/profiler.h"
 #include "search_engines/search_engines.h"
 #include "service_inspectors/service_inspectors.h"
 #include "side_channel/side_channel.h"
-#include "stream/stream.h"
 #include "stream/stream_inspectors.h"
 #include "target_based/sftarget_reader.h"
-#include "time/packet_time.h"
 #include "time/periodic.h"
 #include "utils/util.h"
-#include "utils/util_utf.h"
-#include "utils/util_jsnorm.h"
 
 #ifdef PIGLET
 #include "piglet/piglet.h"
 using namespace snort;
 using namespace std;
 
-//-------------------------------------------------------------------------
-
 static SnortConfig* snort_cmd_line_conf = nullptr;
 static pid_t snort_main_thread_pid = 0;
 
-// non-local for easy access from core
-static THREAD_LOCAL DAQ_PktHdr_t s_pkth;
-static THREAD_LOCAL uint8_t* s_data = nullptr;
-static THREAD_LOCAL Packet* s_packet = nullptr;
-static THREAD_LOCAL ContextSwitcher* s_switcher = nullptr;
-
-ContextSwitcher* Snort::get_switcher()
-{ return s_switcher; }
-
-// Test util - used for pause-after-n and resume(n)
-static THREAD_LOCAL TestPause s_pause;
-
-TestPause& Snort::get_test_pause()
-{ return s_pause; }
-void TestPause::set_pause_cnt(int cnt)
-{ pause_cnt = cnt ? (cnt + pc.total_from_daq) : 0; }
-
 //-------------------------------------------------------------------------
 // perf stats
 // FIXIT-M move these to appropriate modules
 //-------------------------------------------------------------------------
 
-static THREAD_LOCAL ProfileStats totalPerfStats;
-static THREAD_LOCAL ProfileStats metaPerfStats;
-
 static ProfileStats* get_profile(const char* key)
 {
     if ( !strcmp(key, "detect") )
@@ -169,9 +128,6 @@ static ProfileStats* get_profile(const char* key)
     if ( !strcmp(key, "total") )
         return &totalPerfStats;
 
-    if ( !strcmp(key, "daq_meta") )
-        return &metaPerfStats;
-
     return nullptr;
 }
 
@@ -194,36 +150,6 @@ static void register_profiles()
 // helpers
 //-------------------------------------------------------------------------
 
-static bool pass_pkts(Packet*) { return true; }
-static MainHook_f main_hook = pass_pkts;
-
-static void set_policy(Packet* p)
-{
-    set_default_policy();
-    p->user_inspection_policy_id = get_inspection_policy()->user_policy_id;
-    p->user_ips_policy_id = get_ips_policy()->user_policy_id;
-    p->user_network_policy_id = get_network_policy()->user_policy_id;
-}
-
-static void show_source(const char* pcap)
-{
-    if ( !SnortConfig::pcap_show() )
-        return;
-
-    if ( !strcmp(pcap, "-") )
-        pcap = "stdin";
-
-    static bool first = true;
-    if ( first )
-        first = false;
-    else
-        fprintf(stdout, "%s", "\n");
-
-    fprintf(stdout, "Reading network traffic from \"%s\" with snaplen = %u\n",
-        pcap, SFDAQ::get_snap_len());
-}
-
-
 //-------------------------------------------------------------------------
 // initialization
 //-------------------------------------------------------------------------
@@ -273,7 +199,7 @@ void Snort::init(int argc, char** argv)
     ScriptManager::load_scripts(snort_cmd_line_conf->script_paths);
     PluginManager::load_plugins(snort_cmd_line_conf->plugin_path);
 
-    if ( SnortConfig::get_conf()->logging_flags & LOGGING_FLAG__SHOW_PLUGINS )
+    if ( snort_cmd_line_conf->logging_flags & LOGGING_FLAG__SHOW_PLUGINS )
     {
         ModuleManager::dump_modules();
         PluginManager::dump_plugins();
@@ -352,6 +278,10 @@ void Snort::init(int argc, char** argv)
     parser_term(sc);
 
     Active::init(sc);
+
+    LogMessage("%s\n", LOG_DIV);
+
+    SFDAQ::init(sc->daq_config);
 }
 
 // this function should only include initialization that must be done as a
@@ -380,10 +310,9 @@ bool Snort::drop_privileges()
     /* Drop privileges if requested. */
     if (SnortConfig::get_uid() != -1 || SnortConfig::get_gid() != -1)
     {
-        if (!SFDAQ::unprivileged())
+        if (!SFDAQ::can_run_unprivileged())
         {
-            ParseError("Cannot drop privileges - %s DAQ does not support unprivileged operation.\n",
-                SFDAQ::get_type());
+            ParseError("Cannot drop privileges - at least one of the configured DAQ modules does not support unprivileged operation.\n");
             return false;
         }
         if (!SetUidGid(SnortConfig::get_uid(), SnortConfig::get_gid()))
@@ -509,12 +438,6 @@ bool Snort::is_reloading()
 bool Snort::has_dropped_privileges()
 { return privileges_dropped; }
 
-void Snort::set_main_hook(MainHook_f f)
-{ main_hook = f; }
-
-Packet* Snort::get_packet()
-{ return s_packet; }
-
 void Snort::setup(int argc, char* argv[])
 {
     set_main_thread();
@@ -525,9 +448,6 @@ void Snort::setup(int argc, char* argv[])
 
     init(argc, argv);
 
-    LogMessage("%s\n", LOG_DIV);
-    SFDAQ::init(SnortConfig::get_conf());
-
     if ( SnortConfig::daemon_mode() )
         daemonize();
 
@@ -737,341 +657,3 @@ SnortConfig* Snort::get_updated_module(SnortConfig* other_conf, const char* name
     return sc;
 }
 
-void Snort::capture_packet()
-{
-    if ( snort_main_thread_pid == gettid() )
-    {
-        // FIXIT-L main thread crashed.  Do anything?
-    }
-    else
-    {
-        // Copy the crashed threads data.  C++11 specs ensure the
-        // thread that segfaulted will still be running.
-        if ( s_packet && s_packet->pkth )
-        {
-            s_pkth = *(s_packet->pkth);
-
-            if ( s_packet->pkt )
-            {
-                memcpy(s_data, s_packet->pkt, 0xFFFF & s_packet->pkth->caplen);
-                s_packet->pkt = s_data;
-            }
-        }
-    }
-}
-
-void Snort::thread_idle()
-{
-    // FIXIT-L this whole thing could be pub-sub
-    DataBus::publish(THREAD_IDLE_EVENT, nullptr);
-    if (SnortConfig::read_mode())
-        Stream::timeout_flows(packet_time());
-    else
-        Stream::timeout_flows(time(nullptr));
-    aux_counts.idle++;
-    HighAvailabilityManager::process_receive();
-}
-
-void Snort::thread_rotate()
-{
-    DataBus::publish(THREAD_ROTATE_EVENT, nullptr);
-}
-
-/*
- * Perform all packet thread initialization actions that need to be taken with escalated privileges
- * prior to starting the DAQ module.
- */
-bool Snort::thread_init_privileged(const char* intf)
-{
-    s_data = new uint8_t[65535];
-    show_source(intf);
-
-    SnortConfig::get_conf()->thread_config->implement_thread_affinity(STHREAD_TYPE_PACKET,
-        get_instance_id());
-
-    // FIXIT-M the start-up sequence is a little off due to dropping privs
-    SFDAQInstance* daq_instance = new SFDAQInstance(intf);
-    SFDAQ::set_local_instance(daq_instance);
-    if (!daq_instance->configure(SnortConfig::get_conf()))
-    {
-        SFDAQ::set_local_instance(nullptr);
-        delete daq_instance;
-        return false;
-    }
-
-    return true;
-}
-
-/*
- * Perform all packet thread initialization actions that can be taken with dropped privileges
- * and/or must be called after the DAQ module has been started.
- */
-void Snort::thread_init_unprivileged()
-{
-    // using dummy values until further integration
-    const unsigned max_contexts = 20;
-
-    s_switcher = new ContextSwitcher;
-
-    for ( unsigned i = 0; i < max_contexts; ++i )
-        s_switcher->push(new IpsContext);
-
-    CodecManager::thread_init(SnortConfig::get_conf());
-
-    // this depends on instantiated daq capabilities
-    // so it is done here instead of init()
-    Active::thread_init(SnortConfig::get_conf());
-
-    InitTag();
-    EventTrace_Init();
-    detection_filter_init(SnortConfig::get_conf()->detection_filter_config);
-    DetectionEngine::thread_init();
-
-    EventManager::open_outputs();
-    IpsManager::setup_options();
-    ActionManager::thread_init(SnortConfig::get_conf());
-    FileService::thread_init();
-    SideChannelManager::thread_init();
-    HighAvailabilityManager::thread_init(); // must be before InspectorManager::thread_init();
-    InspectorManager::thread_init(SnortConfig::get_conf());
-    PacketTracer::thread_init();
-
-    // in case there are HA messages waiting, process them first
-    HighAvailabilityManager::process_receive();
-    PacketManager::thread_init();
-}
-
-void Snort::thread_reinit(SnortConfig* sc)
-{
-    InspectorManager::thread_reinit(sc);
-    ActionManager::thread_reinit(sc);
-}
-
-void Snort::thread_term()
-{
-    HighAvailabilityManager::thread_term_beginning();
-
-    if ( !SnortConfig::get_conf()->dirty_pig )
-        Stream::purge_flows();
-
-    DetectionEngine::idle();
-    InspectorManager::thread_stop(SnortConfig::get_conf());
-    ModuleManager::accumulate(SnortConfig::get_conf());
-    InspectorManager::thread_term(SnortConfig::get_conf());
-    ActionManager::thread_term(SnortConfig::get_conf());
-
-    IpsManager::clear_options();
-    EventManager::close_outputs();
-    CodecManager::thread_term();
-    HighAvailabilityManager::thread_term();
-    SideChannelManager::thread_term();
-
-    s_packet = nullptr;
-
-    SFDAQInstance* daq_instance = SFDAQ::get_local_instance();
-    if ( daq_instance->was_started() )
-        daq_instance->stop();
-    SFDAQ::set_local_instance(nullptr);
-    delete daq_instance;
-
-    PacketLatency::tterm();
-    RuleLatency::tterm();
-
-    Profiler::consolidate_stats();
-
-    DetectionEngine::thread_term();
-    detection_filter_term();
-    EventTrace_Term();
-    CleanupTag();
-    FileService::thread_term();
-    PacketTracer::thread_term();
-    PacketManager::thread_term();
-
-    Active::thread_term();
-    delete s_switcher;
-    delete[] s_data;
-}
-
-bool Snort::inspect(Packet* p)
-{
-    // Need to include this b/c call is outside the detect tree
-    Profile detect_profile(detectPerfStats);
-    DeepProfile rebuilt_profile(rebuiltPacketPerfStats);
-
-    DetectionEngine de;
-    return main_hook(p);
-}
-
-DAQ_Verdict Snort::process_packet(
-    Packet* p, const DAQ_PktHdr_t* pkthdr, const uint8_t* pkt, bool is_frag)
-{
-    aux_counts.rx_bytes += pkthdr->caplen;
-
-    PacketManager::decode(p, pkthdr, pkt, is_frag);
-    assert(p->pkth && p->pkt);
-
-    PacketTracer::activate(*p);
-
-    if (is_frag)
-    {
-        p->packet_flags |= (PKT_PSEUDO | PKT_REBUILT_FRAG);
-        p->pseudo_type = PSEUDO_PKT_IP;
-    }
-
-    set_policy(p);  // FIXIT-M should not need this here
-
-    if ( !(p->packet_flags & PKT_IGNORE) )
-    {
-        clear_file_data();
-        main_hook(p);
-
-        // FIXIT-L remove this onload when DAQng can push multiple packets
-        if ( p->flow )
-            DetectionEngine::onload(p->flow);
-    }
-
-    Active* act = p->active;
-    // process flow verdicts here
-    if ( act->packet_retry_requested() )
-    {
-        return DAQ_VERDICT_RETRY;
-    }
-    else if ( act->session_was_blocked() )
-    {
-        if ( !act->can_block() )
-            return DAQ_VERDICT_PASS;
-
-        if ( act->get_tunnel_bypass() )
-        {
-            aux_counts.internal_blacklist++;
-            return DAQ_VERDICT_PASS;
-        }
-
-        if ( SnortConfig::inline_mode() or act->packet_force_dropped() )
-            return DAQ_VERDICT_BLACKLIST;
-        else
-            return DAQ_VERDICT_IGNORE;
-    }
-
-    return DAQ_VERDICT_PASS;
-}
-
-// process (wire-only) packet verdicts here
-static DAQ_Verdict update_verdict(Packet* p, DAQ_Verdict verdict, int& inject)
-{
-    if ( p->active->packet_was_dropped() and p->active->can_block() )
-    {
-        if ( verdict == DAQ_VERDICT_PASS )
-            verdict = DAQ_VERDICT_BLOCK;
-    }
-    else if ( verdict == DAQ_VERDICT_RETRY )
-    {
-        return verdict;
-    }
-    else if ( p->packet_flags & PKT_RESIZED )
-    {
-        // we never increase, only trim, but daq doesn't support resizing wire packet
-        PacketManager::encode_update(p);
-
-        if ( !SFDAQ::inject(p->pkth, 0, p->pkt, p->pkth->pktlen) )
-        {
-            inject = 1;
-            verdict = DAQ_VERDICT_BLOCK;
-        }
-    }
-    else if ( p->packet_flags & PKT_MODIFIED )
-    {
-        // this packet was normalized and/or has replacements
-        PacketManager::encode_update(p);
-        verdict = DAQ_VERDICT_REPLACE;
-    }
-    else if ( (p->packet_flags & PKT_IGNORE) ||
-        (p->flow && p->flow->get_ignore_direction( ) == SSN_DIR_BOTH) )
-    {
-        if ( !p->active->get_tunnel_bypass() )
-        {
-            verdict = DAQ_VERDICT_WHITELIST;
-        }
-        else
-        {
-            verdict = DAQ_VERDICT_PASS;
-            aux_counts.internal_whitelist++;
-        }
-    }
-    else if ( p->ptrs.decode_flags & DECODE_PKT_TRUST )
-    {
-        if (p->flow)
-            p->flow->set_ignore_direction(SSN_DIR_BOTH);
-        verdict = DAQ_VERDICT_WHITELIST;
-    }
-    else
-    {
-        verdict = DAQ_VERDICT_PASS;
-    }
-    return verdict;
-}
-
-DAQ_Verdict Snort::packet_callback(
-    void*, const DAQ_PktHdr_t* pkthdr, const uint8_t* pkt)
-{
-    set_default_policy();
-    Profile profile(totalPerfStats);
-
-    pc.total_from_daq++;
-    packet_time_update(&pkthdr->ts);
-
-    if ( SnortConfig::get_conf()->pkt_skip && pc.total_from_daq <= SnortConfig::get_conf()->pkt_skip )
-        return DAQ_VERDICT_PASS;
-
-    s_switcher->start();
-    s_packet = s_switcher->get_context()->packet;
-    s_packet->context->packet_number = pc.total_from_daq;
-
-    DetectionEngine::reset();
-
-    sfthreshold_reset();
-    ActionManager::reset_queue(s_packet);
-
-    DAQ_Verdict verdict = process_packet(s_packet, pkthdr, pkt);
-    ActionManager::execute(s_packet);
-
-    int inject = 0;
-    verdict = update_verdict(s_packet, verdict, inject);
-
-    if (PacketTracer::is_active())
-    {
-        PacketTracer::log("Policies: Network %u, Inspection %u, Detection %u\n",
-            get_network_policy()->user_policy_id, get_inspection_policy()->user_policy_id,
-            get_ips_policy()->user_policy_id);
-        PacketTracer::log("Verdict: %s\n", SFDAQ::verdict_to_string(verdict));
-
-        PacketTracer::dump(pkthdr);
-    }
-
-    HighAvailabilityManager::process_update(s_packet->flow, pkthdr);
-
-    Stream::timeout_flows(pkthdr->ts.tv_sec);
-    HighAvailabilityManager::process_receive();
-
-    s_packet->pkth = nullptr;  // no longer avail upon sig segv
-
-    if ( SnortConfig::get_conf()->pkt_cnt && pc.total_from_daq >= SnortConfig::get_conf()->pkt_cnt )
-        SFDAQ::break_loop(-1);
-
-    // Check for resume(n) 
-    else if ((s_pause.pause_cnt && pc.total_from_daq >= s_pause.pause_cnt) 
-#ifdef REG_TEST   // pause-after-n
-        || ( SnortConfig::get_conf()->pkt_pause_cnt && !s_pause.was_paused && 
-       pc.total_from_daq >= SnortConfig::get_conf()->pkt_pause_cnt )
-#endif
-       )
-    {
-        SFDAQ::break_loop(0);
-        s_pause.was_paused = s_pause.pause = true;
-    }  
-
-    s_switcher->stop();
-
-    return verdict;
-}
-
index ad467be245e172ff989fba3900e38c2020cd93ae..0d51b1686ab5f1f9b9abd0ccaf2ba8527f444174 100644 (file)
@@ -31,24 +31,10 @@ class ContextSwitcher;
 namespace snort
 {
 class Flow;
+class SFDAQInstance;
 struct Packet;
 struct SnortConfig;
 
-typedef bool (* MainHook_f)(Packet*);
-
-class TestPause
-{
-public:
-    bool get_pause() { return pause; }
-    void clear_pause() { pause = false; }
-    void set_pause_cnt(int cnt);
-
-public:
-    bool pause = false;
-    bool was_paused = false;
-    uint64_t pause_cnt = 0;
-};
-
 class Snort
 {
 public:
@@ -64,29 +50,6 @@ public:
     static bool is_reloading();
     static bool has_dropped_privileges();
 
-    static bool thread_init_privileged(const char* intf);
-    static void thread_init_unprivileged();
-    static void thread_reinit(SnortConfig*);
-    static void thread_term();
-
-    static void thread_idle();
-    static void thread_rotate();
-
-    static void capture_packet();
-
-    static DAQ_Verdict process_packet(
-        Packet*, const DAQ_PktHdr_t*, const uint8_t* pkt, bool is_frag=false);
-
-    static DAQ_Verdict packet_callback(void*, const DAQ_PktHdr_t*, const uint8_t*);
-
-    static bool inspect(Packet*);
-
-    static void set_main_hook(MainHook_f);
-    static ContextSwitcher* get_switcher();
-
-    SO_PUBLIC static Packet* get_packet();
-    static TestPause& get_test_pause();
-
 private:
     static void init(int, char**);
     static void term();
index a0017c374c94c48ac8e35194c6d46adc5fb99731..dc93daf5f40d60d3680402212773213e808a0c96 100644 (file)
@@ -61,7 +61,7 @@
 #include "utils/util.h"
 #include "utils/util_cstring.h"
 
-#include "snort.h"
+#include "analyzer.h"
 #include "thread_config.h"
 
 using namespace snort;
@@ -614,7 +614,7 @@ bool SnortConfig::verify()
         return false;
     }
 
-    if (get_conf()->daq_config->mru_size != daq_config->mru_size)
+    if (get_conf()->daq_config->get_mru_size() != daq_config->get_mru_size())
     {
         ReloadError("Snort Reload: Changing the packet snaplen "
             "configuration requires a restart.\n");
@@ -1021,14 +1021,14 @@ void SnortConfig::set_alert_mode(const char* val)
         output = val;
 
     output_flags |= OUTPUT_FLAG__ALERTS;
-    Snort::set_main_hook(DetectionEngine::inspect);
+    Analyzer::set_main_hook(DetectionEngine::inspect);
 }
 
 void SnortConfig::set_log_mode(const char* val)
 {
     if (strcasecmp(val, LOG_NONE) == 0)
     {
-        Snort::set_main_hook(snort_ignore);
+        Analyzer::set_main_hook(snort_ignore);
         EventManager::enable_logs(false);
     }
     else
@@ -1036,7 +1036,7 @@ void SnortConfig::set_log_mode(const char* val)
         if ( !strcmp(val, LOG_DUMP) )
             val = LOG_CODECS;
         output = val;
-        Snort::set_main_hook(snort_log);
+        Analyzer::set_main_hook(snort_log);
     }
 }
 
index 95a04d16b6b066186f1e693ce40445aef11904f2..73eb83901aad5d3faf4da89fd4a50c4a1c7f7d5d 100644 (file)
@@ -303,12 +303,18 @@ static const Parameter s_params[] =
     { "--daq", Parameter::PT_STRING, nullptr, nullptr,
       "<type> select packet acquisition module (default is pcap)" },
 
+    { "--daq-batch-size", Parameter::PT_INT, "1:", "64",
+      "<size> set the DAQ receive batch size", },
+
     { "--daq-dir", Parameter::PT_STRING, nullptr, nullptr,
       "<dir> tell snort where to find desired DAQ" },
 
     { "--daq-list", Parameter::PT_IMPLIED, nullptr, nullptr,
       "list packet acquisition modules available in optional dir, default is static modules only" },
 
+    { "--daq-mode", Parameter::PT_ENUM, "passive | inline | read-file", nullptr,
+      "<mode> select DAQ module operating mode (overrides automatic selection)" },
+
     { "--daq-var", Parameter::PT_STRING, nullptr, nullptr,
       "<name=value> specify extra DAQ configuration variable" },
 
@@ -606,13 +612,13 @@ public:
     { return GLOBAL; }
 
 private:
-    int instance_id;
+    SFDAQModuleConfig *module_config;
 };
 
 bool SnortModule::begin(const char* fqn, int, SnortConfig*)
 {
     if (!strcmp(fqn, "snort"))
-        instance_id = -1;
+        module_config = nullptr;
     return true;
 }
 
@@ -655,13 +661,7 @@ bool SnortModule::set(const char*, Value& v, SnortConfig* sc)
         sc->run_flags |= RUN_FLAG__STATIC_HASH;
 
     else if ( v.is("-i") )
-    {
-        instance_id++;
-        if (instance_id > 0)
-            sc->daq_config->set_input_spec(v.get_string(), instance_id);
-        else
-            sc->daq_config->set_input_spec(v.get_string());
-    }
+        sc->daq_config->add_input(v.get_string());
 
 #ifdef SHELL
     else if ( v.is("-j") )
@@ -766,7 +766,10 @@ bool SnortModule::set(const char*, Value& v, SnortConfig* sc)
         sc->set_create_pid_file(true);
 
     else if ( v.is("--daq") )
-        sc->daq_config->set_module_name(v.get_string());
+        module_config = sc->daq_config->add_module_config(v.get_string());
+
+    else if ( v.is("--daq-batch-size") )
+        sc->daq_config->set_batch_size(v.get_long());
 
     else if ( v.is("--daq-dir") )
     {
@@ -776,15 +779,31 @@ bool SnortModule::set(const char*, Value& v, SnortConfig* sc)
         while ( getline(ss, path, ':') )
             sc->daq_config->add_module_dir(path.c_str());
     }
+    else if ( v.is("--daq-mode") )
+    {
+        if (!module_config)
+            return false;
+        switch ( v.get_long() )
+        {
+            case 0:
+                module_config->mode = SFDAQModuleConfig::SFDAQ_MODE_PASSIVE;
+                break;
+            case 1:
+                module_config->mode = SFDAQModuleConfig::SFDAQ_MODE_INLINE;
+                break;
+            case 2:
+                module_config->mode = SFDAQModuleConfig::SFDAQ_MODE_READ_FILE;
+                break;
+        }
+    }
     else if ( v.is("--daq-list") )
         list_daqs(sc);
 
     else if ( v.is("--daq-var") )
     {
-        if (instance_id < 0)
-            sc->daq_config->set_variable(v.get_string());
-        else
-            sc->daq_config->set_variable(v.get_string(), instance_id);
+        if (!module_config)
+            return false;
+        module_config->set_variable(v.get_string());
     }
     else if ( v.is("--dirty-pig") )
         sc->set_dirty_pig(true);
index f294c208f50a72559a79283b917501457688a920..f4ca31e169c8eeea1d0f18568445a36357482651 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "target_based/sftarget_reader.h"
 
+#include "analyzer.h"
 #include "snort.h"
 #include "snort_config.h"
 
@@ -77,7 +78,7 @@ Swapper::~Swapper()
         SFAT_Free(old_attribs);
 }
 
-void Swapper::apply()
+void Swapper::apply(Analyzer& analyzer)
 {
     if ( new_conf )
     {
@@ -85,7 +86,7 @@ void Swapper::apply()
         snort::SnortConfig::set_conf(new_conf);
         // FIXIT-M Determine whether we really want to do this before or after the set_conf
         if (reload)
-            snort::Snort::thread_reinit(new_conf);
+            analyzer.reinit(new_conf);
     }
 
     if ( new_attribs )
index 91dd6e52f99ae590ef00acafd75a89489ed8b647..46a9aeeb82d982a4faac203e9fddef6feaf5e06c 100644 (file)
@@ -27,6 +27,7 @@ namespace snort
 struct SnortConfig;
 }
 
+class Analyzer;
 struct tTargetBasedConfig;
 
 class Swapper
@@ -38,7 +39,7 @@ public:
     Swapper(tTargetBasedConfig*, tTargetBasedConfig*);
     ~Swapper();
 
-    void apply();
+    void apply(Analyzer&);
 
     static bool get_reload_in_progress() { return reload_in_progress; }
     static void set_reload_in_progress(bool rip) { reload_in_progress = rip; }
index aa91ce7d6c7b7b75bd7d7811c4a11119de187270..42003fa9ec52a87f1a4d697838a25788c2f22ad9 100644 (file)
@@ -214,14 +214,17 @@ void ActionManager::thread_reinit(SnortConfig* sc)
 
 void ActionManager::thread_term(SnortConfig*)
 {
-    // Call tterm for every IPS action plugin ever configured during the lifetime of this thread
-    for ( auto& p : *s_tl_actors )
+    if (s_tl_actors)
     {
-        if ( p.api->tterm )
-            p.api->tterm();
+        // Call tterm for every IPS action plugin ever configured during the lifetime of this thread
+        for ( auto& p : *s_tl_actors )
+        {
+            if ( p.api->tterm )
+                p.api->tterm();
+        }
+        delete s_tl_actors;
+        s_tl_actors = nullptr;
     }
-    delete s_tl_actors;
-    s_tl_actors = nullptr;
 }
 
 void ActionManager::execute(Packet* p)
index 68248a54d67ce953ea2e9c6dd1be17f1f532d11e..bf3216f389301c8c164770400799274b057ffd12 100644 (file)
@@ -205,7 +205,7 @@ void PacketCapture::eval(Packet* p)
                 return;
 
         if ( !bpf.bf_insns || bpf_filter(bpf.bf_insns, p->pkt,
-                p->pkth->caplen, p->pkth->pktlen) )
+                p->pktlen, p->pkth->pktlen) )
         {
             write_packet(p);
             cap_count_stats.matched++;
@@ -221,7 +221,7 @@ void PacketCapture::write_packet(Packet* p)
 {
     struct pcap_pkthdr pcaphdr;
     pcaphdr.ts = p->pkth->ts;
-    pcaphdr.caplen = p->pkth->caplen;
+    pcaphdr.caplen = p->pktlen;
     pcaphdr.len = p->pkth->pktlen;
     pcap_dump((unsigned char*)dumper, &pcaphdr, p->pkt);
     pcap_dump_flush(dumper);
@@ -291,9 +291,9 @@ static Packet* init_null_packet()
     static Packet p(false);
     static DAQ_PktHdr_t h;
 
-    p.pkt = nullptr;
     p.pkth = &h;
-    h.caplen = 0;
+    p.pkt = nullptr;
+    p.pktlen = 0;
     h.pktlen = 0;
 
     return &p;
@@ -394,10 +394,10 @@ TEST_CASE("blank filter", "[PacketCapture]")
 
     Packet p(false);
     DAQ_PktHdr_t daq_hdr;
-    p.pkt = cooked;
     p.pkth = &daq_hdr;
+    p.pkt = cooked;
+    p.pktlen = sizeof(cooked);
 
-    daq_hdr.caplen = sizeof(cooked);
     daq_hdr.pktlen = sizeof(cooked);
 
     CaptureModule mod;
@@ -479,7 +479,9 @@ TEST_CASE("bpf filter", "[PacketCapture]")
     p_match.pkt = match;
     p_non_match.pkt = non_match;
 
-    daq_hdr.caplen = sizeof(match);
+    p_match.pktlen = sizeof(match);
+    p_non_match.pktlen = sizeof(match);
+
     daq_hdr.pktlen = sizeof(match);
 
     CaptureModule mod;
index 4934598390d109db78f0034c086e400bdb6e41af..222fc00afa0c72b5fb8687f8eb5715178aa822ae 100644 (file)
@@ -31,7 +31,7 @@
 #include "detection/ips_context.h"
 #include "log/log.h"
 #include "log/messages.h"
-#include "packet_io/sfdaq.h"
+#include "packet_io/sfdaq_instance.h"
 #include "protocols/eth.h"
 #include "protocols/icmp4.h"
 #include "protocols/ip.h"
@@ -112,13 +112,13 @@ void PacketTracer::dump(char* output_buff, unsigned int len)
     s_pkt_trace->reset();
 }
 
-void PacketTracer::dump(const DAQ_PktHdr_t* pkt_hdr)
+void PacketTracer::dump(Packet* p)
 {
     if (is_paused())
         return;
 
     if (s_pkt_trace->daq_activated)
-        s_pkt_trace->dump_to_daq(pkt_hdr);
+        s_pkt_trace->dump_to_daq(p);
 
     if (s_pkt_trace->user_enabled or s_pkt_trace->shell_enabled)
         LogMessage(s_pkt_trace->log_fh, "%s\n", s_pkt_trace->buffer);
@@ -341,12 +341,12 @@ void PacketTracer::add_packet_type_info(const Packet& p)
                 PacketTracer::log("Packet %" PRIu64 ": TCP %s, %s, seq %u, ack %u, dsize %u%s\n",
                     p.context->packet_number, tcpFlags, timestamp,
                     p.ptrs.tcph->seq(), p.ptrs.tcph->ack(), p.dsize,
-                    (p.pkth->flags & DAQ_PKT_FLAG_RETRY_PACKET) ? ", retry pkt" : "");
+                    p.is_retry() ? ", retry pkt" : "");
             else
                 PacketTracer::log("Packet %" PRIu64 ": TCP %s, %s, seq %u, dsize %u%s\n",
                     p.context->packet_number, tcpFlags, timestamp, p.ptrs.tcph->seq(),
                     p.dsize,
-                    (p.pkth->flags & DAQ_PKT_FLAG_RETRY_PACKET) ? ", retry pkt" : "");
+                    p.is_retry() ? ", retry pkt" : "");
             break;
         }
 
@@ -416,9 +416,10 @@ void PacketTracer::open_file()
     }
 }
 
-void PacketTracer::dump_to_daq(const DAQ_PktHdr_t* pkt_hdr)
+void PacketTracer::dump_to_daq(Packet* p)
 {
-    SFDAQ::get_local_instance()->modify_flow_pkt_trace(pkt_hdr, reason,
+    assert(p);
+    p->daq_instance->modify_flow_pkt_trace(p->daq_msg, reason,
         (uint8_t *)buffer, buff_len + 1);
 }
 
@@ -475,7 +476,7 @@ public:
     static uint8_t get_dump_reason()
     { return ((TestPacketTracer*)s_pkt_trace)->dump_reason; }
 
-    void dump_to_daq(const DAQ_PktHdr_t*) override
+    void dump_to_daq(Packet*) override
     { dump_reason = reason; }
 
     static std::vector<bool> get_mutes()
index 38a30470f289e95015baadea9e231d416004d7ff..df8bdbdf9efe3d487afd40f72a15dd8b6eae34f0 100644 (file)
@@ -24,7 +24,6 @@
 #include <cstdarg>
 #include <cstdio>
 #include <cstring>
-#include <daq_common.h>
 #include <vector>
 
 #include "main/snort_types.h"
@@ -102,7 +101,7 @@ public:
     static void thread_term();
 
     static void dump(char* output_buff, unsigned int len);
-    static void dump(const DAQ_PktHdr_t*);
+    static void dump(Packet*);
 
     static void configure(bool status, const std::string& file_name);
     static void set_constraints(const PTSessionConstraints* constraints);
@@ -151,7 +150,7 @@ protected:
     const char *get_debug_session() { return debug_session; }
 
     virtual void open_file();
-    virtual void dump_to_daq(const DAQ_PktHdr_t*);
+    virtual void dump_to_daq(Packet*);
     virtual void reset();
 
 };
index 261d66a90b600612b1a306eab861a4cc4bc9a067..a35e09ab8e519ed1a284352db872e101809479c5 100644 (file)
@@ -137,7 +137,7 @@ void FlowIPTracker::update(Packet* p)
 
         const SfIp* src_addr = p->ptrs.ip_api.get_src();
         const SfIp* dst_addr = p->ptrs.ip_api.get_dst();
-        int len = p->pkth->caplen;
+        int len = p->pktlen;
 
         if (p->ptrs.tcph)
             type = SFS_TYPE_TCP;
index 1ffc65a60af596a48cb3d82b994ee779ae7393fe..8249b7f9937b0320dabef972f8775b0ee0583fad 100644 (file)
@@ -74,7 +74,7 @@ void FlowTracker::update(Packet* p)
 {
     if (!p->is_rebuilt())
     {
-        auto len = p->pkth->caplen;
+        auto len = p->pktlen;
 
         if (p->ptrs.tcph)
             update_transport_flows(p->ptrs.sp, p->ptrs.dp, tcp, len);
@@ -163,7 +163,7 @@ public:
 TEST_CASE("no protocol", "[FlowTracker]")
 {
     Packet p;
-    uint32_t* len_ptr = &const_cast<DAQ_PktHdr_t*>(p.pkth)->caplen;
+    uint32_t* len_ptr = &p.pktlen;
 
     PerfConfig config;
     config.format = PerfFormat::MOCK;
@@ -208,7 +208,7 @@ TEST_CASE("icmp", "[FlowTracker]")
 {
     Packet p;
     icmp::ICMPHdr icmp;
-    uint32_t* len_ptr = &const_cast<DAQ_PktHdr_t*>(p.pkth)->caplen;
+    uint32_t* len_ptr = &p.pktlen;
     uint8_t* type_ptr = (uint8_t*) &icmp.type;
 
     PerfConfig config;
@@ -253,7 +253,7 @@ TEST_CASE("tcp", "[FlowTracker]")
 {
     Packet p;
     tcp::TCPHdr tcp;
-    uint32_t* len_ptr = &const_cast<DAQ_PktHdr_t*>(p.pkth)->caplen;
+    uint32_t* len_ptr = &p.pktlen;
 
     PerfConfig config;
     config.format = PerfFormat::MOCK;
@@ -307,7 +307,7 @@ TEST_CASE("udp", "[FlowTracker]")
 {
     Packet p;
     udp::UDPHdr udp;
-    uint32_t* len_ptr = &const_cast<DAQ_PktHdr_t*>(p.pkth)->caplen;
+    uint32_t* len_ptr = &p.pktlen;
 
     PerfConfig config;
     config.format = PerfFormat::MOCK;
index 563bfd46518bee4c9fe101846b04973665982d3f..4c2807d9b54f16d4171b954e1606348b95102b47 100644 (file)
@@ -2,6 +2,7 @@
 set ( PACKET_IO_INCLUDES
     active.h
     sfdaq.h
+    sfdaq_instance.h
 )
 
 if (ENABLE_UNIT_TESTS)
@@ -10,6 +11,20 @@ if (ENABLE_UNIT_TESTS)
     )
 endif (ENABLE_UNIT_TESTS)
 
+if (ENABLE_STATIC_DAQ)
+    foreach (STATIC_MODULE_NAME IN LISTS DAQ_STATIC_MODULES)
+        string(APPEND DAQ_STATIC_MODULE_EXTERNS "extern const DAQ_ModuleAPI_t ${STATIC_MODULE_NAME}_daq_module_data;\n")
+        string(APPEND DAQ_STATIC_MODULE_DATA_ARRAY "    &${STATIC_MODULE_NAME}_daq_module_data,\n")
+    endforeach ()
+    configure_file (
+        "${CMAKE_CURRENT_SOURCE_DIR}/sfdaq_static_modules.h.in"
+        "${CMAKE_CURRENT_BINARY_DIR}/sfdaq_static_modules.h"
+    )
+    set_source_files_properties(sfdaq.cc PROPERTIES COMPILE_DEFINITIONS ENABLE_STATIC_DAQ)
+    include_directories(${CMAKE_CURRENT_BINARY_DIR})
+    set(STATIC_DAQ_MODULES_HEADER "sfdaq_static_modules.h")
+endif ()
+
 add_library (packet_io OBJECT
     active.cc
     active.h
@@ -17,10 +32,13 @@ add_library (packet_io OBJECT
     sfdaq.h
     sfdaq_config.cc
     sfdaq_config.h
+    sfdaq_instance.cc
+    sfdaq_instance.h
     sfdaq_module.cc
     sfdaq_module.h
     trough.cc
     trough.h
+    ${STATIC_DAQ_MODULES_HEADER}
     ${TEST_FILES}
 )
 
index acd7ba59c45025da48c142f1853f83a09839d6c6..1270f7265b8d02e4c56238901276a12da1ada41c 100644 (file)
@@ -53,7 +53,7 @@ THREAD_LOCAL bool Active::s_suspend = false;
 THREAD_LOCAL Active::Counts snort::active_counts;
 
 typedef int (* send_t) (
-    const DAQ_PktHdr_t* h, int rev, const uint8_t* buf, uint32_t len);
+    DAQ_Msg_h msg, int rev, const uint8_t* buf, uint32_t len);
 
 static THREAD_LOCAL eth_t* s_link = nullptr;
 static THREAD_LOCAL ip_t* s_ipnet = nullptr;
@@ -63,7 +63,7 @@ static THREAD_LOCAL send_t s_send = SFDAQ::inject;
 // helpers
 
 int Active::send_eth(
-    const DAQ_PktHdr_t*, int, const uint8_t* buf, uint32_t len)
+    DAQ_Msg_h, int, const uint8_t* buf, uint32_t len)
 {
     ssize_t sent = eth_send(s_link, buf, len);
     active_counts.injects++;
@@ -71,7 +71,7 @@ int Active::send_eth(
 }
 
 int Active::send_ip(
-    const DAQ_PktHdr_t*, int, const uint8_t* buf, uint32_t len)
+    DAQ_Msg_h, int, const uint8_t* buf, uint32_t len)
 {
     ssize_t sent = ip_send(s_ipnet, buf, len);
     active_counts.injects++;
@@ -209,7 +209,7 @@ void Active::send_reset(Packet* p, EncodeFlags ef)
         if ( !rej )
             return;
 
-        s_send(p->pkth, !(ef & ENC_FLAG_FWD), rej, len);
+        s_send(p->daq_msg, !(ef & ENC_FLAG_FWD), rej, len);
     }
 }
 
@@ -226,7 +226,7 @@ void Active::send_unreach(Packet* p, snort::UnreachResponse type)
     if ( !rej )
         return;
 
-    s_send(p->pkth, 1, rej, len);
+    s_send(p->daq_msg, 1, rej, len);
 }
 
 bool Active::send_data(
@@ -246,7 +246,7 @@ bool Active::send_data(
 
         if ( seg )
         {
-            s_send(p->pkth, !(tmp_flags & ENC_FLAG_FWD), seg, plen);
+            s_send(p->daq_msg, !(tmp_flags & ENC_FLAG_FWD), seg, plen);
             active_counts.injects++;
         }
     }
@@ -268,7 +268,7 @@ bool Active::send_data(
             if ( !seg )
                 return false;
 
-            s_send(p->pkth, !(flags & ENC_FLAG_FWD), seg, plen);
+            s_send(p->daq_msg, !(flags & ENC_FLAG_FWD), seg, plen);
             active_counts.injects++;
 
             buf += toSend;
@@ -284,7 +284,7 @@ bool Active::send_data(
     if ( !seg )
         return false;
 
-    s_send(p->pkth, !(flags & ENC_FLAG_FWD), seg, plen);
+    s_send(p->daq_msg, !(flags & ENC_FLAG_FWD), seg, plen);
     active_counts.injects++;
 
     if (flags & ENC_FLAG_RST_CLNT)
@@ -296,7 +296,7 @@ bool Active::send_data(
 
         if ( seg )
         {
-            s_send(p->pkth, !(flags & ENC_FLAG_FWD), seg, plen);
+            s_send(p->daq_msg, !(flags & ENC_FLAG_FWD), seg, plen);
             active_counts.injects++;
         }
     }
@@ -320,7 +320,7 @@ void Active::inject_data(
     if ( !seg )
         return;
 
-    s_send(p->pkth, !(flags & ENC_FLAG_FWD), seg, plen);
+    s_send(p->daq_msg, !(flags & ENC_FLAG_FWD), seg, plen);
 }
 
 //--------------------------------------------------------------------
@@ -422,11 +422,11 @@ bool Active::daq_retry_packet(const Packet* p)
 {
     bool retry_queued = false;
 
-    if ( ( active_action == ACT_PASS ) and SFDAQ::can_retry() )
+    if ( !p->is_rebuilt() && (active_action == ACT_PASS) )
     {
         if ( SFDAQ::forwarding_packet(p->pkth) )
         {
-            if(p->packet_flags & PKT_RETRANSMIT)
+            if (p->packet_flags & PKT_RETRANSMIT)
                 active_action = ACT_DROP;  // Don't add retransmits to retry queue.
             else
                 active_action = ACT_RETRY;
index d3c1164985c13e6e9250c967eb8ee5eb27368a6d..f20842ae1d4e731d8460da773a662a532971c03f 100644 (file)
@@ -129,8 +129,8 @@ public:
 private:
     static bool open(const char*);
     static void close();
-    static int send_eth(const DAQ_PktHdr_t*, int, const uint8_t* buf, uint32_t len);
-    static int send_ip(const DAQ_PktHdr_t*, int, const uint8_t* buf, uint32_t len);
+    static int send_eth(DAQ_Msg_h, int, const uint8_t* buf, uint32_t len);
+    static int send_ip(DAQ_Msg_h, int, const uint8_t* buf, uint32_t len);
 
     void update_status(const Packet*, bool force = false);
     void daq_update_status(const Packet*);
index 4030e1316a466359a7db3cae1365210ed339c94f..c99cf29159be1c99445d80c76f6ed0b0bb876f97 100644 (file)
 
 #include "sfdaq.h"
 
-extern "C" {
 #include <daq.h>
-#include <sfbpf_dlt.h>
-}
-
-#include <cassert>
-#include <mutex>
 
 #include "log/messages.h"
 #include "main/snort_config.h"
-#include "protocols/packet.h"
-#include "protocols/vlan.h"
 
 #include "sfdaq_config.h"
+#include "sfdaq_instance.h"
+#ifdef ENABLE_STATIC_DAQ
+#include "sfdaq_static_modules.h"
+#endif
 
 using namespace snort;
 using namespace std;
 
 #ifdef DEFAULT_DAQ
-#define XSTR(s) STR(s)
-#define STR(s) #s
-#define DAQ_DEFAULT XSTR(DEFAULT_DAQ)
+#define DAQ_DEFAULT STRINGIFY_MX(DEFAULT_DAQ)
 #else
 #define DAQ_DEFAULT "pcap"
 #endif
 
-static const int DEFAULT_PKT_SNAPLEN = 1518;
-
 // common for all daq threads / instances
-static const DAQ_Module_t* daq_mod = nullptr;
-static DAQ_Mode daq_mode = DAQ_MODE_PASSIVE;
-static uint32_t snap = DEFAULT_PKT_SNAPLEN;
+static DAQ_Config_h daqcfg = nullptr;
+static DAQ_Mode default_daq_mode = DAQ_MODE_PASSIVE;
+static string daq_module_names;
 static bool loaded = false;
-static std::mutex bpf_gate;
 
 // specific for each thread / instance
 static THREAD_LOCAL SFDAQInstance *local_instance = nullptr;
 
-/*
- * SFDAQ
- */
-
-void SFDAQ::load(const SnortConfig* sc)
+void SFDAQ::load(const SFDAQConfig* cfg)
 {
-    const char** dirs = new const char*[sc->daq_config->module_dirs.size() + 1];
+    const char** dirs = new const char*[cfg->module_dirs.size() + 1];
     int i = 0;
 
-    for (string& module_dir : sc->daq_config->module_dirs)
+    for (const string& module_dir : cfg->module_dirs)
         dirs[i++] = module_dir.c_str();
     dirs[i] = nullptr;
 
-    int err = daq_load_modules(dirs);
-
+#ifdef ENABLE_STATIC_DAQ
+    daq_load_static_modules(static_daq_modules);
+#endif
+    int err = daq_load_dynamic_modules(dirs);
     if (err)
-        FatalError("Can't load DAQ modules = %d\n", err);
+        FatalError("Could not load dynamic DAQ modules! (%d)\n", err);
 
     delete[] dirs;
 
@@ -94,41 +83,63 @@ void SFDAQ::unload()
 
 void SFDAQ::print_types(ostream& ostr)
 {
-    DAQ_Module_Info_t* list = nullptr;
-    int i, nMods = daq_get_module_list(&list);
+    DAQ_Module_h module = daq_modules_first();
 
-    if (nMods)
+    if (module)
         ostr << "Available DAQ modules:" << endl;
     else
         ostr << "No available DAQ modules (try adding directories with --daq-dir)." << endl;
 
-    for (i = 0; i < nMods; i++)
+    while (module)
     {
-        ostr << list[i].name << "(v" << list[i].version << "):";
+        ostr << daq_module_get_name(module) << "(v" << daq_module_get_version(module) << "):";
 
-        if (list[i].type & DAQ_TYPE_FILE_CAPABLE)
+        uint32_t type = daq_module_get_type(module);
+
+        if (type & DAQ_TYPE_FILE_CAPABLE)
             ostr << " readback";
 
-        if (list[i].type & DAQ_TYPE_INTF_CAPABLE)
+        if (type & DAQ_TYPE_INTF_CAPABLE)
             ostr << " live";
 
-        if (list[i].type & DAQ_TYPE_INLINE_CAPABLE)
+        if (type & DAQ_TYPE_INLINE_CAPABLE)
             ostr << " inline";
 
-        if (list[i].type & DAQ_TYPE_MULTI_INSTANCE)
+        if (type & DAQ_TYPE_MULTI_INSTANCE)
             ostr << " multi";
 
-        if (!(list[i].type & DAQ_TYPE_NO_UNPRIV))
+        if (!(type & DAQ_TYPE_NO_UNPRIV))
             ostr << " unpriv";
 
+        if (type & DAQ_TYPE_WRAPPER)
+            ostr << " wrapper";
+
         ostr << endl;
+
+        const DAQ_VariableDesc_t *var_desc_table;
+        int num_var_descs = daq_module_get_variable_descs(module, &var_desc_table);
+        if (num_var_descs > 0)
+        {
+            ostr << " Variables:" << endl;
+            for (int i = 0; i < num_var_descs; i++)
+            {
+                ostr << "  " << var_desc_table[i].name << " ";
+                if (var_desc_table[i].flags & DAQ_VAR_DESC_REQUIRES_ARGUMENT)
+                    ostr << "<arg> ";
+                else if (!(var_desc_table[i].flags & DAQ_VAR_DESC_FORBIDS_ARGUMENT))
+                    ostr << "[arg] ";
+                ostr << "- " << var_desc_table[i].description << endl;
+            }
+        }
+
+        module = daq_modules_next();
     }
-    daq_free_module_list(list, nMods);
 }
 
-static int DAQ_ValidateModule(DAQ_Mode mode)
+/*
+static int DAQ_ValidateModule(DAQ_Module_h module, DAQ_Mode mode)
 {
-    uint32_t have = daq_get_type(daq_mod);
+    uint32_t have = daq_module_get_type(module);
     uint32_t need = 0;
 
     if (mode == DAQ_MODE_READ_FILE)
@@ -142,42 +153,153 @@ static int DAQ_ValidateModule(DAQ_Mode mode)
 
     return ((have & need) != 0);
 }
+*/
 
-void SFDAQ::init(const SnortConfig* sc)
+static bool AddDaqModuleConfig(const SFDAQModuleConfig *dmc)
 {
-    if (!loaded)
-        load(sc);
+    const char* module_name = dmc->name.c_str();
+    DAQ_Module_h module = daq_find_module(module_name);
+    if (!module)
+    {
+        ErrorMessage("Could not find requested DAQ module: %s\n", module_name);
+        return false;
+    }
 
-    const char* type = DAQ_DEFAULT;
+    DAQ_ModuleConfig_h modcfg;
+    int rval;
+    if ((rval = daq_module_config_new(&modcfg, module)) != DAQ_SUCCESS)
+    {
+        ErrorMessage("Error allocating a new DAQ module configuration object! (%d)\n", rval);
+        return false;
+    }
 
-    if (!sc->daq_config->module_name.empty())
-        type = sc->daq_config->module_name.c_str();
+    DAQ_Mode mode;
+    if (dmc->mode == SFDAQModuleConfig::SFDAQ_MODE_PASSIVE)
+        mode = DAQ_MODE_PASSIVE;
+    else if (dmc->mode == SFDAQModuleConfig::SFDAQ_MODE_INLINE)
+        mode = DAQ_MODE_INLINE;
+    else if (dmc->mode == SFDAQModuleConfig::SFDAQ_MODE_READ_FILE)
+        mode = DAQ_MODE_READ_FILE;
+    else
+        mode = default_daq_mode;
+    daq_module_config_set_mode(modcfg, mode);
 
-    daq_mod = daq_find_module(type);
+    for (auto& kvp : dmc->variables)
+    {
+        const char* key = kvp.first.c_str();
+        const char* value = kvp.second.length() ? kvp.second.c_str() : nullptr;
+        if (daq_module_config_set_variable(modcfg, key, value) != DAQ_SUCCESS)
+        {
+            ErrorMessage("Error setting DAQ configuration variable with key '%s' and value '%s'! (%d)",
+                    key, value, rval);
+            daq_module_config_destroy(modcfg);
+            return false;
+        }
+    }
 
-    if (!daq_mod)
-        FatalError("Can't find %s DAQ\n", type);
+    if ((rval = daq_config_push_module_config(daqcfg, modcfg)) != DAQ_SUCCESS)
+    {
+        ErrorMessage("Error pushing DAQ module configuration for '%s' onto the DAQ config! (%d)\n",
+                daq_module_get_name(module), rval);
+        daq_module_config_destroy(modcfg);
+        return false;
+    }
 
-    snap = (sc->daq_config->mru_size > 0) ? sc->daq_config->mru_size : DEFAULT_PKT_SNAPLEN;
+    if (!daq_module_names.empty())
+        daq_module_names.insert(0, 1, ':');
+    daq_module_names.insert(0, module_name);
+
+    return true;
+}
+
+bool SFDAQ::init(const SFDAQConfig* cfg)
+{
+    if (!loaded)
+        load(cfg);
+
+    int rval;
 
     if (SnortConfig::adaptor_inline_mode())
-        daq_mode = DAQ_MODE_INLINE;
+        default_daq_mode = DAQ_MODE_INLINE;
     else if (SnortConfig::read_mode())
-        daq_mode = DAQ_MODE_READ_FILE;
+        default_daq_mode = DAQ_MODE_READ_FILE;
     else
-        daq_mode = DAQ_MODE_PASSIVE;
+        default_daq_mode = DAQ_MODE_PASSIVE;
+
+    if ((rval = daq_config_new(&daqcfg)) != DAQ_SUCCESS)
+    {
+        ErrorMessage("Error allocating a new DAQ configuration object! (%d)\n", rval);
+        return false;
+    }
 
+    daq_config_set_msg_pool_size(daqcfg, cfg->get_batch_size() * 4);
+    daq_config_set_snaplen(daqcfg, cfg->get_mru_size());
+    daq_config_set_timeout(daqcfg, cfg->timeout);
+
+    /* If no modules were specified, try to automatically configure with the default. */
+    if (cfg->module_configs.empty())
+    {
+        SFDAQModuleConfig dmc;
+        dmc.name = DAQ_DEFAULT;
+        if (!AddDaqModuleConfig(&dmc))
+        {
+            daq_config_destroy(daqcfg);
+            daqcfg = nullptr;
+            return false;
+        }
+    }
+    /* Otherwise, if the module stack doesn't have a terminal module at the bottom, default
+        to a hardcoded base of the PCAP DAQ module in read-file mode.  This is a convenience
+        provided to emulate the previous dump/regtest DAQ module behavior. */
+    else
+    {
+        const char* module_name = cfg->module_configs[0]->name.c_str();
+        DAQ_Module_h module = daq_find_module(module_name);
+        if (module && (daq_module_get_type(module) & DAQ_TYPE_WRAPPER))
+        {
+            SFDAQModuleConfig dmc;
+            dmc.name = "pcap";
+            dmc.mode = SFDAQModuleConfig::SFDAQ_MODE_READ_FILE;
+            if (!AddDaqModuleConfig(&dmc))
+            {
+                daq_config_destroy(daqcfg);
+                daqcfg = nullptr;
+                return false;
+            }
+        }
+    }
+
+    for (SFDAQModuleConfig* dmc : cfg->module_configs)
+    {
+        if (!AddDaqModuleConfig(dmc))
+        {
+            daq_config_destroy(daqcfg);
+            daqcfg = nullptr;
+            return false;
+        }
+    }
+
+/*
     if (!DAQ_ValidateModule(daq_mode))
         FatalError("%s DAQ does not support %s.\n", type, daq_mode_string(daq_mode));
 
-    LogMessage("%s DAQ configured to %s.\n", type, daq_mode_string(daq_mode));
+*/
+    LogMessage("%s DAQ configured to %s.\n", daq_module_names.c_str(), daq_mode_string(default_daq_mode));
+
+    return true;
 }
 
 void SFDAQ::term()
 {
+    if (daqcfg)
+    {
+        daq_config_destroy(daqcfg);
+        daqcfg = nullptr;
+    }
+#ifndef REG_TEST
     if (loaded)
         unload();
-    daq_mod = nullptr;
+#endif
 }
 
 const char* SFDAQ::verdict_to_string(DAQ_Verdict verdict)
@@ -188,25 +310,26 @@ const char* SFDAQ::verdict_to_string(DAQ_Verdict verdict)
 bool SFDAQ::forwarding_packet(const DAQ_PktHdr_t* h)
 {
     // DAQ mode is inline and the packet will be forwarded?
-    return (daq_mode == DAQ_MODE_INLINE && !(h->flags & DAQ_PKT_FLAG_NOT_FORWARDING));
-}
-
-const char* SFDAQ::get_type()
-{
-    return daq_mod ? daq_get_name(daq_mod) : "error";
+    return (default_daq_mode == DAQ_MODE_INLINE && !(h->flags & DAQ_PKT_FLAG_NOT_FORWARDING));
 }
 
-// Snort has its own snap applied to packets it acquires via the DAQ.  This
-// should not be confused with the snap that was used to capture a pcap which
-// may be different.
-uint32_t SFDAQ::get_snap_len()
+bool SFDAQ::can_run_unprivileged()
 {
-    return snap;
+    // Iterate over the configured modules to see if any of them don't support unprivileged operation
+    DAQ_ModuleConfig_h modcfg = daq_config_top_module_config(daqcfg);
+    while (modcfg)
+    {
+        DAQ_Module_h module = daq_module_config_get_module(modcfg);
+        if (daq_module_get_type(module) & DAQ_TYPE_NO_UNPRIV)
+            return false;
+        modcfg = daq_config_next_module_config(daqcfg);
+    }
+    return true;
 }
 
-bool SFDAQ::unprivileged()
+bool SFDAQ::init_instance(SFDAQInstance* instance, const string& bpf_string)
 {
-    return !(daq_get_type(daq_mod) & DAQ_TYPE_NO_UNPRIV);
+    return instance->init(daqcfg, bpf_string);
 }
 
 /*
@@ -223,10 +346,9 @@ SFDAQInstance* SFDAQ::get_local_instance()
     return local_instance;
 }
 
-const char* SFDAQ::get_interface_spec()
+const char* SFDAQ::get_input_spec()
 {
-    assert(local_instance->get_interface_spec());
-    return local_instance->get_interface_spec();
+    return local_instance->get_input_spec();
 }
 
 int SFDAQ::get_base_protocol()
@@ -249,24 +371,14 @@ bool SFDAQ::can_replace()
     return local_instance && local_instance->can_replace();
 }
 
-bool SFDAQ::can_retry()
-{
-    return local_instance && local_instance->can_retry();
-}
-
 bool SFDAQ::get_tunnel_bypass(uint8_t proto)
 {
     return local_instance && local_instance->get_tunnel_bypass(proto);
 }
 
-int SFDAQ::inject(const DAQ_PktHdr_t* hdr, int rev, const uint8_t* buf, uint32_t len)
+int SFDAQ::inject(DAQ_Msg_h msg, int rev, const uint8_t* buf, uint32_t len)
 {
-    return local_instance->inject(hdr, rev, buf, len);
-}
-
-bool SFDAQ::break_loop(int error)
-{
-    return local_instance->break_loop(error);
+    return local_instance->inject(msg, rev, buf, len);
 }
 
 const DAQ_Stats_t* SFDAQ::get_stats()
@@ -274,16 +386,15 @@ const DAQ_Stats_t* SFDAQ::get_stats()
     return local_instance->get_stats();
 }
 
-const char* SFDAQ::get_input_spec(const SnortConfig* sc, unsigned instance_id)
+const char* SFDAQ::get_input_spec(const SFDAQConfig* cfg, unsigned instance_id)
 {
-    auto it = sc->daq_config->instances.find(instance_id);
-    if (it != sc->daq_config->instances.end() && !it->second->input_spec.empty())
-        return it->second->input_spec.c_str();
+    if (cfg->inputs.empty())
+        return nullptr;
 
-    if (!sc->daq_config->input_spec.empty())
-        return sc->daq_config->input_spec.c_str();
+    if (instance_id > 0 && instance_id < cfg->inputs.size())
+        return cfg->inputs[instance_id].c_str();
 
-    return nullptr;
+    return cfg->inputs[0].c_str();
 }
 
 const char* SFDAQ::default_type()
@@ -291,413 +402,3 @@ const char* SFDAQ::default_type()
     return DAQ_DEFAULT;
 }
 
-/*
- * SFDAQInstance
- */
-
-SFDAQInstance::SFDAQInstance(const char* intf)
-{
-    if (intf)
-        interface_spec = intf;
-    daq_hand = nullptr;
-    daq_dlt = -1;
-    s_error = DAQ_SUCCESS;
-    memset(&daq_stats, 0, sizeof(daq_stats));
-    daq_tunnel_mask = 0;
-}
-
-SFDAQInstance::~SFDAQInstance()
-{
-    if (daq_hand)
-        daq_shutdown(daq_mod, daq_hand);
-}
-
-static bool DAQ_ValidateInstance(void* daq_hand)
-{
-    uint32_t caps = daq_get_capabilities(daq_mod, daq_hand);
-
-    if (!SnortConfig::adaptor_inline_mode())
-        return true;
-
-    if (!(caps & DAQ_CAPA_BLOCK))
-        ParseWarning(WARN_DAQ, "inline mode configured but DAQ can't block packets.\n");
-
-    return true;
-}
-
-bool SFDAQInstance::configure(const SnortConfig* sc)
-{
-    DAQ_Config_t cfg;
-    const char* type = daq_get_name(daq_mod);
-    char buf[256] = "";
-    int err;
-
-    memset(&cfg, 0, sizeof(cfg));
-
-    cfg.name = const_cast<char*>(interface_spec.c_str());
-    cfg.snaplen = snap;
-    cfg.timeout = sc->daq_config->timeout;
-    cfg.mode = daq_mode;
-    cfg.extra = nullptr;
-    cfg.flags = 0;
-
-    for (auto& kvp : sc->daq_config->variables)
-    {
-        daq_config_set_value(&cfg, kvp.first.c_str(),
-                kvp.second.length() ? kvp.second.c_str() : nullptr);
-    }
-
-    auto it = sc->daq_config->instances.find(get_instance_id());
-    if (it != sc->daq_config->instances.end())
-    {
-        for (auto& kvp : it->second->variables)
-        {
-            daq_config_set_value(&cfg, kvp.first.c_str(),
-                    kvp.second.length() ? kvp.second.c_str() : nullptr);
-        }
-    }
-
-    if (!SnortConfig::read_mode())
-    {
-        if (!(sc->run_flags & RUN_FLAG__NO_PROMISCUOUS))
-            cfg.flags |= DAQ_CFG_PROMISC;
-    }
-
-    // FIXIT-M - This is sort of an abomination and would ideally be configurable ...
-    if (!strcasecmp(type, "dump") or !strcasecmp(type, "regtest"))
-        cfg.extra = reinterpret_cast<char*>(const_cast<DAQ_Module_t*>(daq_find_module("pcap")));
-
-    err = daq_initialize(daq_mod, &cfg, &daq_hand, buf, sizeof(buf));
-    if (err)
-    {
-        ErrorMessage("Can't initialize DAQ %s (%d) - %s\n", type, err, buf);
-        return false;
-    }
-    daq_config_clear_values(&cfg);
-
-    if (!DAQ_ValidateInstance(daq_hand))
-        FatalError("DAQ configuration incompatible with intended operation.\n");
-
-    set_filter(sc->bpf_filter.c_str());
-
-    return true;
-}
-
-void SFDAQInstance::reload()
-{
-    void* old_config = nullptr;
-    void* new_config = nullptr;
-    if (daq_mod && daq_hand)
-    {
-        if ( ( daq_hup_prep(daq_mod, daq_hand, &new_config) == DAQ_SUCCESS ) and
-            ( daq_hup_apply(daq_mod, daq_hand, new_config, &old_config) == DAQ_SUCCESS ) )
-        {
-            daq_hup_post(daq_mod, daq_hand, old_config);
-        }
-    }
-}
-
-void SFDAQInstance::abort()
-{
-    if (was_started())
-        stop();
-
-    //DAQ_Delete();
-    //DAQ_Term();  FIXIT-L this must be called from main thread on abort
-}
-
-const char* SFDAQInstance::get_interface_spec()
-{
-    return interface_spec.c_str();
-}
-
-// That distinction does not hold with datalink types.  Snort must use whatever
-// datalink type the DAQ coughs up as its base protocol decoder.  For pcaps,
-// the datalink type in the file must be used - which may not be known until
-// start.  The value is cached here since it used for packet operations like
-// logging and is needed at shutdown.  This avoids sequencing issues.
-int SFDAQInstance::get_base_protocol()
-{
-    return daq_dlt;
-}
-
-bool SFDAQInstance::can_inject()
-{
-    return (daq_get_capabilities(daq_mod, daq_hand) & DAQ_CAPA_INJECT) != 0;
-}
-
-bool SFDAQInstance::can_inject_raw()
-{
-    return (daq_get_capabilities(daq_mod, daq_hand) & DAQ_CAPA_INJECT_RAW) != 0;
-}
-
-bool SFDAQInstance::can_replace()
-{
-    return (daq_get_capabilities(daq_mod, daq_hand) & DAQ_CAPA_REPLACE) != 0;
-}
-
-bool SFDAQInstance::can_retry()
-{
-    return (daq_get_capabilities(daq_mod, daq_hand) & DAQ_CAPA_RETRY) != 0;
-}
-
-bool SFDAQInstance::can_start_unprivileged()
-{
-    return (daq_get_capabilities(daq_mod, daq_hand) & DAQ_CAPA_UNPRIV_START) != 0;
-}
-
-bool SFDAQInstance::can_whitelist()
-{
-    return (daq_get_capabilities(daq_mod, daq_hand) & DAQ_CAPA_WHITELIST) != 0;
-}
-
-bool SFDAQInstance::set_filter(const char* bpf)
-{
-    int err = 0;
-
-    // The BPF can be compiled either during daq_set_filter() or daq_start(),
-    // so protect the thread-unsafe BPF scanner/compiler in both places.
-
-    if (bpf and *bpf)
-    {
-        std::lock_guard<std::mutex> lock(bpf_gate);
-        err = daq_set_filter(daq_mod, daq_hand, bpf);
-    }
-
-    if (err)
-        FatalError("Can't set DAQ BPF filter to '%s' (%s)\n",
-            bpf, daq_get_error(daq_mod, daq_hand));
-
-    return (err == DAQ_SUCCESS);
-}
-
-bool SFDAQInstance::start()
-{
-    int err;
-
-    // The BPF can be compiled either during daq_set_filter() or daq_start(),
-    // so protect the thread-unsafe BPF scanner/compiler in both places.
-    {
-        std::lock_guard<std::mutex> lock(bpf_gate);
-        err = daq_start(daq_mod, daq_hand);
-    }
-
-    if (err)
-        ErrorMessage("Can't start DAQ (%d) - %s\n", err, daq_get_error(daq_mod, daq_hand));
-    else
-        daq_dlt = daq_get_datalink_type(daq_mod, daq_hand);
-
-    get_tunnel_capabilities();
-
-    return (err == DAQ_SUCCESS);
-}
-
-void SFDAQInstance::get_tunnel_capabilities()
-{
-    daq_tunnel_mask = 0;
-    if (daq_mod && daq_hand)
-    {
-        uint32_t caps = daq_get_capabilities(daq_mod, daq_hand);
-
-        if (caps & DAQ_CAPA_DECODE_GTP)
-        {
-            daq_tunnel_mask |= TUNNEL_GTP;
-        }
-        if (caps & DAQ_CAPA_DECODE_TEREDO)
-        {
-            daq_tunnel_mask |= TUNNEL_TEREDO;
-        }
-        if (caps & DAQ_CAPA_DECODE_GRE)
-        {
-            daq_tunnel_mask |= TUNNEL_GRE;
-        }
-        if (caps & DAQ_CAPA_DECODE_4IN4)
-        {
-            daq_tunnel_mask |= TUNNEL_4IN4;
-        }
-        if (caps & DAQ_CAPA_DECODE_6IN4)
-        {
-            daq_tunnel_mask |= TUNNEL_6IN4;
-        }
-        if (caps & DAQ_CAPA_DECODE_4IN6)
-        {
-            daq_tunnel_mask |= TUNNEL_4IN6;
-        }
-        if (caps & DAQ_CAPA_DECODE_6IN6)
-        {
-            daq_tunnel_mask |= TUNNEL_6IN6;
-        }
-        if (caps & DAQ_CAPA_DECODE_MPLS)
-        {
-            daq_tunnel_mask |= TUNNEL_MPLS;
-        }
-    }
-}
-
-bool SFDAQInstance::get_tunnel_bypass(uint8_t proto)
-{
-    return (daq_tunnel_mask & proto) != 0;
-}
-
-bool SFDAQInstance::was_started()
-{
-    DAQ_State s;
-
-    if (!daq_hand)
-        return false;
-
-    s = daq_check_status(daq_mod, daq_hand);
-
-    return (DAQ_STATE_STARTED == s);
-}
-
-bool SFDAQInstance::stop()
-{
-    int err = daq_stop(daq_mod, daq_hand);
-
-    if (err)
-        LogMessage("Can't stop DAQ (%d) - %s\n", err, daq_get_error(daq_mod, daq_hand));
-
-    return (err == DAQ_SUCCESS);
-}
-
-static int metacallback(void *user, const DAQ_MetaHdr_t* hdr, const uint8_t* data)
-{
-    DataBus::publish(DAQ_META_EVENT, user, hdr->type, data);
-    return 0;
-}
-
-int SFDAQInstance::acquire(int max, DAQ_Analysis_Func_t callback)
-{
-    int err = daq_acquire_with_meta(daq_mod, daq_hand, max, callback, metacallback, nullptr);
-
-    if (err && err != DAQ_READFILE_EOF)
-        LogMessage("Can't acquire (%d) - %s\n", err, daq_get_error(daq_mod, daq_hand));
-
-    if (s_error != DAQ_SUCCESS)
-    {
-        err = s_error;
-        s_error = DAQ_SUCCESS;
-    }
-    return err;
-}
-
-int SFDAQInstance::inject(const DAQ_PktHdr_t* h, int rev, const uint8_t* buf, uint32_t len)
-{
-    int err = daq_inject(daq_mod, daq_hand, h, buf, len, rev);
-#ifdef DEBUG_MSGS
-    if (err)
-        LogMessage("Can't inject (%d) - %s\n", err, daq_get_error(daq_mod, daq_hand));
-#endif
-    return err;
-}
-
-bool SFDAQInstance::break_loop(int error)
-{
-    if (error)
-        s_error = error;
-    return (daq_breakloop(daq_mod, daq_hand) == DAQ_SUCCESS);
-}
-
-// returns statically allocated stats - don't free
-const DAQ_Stats_t* SFDAQInstance::get_stats()
-{
-    if (daq_hand)
-    {
-        int err = daq_get_stats(daq_mod, daq_hand, &daq_stats);
-
-        if (err)
-            LogMessage("Can't get DAQ stats (%d) - %s\n", err, daq_get_error(daq_mod, daq_hand));
-
-        // Some DAQs don't provide hw numbers, so we default HW RX to the SW equivalent
-        // (this means outstanding packets = 0)
-        if (!daq_stats.hw_packets_received)
-            daq_stats.hw_packets_received = daq_stats.packets_received + daq_stats.packets_filtered;
-    }
-
-    return &daq_stats;
-}
-
-int SFDAQInstance::query_flow(const DAQ_PktHdr_t* hdr, DAQ_QueryFlow_t* query)
-{
-    return daq_query_flow(daq_mod, daq_hand, hdr, query);
-}
-
-int SFDAQInstance::modify_flow_opaque(const DAQ_PktHdr_t* hdr, uint32_t opaque)
-{
-    DAQ_ModFlow_t mod;
-
-    mod.type = DAQ_MODFLOW_TYPE_OPAQUE;
-    mod.length = sizeof(opaque);
-    mod.value = &opaque;
-
-    return daq_modify_flow(daq_mod, daq_hand, hdr, &mod);
-}
-
-int SFDAQInstance::modify_flow_pkt_trace(const DAQ_PktHdr_t* hdr, uint8_t verdict_reason,
-    uint8_t* buff, uint32_t buff_len)
-{
-    DAQ_ModFlow_t mod;
-    DAQ_ModFlowPktTrace_t mod_tr;
-    mod_tr.vreason = verdict_reason;
-    mod_tr.pkt_trace_data_len = buff_len;
-    mod_tr.pkt_trace_data = buff;
-    mod.type = DAQ_MODFLOW_TYPE_PKT_TRACE;
-    mod.length = sizeof(DAQ_ModFlowPktTrace_t);
-    mod.value = (void*)&mod_tr;
-    return daq_modify_flow(daq_mod, daq_hand, hdr, &mod);
-}
-
-// FIXIT-L X Add Snort flag definitions for callers to use and translate/pass them through to
-// the DAQ module
-int SFDAQInstance::add_expected(const Packet* ctrlPkt, const SfIp* cliIP, uint16_t cliPort,
-        const SfIp* srvIP, uint16_t srvPort, IpProtocol protocol, unsigned timeout_ms, unsigned /* flags */)
-{
-    DAQ_Data_Channel_Params_t daq_params;
-    DAQ_DP_key_t dp_key;
-
-    dp_key.src_af = cliIP->get_family();
-    if (cliIP->is_ip4())
-        dp_key.sa.src_ip4.s_addr = cliIP->get_ip4_value();
-    else
-        memcpy(&dp_key.sa.src_ip6, cliIP->get_ip6_ptr(), sizeof(dp_key.sa.src_ip6));
-    dp_key.src_port = cliPort;
-
-    dp_key.dst_af = srvIP->get_family();
-    if (srvIP->is_ip4())
-        dp_key.da.dst_ip4.s_addr = srvIP->get_ip4_value();
-    else
-        memcpy(&dp_key.da.dst_ip6, srvIP->get_ip6_ptr(), sizeof(dp_key.da.dst_ip6));
-    dp_key.dst_port = srvPort;
-
-    dp_key.protocol = (uint8_t) protocol;
-    dp_key.vlan_cnots = 1;
-    if (ctrlPkt->proto_bits & PROTO_BIT__VLAN)
-        dp_key.vlan_id = layer::get_vlan_layer(ctrlPkt)->vid();
-    else
-        dp_key.vlan_id = 0xFFFF;
-
-    if (ctrlPkt->proto_bits & PROTO_BIT__GTP)
-        dp_key.tunnel_type = DAQ_DP_TUNNEL_TYPE_GTP_TUNNEL;
-    else if (ctrlPkt->proto_bits & PROTO_BIT__MPLS)
-        dp_key.tunnel_type = DAQ_DP_TUNNEL_TYPE_MPLS_TUNNEL;
-/*
-    else if ( ctrlPkt->encapsulated )
-        dp_key.tunnel_type = DAQ_DP_TUNNEL_TYPE_OTHER_TUNNEL;
-*/
-    else
-        dp_key.tunnel_type = DAQ_DP_TUNNEL_TYPE_NON_TUNNEL;
-
-    memset(&daq_params, 0, sizeof(daq_params));
-    daq_params.timeout_ms = timeout_ms;
-/*
-    if (flags & DAQ_DC_FLOAT)
-        daq_params.flags |= DAQ_DATA_CHANNEL_FLOAT;
-    if (flags & DAQ_DC_ALLOW_MULTIPLE)
-        daq_params.flags |= DAQ_DATA_CHANNEL_ALLOW_MULTIPLE;
-    if (flags & DAQ_DC_PERSIST)
-        daq_params.flags |= DAQ_DATA_CHANNEL_PERSIST;
-*/
-
-    return daq_dp_add_dc(daq_mod, daq_hand, ctrlPkt->pkth, &dp_key, nullptr, &daq_params);
-}
index 2fa4613c912843281947b96fe3970448fb70ab03..d207c2f813560563ba4006450335ca2b196a8a6f 100644 (file)
 
 #include <daq_common.h>
 
-#include <string>
+#include <ostream>
 
 #include "main/snort_types.h"
-#include "protocols/protocol_ids.h"
 
-namespace snort
-{
-struct Packet;
-struct SnortConfig;
-struct SfIp;
+struct SFDAQConfig;
 
-class SFDAQInstance
+namespace snort
 {
-public:
-    SFDAQInstance(const char* intf);
-    ~SFDAQInstance();
-
-    bool configure(const SnortConfig*);
-    void set_metacallback(DAQ_Meta_Func_t);
-
-    bool start();
-    bool was_started();
-    bool stop();
-    void reload();
-    void abort();
-
-    int get_base_protocol();
-    const char* get_interface_spec();
-    const DAQ_Stats_t* get_stats();
-
-    bool can_inject();
-    bool can_inject_raw();
-    bool can_replace();
-    bool can_retry();
-    bool can_start_unprivileged();
-    SO_PUBLIC bool can_whitelist();
-
-    int acquire(int max, DAQ_Analysis_Func_t);
-    int inject(const DAQ_PktHdr_t*, int rev, const uint8_t* buf, uint32_t len);
-    bool break_loop(int error);
-
-    SO_PUBLIC int query_flow(const DAQ_PktHdr_t*, DAQ_QueryFlow_t*);
-    SO_PUBLIC int modify_flow_opaque(const DAQ_PktHdr_t*, uint32_t opaque);
-    int modify_flow_pkt_trace(const DAQ_PktHdr_t*, uint8_t verdict_reason,
-        uint8_t* buff, uint32_t buff_len);
-    int add_expected(const Packet* ctrlPkt, const SfIp* cliIP, uint16_t cliPort,
-            const SfIp* srvIP, uint16_t srvPort, IpProtocol, unsigned timeout_ms,
-            unsigned /* flags */);
-    bool get_tunnel_bypass(uint8_t proto);
-
-private:
-    void get_tunnel_capabilities();
-    bool set_filter(const char*);
-    std::string interface_spec;
-    void* daq_hand;
-    int daq_dlt;
-    int s_error;
-    DAQ_Stats_t daq_stats;
-    uint8_t daq_tunnel_mask;
-};
+class SFDAQInstance;
 
 class SFDAQ
 {
 public:
-    static void load(const SnortConfig*);
+    static void load(const SFDAQConfig*);
     static void unload();
 
     static void print_types(std::ostream&);
     static const char* verdict_to_string(DAQ_Verdict verdict);
-    static void init(const SnortConfig*);
+    static bool init(const SFDAQConfig*);
     static void term();
 
-    static const char* get_type();
-    static const char* get_input_spec(const SnortConfig*, unsigned instance_id);
+    static bool init_instance(SFDAQInstance*, const std::string& bpf_string);
+
+    static const char* get_input_spec(const SFDAQConfig*, unsigned instance_id);
     static const char* default_type();
     static const DAQ_Stats_t* get_stats();
 
-    static bool unprivileged();
     static bool can_inject();
     static bool can_inject_raw();
     static bool can_replace();
-    static bool can_retry();
+    static bool can_run_unprivileged();
     SO_PUBLIC static bool get_tunnel_bypass(uint8_t proto);
 
     // FIXIT-M X Temporary thread-local instance helpers to be removed when no longer needed
     static void set_local_instance(SFDAQInstance*);
 
     SO_PUBLIC static SFDAQInstance* get_local_instance();
-    SO_PUBLIC static const char* get_interface_spec();
+    SO_PUBLIC static const char* get_input_spec();
     SO_PUBLIC static int get_base_protocol();
-    SO_PUBLIC static uint32_t get_snap_len();
 
-    static int inject(const DAQ_PktHdr_t*, int rev, const uint8_t* buf, uint32_t len);
+    static int inject(DAQ_Msg_h, int rev, const uint8_t* buf, uint32_t len);
     static bool forwarding_packet(const DAQ_PktHdr_t*);
-    static bool break_loop(int error);
 };
 }
 #endif
index 44d1d9ec674fe92a01a7d71547d86c210ad5cb18..bf16400bbf32e4bd4e5058a0504f522683ff1916 100644 (file)
@@ -26,8 +26,6 @@
 
 using namespace std;
 
-static const unsigned DEFAULT_PKT_TIMEOUT = 1000;    // ms, worst daq resolution is 1 sec
-
 static pair<string, string> parse_variable(const char* varkvp)
 {
     string key = varkvp;
@@ -44,27 +42,22 @@ static pair<string, string> parse_variable(const char* varkvp)
 }
 
 /*
- * SFDAQConfigInstance
+ * SFDAQModuleConfig
  */
 
-SFDAQInstanceConfig::SFDAQInstanceConfig(const SFDAQInstanceConfig& other)
+SFDAQModuleConfig::SFDAQModuleConfig(const SFDAQModuleConfig& other)
 {
-    input_spec = other.input_spec;
+    name = other.name;
+    mode = other.mode;
     variables = other.variables;
 }
 
-void SFDAQInstanceConfig::set_input_spec(const char* input_spec_str)
+void SFDAQModuleConfig::set_variable(const char* varkvp)
 {
-    if (input_spec_str)
-        input_spec = input_spec_str;
-    else
-        input_spec.clear();
+    if (varkvp)
+        variables.emplace_back(parse_variable(varkvp));
 }
 
-void SFDAQInstanceConfig::set_variable(const char* varkvp)
-{
-    variables.emplace_back(parse_variable(varkvp));
-}
 
 /*
  * SFDAQConfig
@@ -72,78 +65,45 @@ void SFDAQInstanceConfig::set_variable(const char* varkvp)
 
 SFDAQConfig::SFDAQConfig()
 {
-    mru_size = -1;
-    timeout = DEFAULT_PKT_TIMEOUT;
+    batch_size = BATCH_SIZE_UNSET;
+    mru_size = SNAPLEN_UNSET;
+    timeout = TIMEOUT_DEFAULT;
 }
 
 SFDAQConfig::~SFDAQConfig()
 {
-    for (auto it : instances)
-        delete it.second;
+    for (auto it : module_configs)
+        delete it;
 }
 
-void SFDAQConfig::add_module_dir(const char* module_dir)
+void SFDAQConfig::add_input(const char* input)
 {
-    if (module_dir)
-        module_dirs.emplace_back(module_dir);
+    if (input)
+        inputs.emplace_back(input);
 }
 
-void SFDAQConfig::set_input_spec(const char* input_spec_str, int instance_id)
+SFDAQModuleConfig* SFDAQConfig::add_module_config(const char* module_name)
 {
-    if (instance_id >= 0)
-    {
-        SFDAQInstanceConfig* ic;
-
-        auto it = instances.find(instance_id);
-        if (it == instances.end())
-        {
-            ic = new SFDAQInstanceConfig;
-            instances[instance_id] = ic;
-        }
-        else
-            ic = it->second;
-
-        ic->set_input_spec(input_spec_str);
-    }
-    else
-    {
-        if (input_spec_str)
-            input_spec = input_spec_str;
-        else
-            input_spec.clear();
-    }
+    SFDAQModuleConfig* modcfg = new SFDAQModuleConfig();
+    modcfg->name = module_name;
+    module_configs.emplace_back(modcfg);
+    return modcfg;
 }
 
-void SFDAQConfig::set_module_name(const char* module_name_str)
+void SFDAQConfig::add_module_dir(const char* module_dir)
 {
-    if (module_name_str)
-        module_name = module_name_str;
+    if (module_dir)
+        module_dirs.emplace_back(module_dir);
 }
 
-void SFDAQConfig::set_mru_size(int mru_size_value)
+void SFDAQConfig::set_batch_size(uint32_t batch_size_value)
 {
-    mru_size = mru_size_value;
+    batch_size = batch_size_value;
 }
 
-void SFDAQConfig::set_variable(const char* varkvp, int instance_id)
+void SFDAQConfig::set_mru_size(int mru_size_value)
 {
-    if (instance_id >= 0)
-    {
-        SFDAQInstanceConfig* ic;
-
-        auto it = instances.find(instance_id);
-        if (it == instances.end())
-        {
-            ic = new SFDAQInstanceConfig;
-            instances[instance_id] = ic;
-        }
-        else
-            ic = it->second;
-
-        ic->set_variable(varkvp);
-    }
-    else
-        variables.emplace_back(parse_variable(varkvp));
+    mru_size = mru_size_value;
 }
 
 void SFDAQConfig::overlay(const SFDAQConfig* other)
@@ -151,35 +111,21 @@ void SFDAQConfig::overlay(const SFDAQConfig* other)
     if (!other->module_dirs.empty())
         module_dirs = other->module_dirs;
 
-    if (!other->module_name.empty())
-        module_name = other->module_name;
-
-    if (!other->input_spec.empty())
-        input_spec = other->input_spec;
+    if (!other->module_configs.empty())
+    {
+        for (SFDAQModuleConfig *dmc : module_configs)
+            delete dmc;
+        module_configs.clear();
+        for (SFDAQModuleConfig *dmc : other->module_configs)
+            module_configs.emplace_back(new SFDAQModuleConfig(*dmc));
+    }
 
-    if (!other->variables.empty())
-        variables = other->variables;
+    if (!other->inputs.empty())
+        inputs = other->inputs;
 
-    if (other->mru_size != -1)
+    if (other->batch_size != BATCH_SIZE_UNSET)
+        batch_size = other->batch_size;
+    if (other->mru_size != SNAPLEN_UNSET)
         mru_size = other->mru_size;
-
-    for (auto oit = other->instances.begin(); oit != other->instances.end(); oit++)
-    {
-        SFDAQInstanceConfig* oic = oit->second;
-        SFDAQInstanceConfig* ic;
-        auto it = instances.find(oit->first);
-        if (it != instances.end())
-        {
-            ic = it->second;
-            if (!oic->input_spec.empty())
-                ic->input_spec = oic->input_spec;
-            if (!oic->variables.empty())
-                ic->variables = oic->variables;
-        }
-        else
-        {
-            ic = new SFDAQInstanceConfig(*oic);
-            instances[oit->first] = ic;
-        }
-    }
+    timeout = other->timeout;
 }
index 1665f4017a11ccf780a5496b535457eafdac4dce..abf573b9a8ad3fb69ee92c43cdc1fa47eba62e84 100644 (file)
 #include <unordered_map>
 #include <vector>
 
-/* Per-Instance override configuration */
-struct SFDAQInstanceConfig
-{
-    SFDAQInstanceConfig() = default;
-    SFDAQInstanceConfig(const SFDAQInstanceConfig&);
+using DaqVar = std::pair<std::string, std::string>;
+using DaqVarList = std::vector<DaqVar>;
 
-    SFDAQInstanceConfig& operator=(const SFDAQInstanceConfig&) = delete;
+/* Module configuration */
+struct SFDAQModuleConfig
+{
+    enum SFDAQMode
+    {
+        SFDAQ_MODE_UNSET,
+        SFDAQ_MODE_PASSIVE,
+        SFDAQ_MODE_INLINE,
+        SFDAQ_MODE_READ_FILE,
+    };
 
-    void set_input_spec(const char*);
+    SFDAQModuleConfig() = default;
+    SFDAQModuleConfig(const SFDAQModuleConfig&);
     void set_variable(const char* varkvp);
 
-    std::string input_spec;
-    std::vector<std::pair<std::string, std::string>> variables;
+    std::string name;
+    SFDAQMode mode = SFDAQ_MODE_UNSET;
+    DaqVarList variables;
 };
 
 /* General/base configuration */
@@ -46,23 +54,32 @@ struct SFDAQConfig
     SFDAQConfig();
     ~SFDAQConfig();
 
+    void add_input(const char*);
+    SFDAQModuleConfig* add_module_config(const char* module_name);
     void add_module_dir(const char*);
-    void set_input_spec(const char*, int instance_id = -1);
-    void set_module_name(const char*);
+    void set_batch_size(uint32_t);
     void set_mru_size(int);
-    void set_variable(const char* varkvp, int instance_id = -1);
+
+    uint32_t get_batch_size() const { return (batch_size == BATCH_SIZE_UNSET) ? BATCH_SIZE_DEFAULT : batch_size; }
+    uint32_t get_mru_size() const { return (mru_size == SNAPLEN_UNSET) ? SNAPLEN_DEFAULT : mru_size; }
 
     void overlay(const SFDAQConfig*);
 
     /* General configuration */
     std::vector<std::string> module_dirs;
-    std::string module_name;
-    /* Module configuration */
-    std::string input_spec;
-    std::vector<std::pair<std::string, std::string>> variables;
+    /* Instance configuration */
+    std::vector<std::string> inputs;
+    uint32_t batch_size;
     int mru_size;
     unsigned int timeout;
-    std::unordered_map<unsigned, SFDAQInstanceConfig*> instances;
+    std::vector<SFDAQModuleConfig*> module_configs;
+
+    /* Constants */
+    static constexpr uint32_t BATCH_SIZE_UNSET = 0;
+    static constexpr int SNAPLEN_UNSET = -1;
+    static constexpr uint32_t BATCH_SIZE_DEFAULT = 64;
+    static constexpr int SNAPLEN_DEFAULT = 1518;
+    static constexpr unsigned TIMEOUT_DEFAULT = 1000;
 };
 
 #endif
diff --git a/src/packet_io/sfdaq_instance.cc b/src/packet_io/sfdaq_instance.cc
new file mode 100644 (file)
index 0000000..9f889b0
--- /dev/null
@@ -0,0 +1,388 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// 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 along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// sfdaq_instance.cc author Michael Altizer <mialtize@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "sfdaq_instance.h"
+
+#include <daq.h>
+
+#include "log/messages.h"
+#include "main/snort_config.h"
+#include "protocols/packet.h"
+#include "protocols/vlan.h"
+
+#include "sfdaq_config.h"
+
+using namespace snort;
+
+SFDAQInstance::SFDAQInstance(const char* input, const SFDAQConfig* cfg)
+{
+    if (input)
+        input_spec = input;
+    batch_size = cfg->get_batch_size();
+    daq_msgs = new DAQ_Msg_h[batch_size];
+}
+
+SFDAQInstance::~SFDAQInstance()
+{
+    delete[] daq_msgs;
+    if (instance)
+        daq_instance_destroy(instance);
+}
+
+static bool DAQ_ValidateInstance(DAQ_Instance_h instance)
+{
+    uint32_t caps = daq_instance_get_capabilities(instance);
+
+    if (!SnortConfig::adaptor_inline_mode())
+        return true;
+
+    if (!(caps & DAQ_CAPA_BLOCK))
+        ParseWarning(WARN_DAQ, "inline mode configured but DAQ can't block packets.\n");
+
+    return true;
+}
+
+bool SFDAQInstance::init(DAQ_Config_h daqcfg, const std::string& bpf_string)
+{
+    char buf[256] = "";
+    int rval;
+
+    /* Reuse the main DAQ instance configuration with the input specification specific to this instance. */
+    daq_config_set_input(daqcfg, input_spec.c_str());
+    if ((rval = daq_instance_instantiate(daqcfg, &instance, buf, sizeof(buf))) != DAQ_SUCCESS)
+    {
+        ErrorMessage("Couldn't construct a DAQ instance: %s (%d)\n", buf, rval);
+        return false;
+    }
+
+    if (!DAQ_ValidateInstance(instance))
+        FatalError("DAQ configuration incompatible with intended operation.\n");
+
+    if (!bpf_string.empty())
+    {
+        rval = daq_instance_set_filter(instance, bpf_string.c_str());
+        if (rval != DAQ_SUCCESS)
+            FatalError("Couldn't set DAQ instance BPF filter to '%s': %s (%d)\n",
+                bpf_string.c_str(), daq_instance_get_error(instance), rval);
+    }
+
+    return true;
+}
+
+void SFDAQInstance::reload()
+{
+    if (!instance)
+        return;
+
+    void* new_config = nullptr;
+    if (daq_instance_config_load(instance, &new_config) == DAQ_SUCCESS)
+    {
+        void* old_config = nullptr;
+        if (daq_instance_config_swap(instance, new_config, &old_config) == DAQ_SUCCESS)
+            daq_instance_config_free(instance, old_config);
+        else
+            daq_instance_config_free(instance, new_config);
+    }
+}
+
+void SFDAQInstance::abort()
+{
+    if (was_started())
+        stop();
+
+    //DAQ_Delete();
+    //DAQ_Term();  FIXIT-L this must be called from main thread on abort
+}
+
+const char* SFDAQInstance::get_input_spec()
+{
+    return input_spec.c_str();
+}
+
+// That distinction does not hold with datalink types.  Snort must use whatever
+// datalink type the DAQ coughs up as its base protocol decoder.  For pcaps,
+// the datalink type in the file must be used - which may not be known until
+// start.  The value is cached here since it used for packet operations like
+// logging and is needed at shutdown.  This avoids sequencing issues.
+int SFDAQInstance::get_base_protocol()
+{
+    return dlt;
+}
+
+bool SFDAQInstance::can_inject()
+{
+    return (daq_instance_get_capabilities(instance) & DAQ_CAPA_INJECT) != 0;
+}
+
+bool SFDAQInstance::can_inject_raw()
+{
+    return (daq_instance_get_capabilities(instance) & DAQ_CAPA_INJECT_RAW) != 0;
+}
+
+bool SFDAQInstance::can_replace()
+{
+    return (daq_instance_get_capabilities(instance) & DAQ_CAPA_REPLACE) != 0;
+}
+
+bool SFDAQInstance::can_start_unprivileged()
+{
+    return (daq_instance_get_capabilities(instance) & DAQ_CAPA_UNPRIV_START) != 0;
+}
+
+bool SFDAQInstance::can_whitelist()
+{
+    return (daq_instance_get_capabilities(instance) & DAQ_CAPA_WHITELIST) != 0;
+}
+
+bool SFDAQInstance::start()
+{
+    int rval = daq_instance_start(instance);
+    if (rval != DAQ_SUCCESS)
+    {
+        ErrorMessage("Couldn't start DAQ instance: %s (%d)\n", daq_instance_get_error(instance), rval);
+        return false;
+    }
+
+    DAQ_MsgPoolInfo_t mpool_info;
+    rval = daq_instance_get_msg_pool_info(instance, &mpool_info);
+    if (rval != DAQ_SUCCESS)
+    {
+        ErrorMessage("Couldn't query DAQ message pool info: %s (%d)\n", daq_instance_get_error(instance), rval);
+        stop();
+        return false;
+    }
+    pool_size = mpool_info.size;
+    pool_available = mpool_info.available;
+    assert(pool_size == pool_available);
+
+    dlt = daq_instance_get_datalink_type(instance);
+    get_tunnel_capabilities();
+
+    return (rval == DAQ_SUCCESS);
+}
+
+DAQ_RecvStatus SFDAQInstance::receive_messages(unsigned max_recv)
+{
+    assert(max_recv <= batch_size);
+
+    if (max_recv > pool_available)
+        max_recv = pool_available;
+
+    DAQ_RecvStatus rstat;
+    curr_batch_size = daq_instance_msg_receive(instance, max_recv, daq_msgs, &rstat);
+    pool_available -= curr_batch_size;
+    curr_batch_idx = 0;
+
+    return rstat;
+}
+
+int SFDAQInstance::finalize_message(DAQ_Msg_h msg, DAQ_Verdict verdict)
+{
+    int rval = daq_instance_msg_finalize(instance, msg, verdict);
+    if (rval == DAQ_SUCCESS)
+        pool_available++;
+    return rval;
+}
+
+const char* SFDAQInstance::get_error()
+{
+    return daq_instance_get_error(instance);
+}
+
+void SFDAQInstance::get_tunnel_capabilities()
+{
+    daq_tunnel_mask = 0;
+    if (instance)
+    {
+        uint32_t caps = daq_instance_get_capabilities(instance);
+
+        if (caps & DAQ_CAPA_DECODE_GTP)
+            daq_tunnel_mask |= TUNNEL_GTP;
+        if (caps & DAQ_CAPA_DECODE_TEREDO)
+            daq_tunnel_mask |= TUNNEL_TEREDO;
+        if (caps & DAQ_CAPA_DECODE_GRE)
+            daq_tunnel_mask |= TUNNEL_GRE;
+        if (caps & DAQ_CAPA_DECODE_4IN4)
+            daq_tunnel_mask |= TUNNEL_4IN4;
+        if (caps & DAQ_CAPA_DECODE_6IN4)
+            daq_tunnel_mask |= TUNNEL_6IN4;
+        if (caps & DAQ_CAPA_DECODE_4IN6)
+            daq_tunnel_mask |= TUNNEL_4IN6;
+        if (caps & DAQ_CAPA_DECODE_6IN6)
+            daq_tunnel_mask |= TUNNEL_6IN6;
+        if (caps & DAQ_CAPA_DECODE_MPLS)
+            daq_tunnel_mask |= TUNNEL_MPLS;
+    }
+}
+
+bool SFDAQInstance::get_tunnel_bypass(uint8_t proto)
+{
+    return (daq_tunnel_mask & proto) != 0;
+}
+
+bool SFDAQInstance::was_started()
+{
+    DAQ_State s;
+
+    if (!instance)
+        return false;
+
+    s = daq_instance_check_status(instance);
+
+    return (DAQ_STATE_STARTED == s);
+}
+
+bool SFDAQInstance::stop()
+{
+    assert(pool_size == pool_available);
+
+    int rval = daq_instance_stop(instance);
+
+    if (rval != DAQ_SUCCESS)
+        LogMessage("Couldn't stop DAQ instance: %s (%d)\n", daq_instance_get_error(instance), rval);
+
+    return (rval == DAQ_SUCCESS);
+}
+
+int SFDAQInstance::inject(DAQ_Msg_h msg, int rev, const uint8_t* buf, uint32_t len)
+{
+    int rval = daq_instance_inject_relative(instance, msg, buf, len, rev);
+#ifdef DEBUG_MSGS
+    if (rval != DAQ_SUCCESS)
+        LogMessage("Couldn't inject on DAQ instance: %s (%d)\n", daq_instance_get_error(instance), rval);
+#endif
+    return rval;
+}
+
+bool SFDAQInstance::interrupt()
+{
+    return (daq_instance_interrupt(instance) == DAQ_SUCCESS);
+}
+
+const DAQ_Stats_t* SFDAQInstance::get_stats()
+{
+    if (instance)
+    {
+        int rval = daq_instance_get_stats(instance, &daq_stats);
+        if (rval != DAQ_SUCCESS)
+            LogMessage("Couldn't query DAQ stats: %s (%d)\n", daq_instance_get_error(instance), rval);
+
+        // Some DAQ modules don't provide hardware numbers, so we default HW RX to the SW equivalent
+        // (this means outstanding packets = 0)
+        if (daq_stats.hw_packets_received == 0)
+            daq_stats.hw_packets_received = daq_stats.packets_received + daq_stats.packets_filtered;
+    }
+
+    return &daq_stats;
+}
+
+int SFDAQInstance::ioctl(DAQ_IoctlCmd cmd, void *arg, size_t arglen)
+{
+    return daq_instance_ioctl(instance, cmd, arg, arglen);
+}
+
+int SFDAQInstance::modify_flow_opaque(DAQ_Msg_h msg, uint32_t opaque)
+{
+    DIOCTL_SetFlowOpaque d_sfo;
+    d_sfo.msg = msg;
+    d_sfo.value = opaque;
+
+    return daq_instance_ioctl(instance, DIOCTL_SET_FLOW_OPAQUE, &d_sfo, sizeof(d_sfo));
+}
+
+int SFDAQInstance::modify_flow_pkt_trace(DAQ_Msg_h msg, uint8_t verdict_reason, uint8_t* buff, uint32_t buff_len)
+{
+    DIOCTL_SetPacketTraceData d_sptd;
+
+    d_sptd.msg = msg;
+    d_sptd.verdict_reason = verdict_reason;
+    d_sptd.trace_data_len = buff_len;
+    d_sptd.trace_data = buff;
+
+    return daq_instance_ioctl(instance, DIOCTL_SET_PACKET_TRACE_DATA, &d_sptd, sizeof(d_sptd));
+}
+
+// FIXIT-L X Add Snort flag definitions for callers to use and translate/pass them through to
+// the DAQ module
+int SFDAQInstance::add_expected(const Packet* ctrlPkt, const SfIp* cliIP, uint16_t cliPort,
+        const SfIp* srvIP, uint16_t srvPort, IpProtocol protocol, unsigned timeout_ms, unsigned /* flags */)
+{
+    DIOCTL_CreateExpectedFlow d_cef;
+
+    d_cef.ctrl_msg = ctrlPkt->daq_msg;
+
+    /* Populate the expected flow key */
+    DAQ_EFlow_Key_t* key = &d_cef.key;
+
+    key->src_af = cliIP->get_family();
+    if (cliIP->is_ip4())
+        key->sa.src_ip4.s_addr = cliIP->get_ip4_value();
+    else
+        memcpy(&key->sa.src_ip6, cliIP->get_ip6_ptr(), sizeof(key->sa.src_ip6));
+    key->src_port = cliPort;
+
+    key->dst_af = srvIP->get_family();
+    if (srvIP->is_ip4())
+        key->da.dst_ip4.s_addr = srvIP->get_ip4_value();
+    else
+        memcpy(&key->da.dst_ip6, srvIP->get_ip6_ptr(), sizeof(key->da.dst_ip6));
+    key->dst_port = srvPort;
+
+    // FIXIT-M The key address_space_id is not currently being populated!
+
+    if (ctrlPkt->proto_bits & PROTO_BIT__GTP)
+        key->tunnel_type = DAQ_EFLOW_TUNNEL_TYPE_GTP_TUNNEL;
+    else if (ctrlPkt->proto_bits & PROTO_BIT__MPLS)
+        key->tunnel_type = DAQ_EFLOW_TUNNEL_TYPE_MPLS_TUNNEL;
+    // FIXIT-L Need to figure out the right way to determine "Other" encapsulation
+/*
+    else if ( ctrlPkt->encapsulated )
+        key->tunnel_type = DAQ_EFLOW_TUNNEL_TYPE_OTHER_TUNNEL;
+*/
+    else
+        key->tunnel_type = DAQ_EFLOW_TUNNEL_TYPE_NON_TUNNEL;
+
+    key->protocol = (uint8_t) protocol;
+    if (ctrlPkt->proto_bits & PROTO_BIT__VLAN)
+        key->vlan_id = layer::get_vlan_layer(ctrlPkt)->vid();
+    else
+        key->vlan_id = 0xFFFF;
+    key->vlan_cnots = 1;
+
+    d_cef.flags = 0;
+/*
+    if (flags & DAQ_DC_FLOAT)
+        d_cef.flags |= DAQ_EFLOW_FLOAT;
+    if (flags & DAQ_DC_ALLOW_MULTIPLE)
+        d_cef.flags |= DAQ_EFLOW_ALLOW_MULTIPLE;
+    if (flags & DAQ_DC_PERSIST)
+        d_cef.flags |= DAQ_EFLOW_PERSIST;
+*/
+    d_cef.timeout_ms = timeout_ms;
+    // Opaque data blob for expected flows is currently unused/unimplemented
+    d_cef.data = nullptr;
+    d_cef.length = 0;
+
+    return daq_instance_ioctl(instance, DIOCTL_CREATE_EXPECTED_FLOW, &d_cef, sizeof(d_cef));
+}
diff --git a/src/packet_io/sfdaq_instance.h b/src/packet_io/sfdaq_instance.h
new file mode 100644 (file)
index 0000000..bc256d8
--- /dev/null
@@ -0,0 +1,103 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2014-2019 Cisco and/or its affiliates. All rights reserved.
+// Copyright (C) 2005-2013 Sourcefire, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// 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 along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// sfdaq.h author Michael Altizer <mialtize@cisco.com>
+
+#ifndef SFDAQ_INSTANCE_H
+#define SFDAQ_INSTANCE_H
+
+#include <daq_common.h>
+
+#include <string>
+
+#include "main/snort_types.h"
+#include "protocols/protocol_ids.h"
+
+struct SFDAQConfig;
+
+namespace snort
+{
+struct Packet;
+struct SfIp;
+
+class SFDAQInstance
+{
+public:
+    SFDAQInstance(const char* intf, const SFDAQConfig*);
+    ~SFDAQInstance();
+
+    bool init(DAQ_Config_h, const std::string& bpf_string);
+
+    bool start();
+    bool was_started();
+    bool stop();
+    void reload();
+    void abort();
+
+    DAQ_RecvStatus receive_messages(unsigned max_recv);
+    DAQ_Msg_h next_message()
+    {
+        if (curr_batch_idx < curr_batch_size)
+            return daq_msgs[curr_batch_idx++];
+        return nullptr;
+    }
+    int finalize_message(DAQ_Msg_h msg, DAQ_Verdict verdict);
+    const char* get_error();
+
+    int get_base_protocol();
+    uint32_t get_batch_size() { return batch_size; }
+    const char* get_input_spec();
+    const DAQ_Stats_t* get_stats();
+
+    bool can_inject();
+    bool can_inject_raw();
+    bool can_replace();
+    bool can_start_unprivileged();
+    SO_PUBLIC bool can_whitelist();
+
+    int inject(DAQ_Msg_h, int rev, const uint8_t* buf, uint32_t len);
+    bool interrupt();
+
+    SO_PUBLIC int ioctl(DAQ_IoctlCmd cmd, void *arg, size_t arglen);
+    SO_PUBLIC int modify_flow_opaque(DAQ_Msg_h, uint32_t opaque);
+    int modify_flow_pkt_trace(DAQ_Msg_h, uint8_t verdict_reason,
+        uint8_t* buff, uint32_t buff_len);
+    int add_expected(const Packet* ctrlPkt, const SfIp* cliIP, uint16_t cliPort,
+            const SfIp* srvIP, uint16_t srvPort, IpProtocol, unsigned timeout_ms,
+            unsigned /* flags */);
+    bool get_tunnel_bypass(uint8_t proto);
+
+private:
+    void get_tunnel_capabilities();
+
+    std::string input_spec;
+    DAQ_Instance_h instance = nullptr;
+    DAQ_Msg_h* daq_msgs;
+    unsigned curr_batch_size = 0;
+    unsigned curr_batch_idx = 0;
+    uint32_t batch_size;
+    uint32_t pool_size = 0;
+    uint32_t pool_available = 0;
+    int dlt = -1;
+    DAQ_Stats_t daq_stats = { };
+    uint8_t daq_tunnel_mask = 0;
+};
+}
+#endif
+
index bb3261ab41a92e3d38e7b0d8afecf015ae465aa0..c15cf9c206d54c9441a554eaae755b8fbe5a6242 100644 (file)
@@ -38,78 +38,47 @@ using namespace snort;
 
 #define sfdaq_help "configure packet acquisition interface"
 
-struct DAQStats
+/*
+ * Module Configuration
+ */
+
+static const Parameter daqvar_list_param[] =
 {
-    PegCount pcaps;
-    PegCount received;
-    PegCount analyzed;
-    PegCount dropped;
-    PegCount filtered;
-    PegCount outstanding;
-    PegCount injected;
-    PegCount verdicts[MAX_DAQ_VERDICT];
-    PegCount internal_blacklist;
-    PegCount internal_whitelist;
-    PegCount skipped;
-    PegCount idle;
-    PegCount rx_bytes;
+    { "variable", Parameter::PT_STRING, nullptr, nullptr, "DAQ module variable (foo[=bar])" },
+
+    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
 
-const PegInfo daq_names[] =
+static const Parameter daq_module_param[] = 
 {
-    { CountType::MAX, "pcaps", "total files and interfaces processed" },
-    { CountType::SUM, "received", "total packets received from DAQ" },
-    { CountType::SUM, "analyzed", "total packets analyzed from DAQ" },
-    { CountType::SUM, "dropped", "packets dropped" },
-    { CountType::SUM, "filtered", "packets filtered out" },
-    { CountType::SUM, "outstanding", "packets unprocessed" },
-    { CountType::SUM, "injected", "active responses or replacements" },
-    { CountType::SUM, "allow", "total allow verdicts" },
-    { CountType::SUM, "block", "total block verdicts" },
-    { CountType::SUM, "replace", "total replace verdicts" },
-    { CountType::SUM, "whitelist", "total whitelist verdicts" },
-    { CountType::SUM, "blacklist", "total blacklist verdicts" },
-    { CountType::SUM, "ignore", "total ignore verdicts" },
-    { CountType::SUM, "retry", "total retry verdicts" },
+    { "name", Parameter::PT_STRING, nullptr, nullptr, "DAQ module name (required)" },
+    { "mode", Parameter::PT_ENUM, "passive | inline | read-file", "passive", "DAQ module mode" },
+    { "variables", Parameter::PT_LIST, daqvar_list_param, nullptr, "DAQ module variables" },
 
-    // FIXIT-L these are not exactly DAQ counts - but they are related
-    { CountType::SUM, "internal_blacklist",
-        "packets blacklisted internally due to lack of DAQ support" },
-    { CountType::SUM, "internal_whitelist",
-        "packets whitelisted internally due to lack of DAQ support" },
-    { CountType::SUM, "skipped", "packets skipped at startup" },
-    { CountType::SUM, "idle", "attempts to acquire from DAQ without available packets" },
-    { CountType::SUM, "rx_bytes", "total bytes received" },
-    { CountType::END, nullptr, nullptr }
+    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
 
-static THREAD_LOCAL DAQStats stats;
-
-static const Parameter string_list_param[] =
+static const Parameter path_list_param[] =
 {
-    { "str", Parameter::PT_STRING, nullptr, nullptr, "string parameter" },
+    { "path", Parameter::PT_STRING, nullptr, nullptr, "directory path" },
 
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
 
-static const Parameter instance_params[] =
+static const Parameter input_list_param[] =
 {
-    { "id", Parameter::PT_INT, "0:max32", nullptr, "instance ID (required)" },
-    { "input_spec", Parameter::PT_STRING, nullptr, nullptr, "input specification" },
-    { "variables", Parameter::PT_LIST, string_list_param, nullptr, "DAQ variables" },
+    { "input", Parameter::PT_STRING, nullptr, nullptr, "input source" },
 
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
 
 static const Parameter s_params[] =
 {
-    { "module_dirs", Parameter::PT_LIST, string_list_param, nullptr, "directories to search for DAQ modules" },
-    { "input_spec", Parameter::PT_STRING, nullptr, nullptr, "input specification" },
-    { "module", Parameter::PT_STRING, nullptr, nullptr, "DAQ module to use" },
-    { "variables", Parameter::PT_LIST, string_list_param, nullptr, "DAQ variables" },
-    { "instances", Parameter::PT_LIST, instance_params, nullptr, "DAQ instance overrides" },
-    { "snaplen", Parameter::PT_INT, "0:65535", nullptr, "set snap length (same as -s)" },
-    { "no_promisc", Parameter::PT_BOOL, nullptr, "false", "whether to put DAQ device into promiscuous mode" },
+    { "module_dirs", Parameter::PT_LIST, path_list_param, nullptr, "directories to search for dynamic DAQ modules" },
+    { "inputs", Parameter::PT_LIST, input_list_param, nullptr, "input sources" },
+    { "snaplen", Parameter::PT_INT, "0:65535", "1518", "set snap length (same as -s)" },
+    { "batch_size", Parameter::PT_INT, "1:", "64", "set receive batch size (same as --daq-batch-size)" },
+    { "modules", Parameter::PT_LIST, daq_module_param, nullptr, "DAQ modules to use" },
 
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
@@ -117,65 +86,53 @@ static const Parameter s_params[] =
 SFDAQModule::SFDAQModule() : Module("daq", sfdaq_help, s_params)
 {
     config = nullptr;
-    instance_config = nullptr;
+    module_config = nullptr;
 }
 
-
 bool SFDAQModule::begin(const char* fqn, int idx, SnortConfig*)
 {
     if (!strcmp(fqn, "daq"))
         config = new SFDAQConfig();
-
-    else if (!strcmp(fqn, "daq.instances"))
+    else if (!strcmp(fqn, "daq.modules"))
     {
         if (idx == 0)
             return true;
 
-        assert(!instance_config);
-        instance_config = new SFDAQInstanceConfig();
-
-        instance_id = -1;
+        module_config = new SFDAQModuleConfig();
     }
+
     return true;
 }
 
-bool SFDAQModule::set(const char* fqn, Value& v, SnortConfig* sc)
+bool SFDAQModule::set(const char* fqn, Value& v, SnortConfig*)
 {
     if (!strcmp(fqn, "daq.module_dirs"))
     {
         config->add_module_dir(v.get_string());
     }
-    else if (!strcmp(fqn, "daq.module"))
-    {
-        config->set_module_name(v.get_string());
-    }
-    else if (!strcmp(fqn, "daq.input_spec"))
+    else if (!strcmp(fqn, "daq.inputs"))
     {
-        config->set_input_spec(v.get_string());
-    }
-    else if (!strcmp(fqn, "daq.variables"))
-    {
-        config->set_variable(v.get_string());
+        config->add_input(v.get_string());
     }
     else if (!strcmp(fqn, "daq.snaplen"))
     {
         config->set_mru_size(v.get_uint16());
     }
-    else if (!strcmp(fqn, "daq.no_promisc"))
+    else if (!strcmp(fqn, "daq.batch_size"))
     {
-        v.update_mask(sc->run_flags, RUN_FLAG__NO_PROMISCUOUS);
+        config->set_batch_size(v.get_long());
     }
-    else if (!strcmp(fqn, "daq.instances.id"))
+    else if (!strcmp(fqn, "daq.modules.name"))
     {
-        instance_id = v.get_uint32();
+        module_config->name = v.get_string();
     }
-    else if (!strcmp(fqn, "daq.instances.input_spec"))
+    else if (!strcmp(fqn, "daq.modules.mode"))
     {
-        instance_config->set_input_spec(v.get_string());
+        module_config->mode = (SFDAQModuleConfig::SFDAQMode) (v.get_long() + 1);
     }
-    else if (!strcmp(fqn, "daq.instances.variables"))
+    else if (!strcmp(fqn, "daq.modules.variables"))
     {
-        instance_config->set_variable(v.get_string());
+        module_config->set_variable(v.get_string());
     }
 
     return true;
@@ -183,20 +140,20 @@ bool SFDAQModule::set(const char* fqn, Value& v, SnortConfig* sc)
 
 bool SFDAQModule::end(const char* fqn, int idx, SnortConfig* sc)
 {
-    if (!strcmp(fqn, "daq.instances"))
+    if (!strcmp(fqn, "daq.modules"))
     {
         if (idx == 0)
             return true;
 
-        if (instance_id < 0 or config->instances[instance_id])
+        if (module_config->name.empty())
         {
-            ParseError("%s - duplicate or no DAQ instance ID specified", fqn);
-            delete instance_config;
-            instance_config = nullptr;
+            ParseError("%s - No module name specified!", fqn);
+            delete module_config;
+            module_config = nullptr;
             return false;
         }
-        config->instances[instance_id] = instance_config;
-        instance_config = nullptr;
+        config->module_configs.push_back(module_config);
+        module_config = nullptr;
     }
     else if (!strcmp(fqn, "daq"))
     {
@@ -210,6 +167,57 @@ bool SFDAQModule::end(const char* fqn, int idx, SnortConfig* sc)
     return true;
 }
 
+/*
+ * Module Counters
+ */
+
+struct DAQStats
+{
+    PegCount pcaps;
+    PegCount received;
+    PegCount analyzed;
+    PegCount dropped;
+    PegCount filtered;
+    PegCount outstanding;
+    PegCount injected;
+    PegCount verdicts[MAX_DAQ_VERDICT];
+    PegCount internal_blacklist;
+    PegCount internal_whitelist;
+    PegCount skipped;
+    PegCount idle;
+    PegCount rx_bytes;
+};
+
+const PegInfo daq_names[] =
+{
+    { CountType::MAX, "pcaps", "total files and interfaces processed" },
+    { CountType::SUM, "received", "total packets received from DAQ" },
+    { CountType::SUM, "analyzed", "total packets analyzed from DAQ" },
+    { CountType::SUM, "dropped", "packets dropped" },
+    { CountType::SUM, "filtered", "packets filtered out" },
+    { CountType::SUM, "outstanding", "packets unprocessed" },
+    { CountType::SUM, "injected", "active responses or replacements" },
+    { CountType::SUM, "allow", "total allow verdicts" },
+    { CountType::SUM, "block", "total block verdicts" },
+    { CountType::SUM, "replace", "total replace verdicts" },
+    { CountType::SUM, "whitelist", "total whitelist verdicts" },
+    { CountType::SUM, "blacklist", "total blacklist verdicts" },
+    { CountType::SUM, "ignore", "total ignore verdicts" },
+    { CountType::SUM, "retry", "total retry verdicts" },
+
+    // FIXIT-L these are not exactly DAQ counts - but they are related
+    { CountType::SUM, "internal_blacklist",
+        "packets blacklisted internally due to lack of DAQ support" },
+    { CountType::SUM, "internal_whitelist",
+        "packets whitelisted internally due to lack of DAQ support" },
+    { CountType::SUM, "skipped", "packets skipped at startup" },
+    { CountType::SUM, "idle", "attempts to acquire from DAQ without available packets" },
+    { CountType::SUM, "rx_bytes", "total bytes received" },
+    { CountType::END, nullptr, nullptr }
+};
+
+static THREAD_LOCAL DAQStats stats;
+
 const PegInfo* SFDAQModule::get_pegs() const
 {
     return daq_names;
@@ -239,7 +247,6 @@ static DAQ_Stats_t operator-(const DAQ_Stats_t& left, const DAQ_Stats_t& right)
 void SFDAQModule::prep_counts()
 {
     static THREAD_LOCAL DAQ_Stats_t sfdaq_stats;
-    static THREAD_LOCAL PegCount last_skipped = 0;
     static THREAD_LOCAL bool did_init = false;
 
     if ( !did_init )
@@ -273,12 +280,11 @@ void SFDAQModule::prep_counts()
 
     stats.internal_blacklist = aux_counts.internal_blacklist;
     stats.internal_whitelist = aux_counts.internal_whitelist;
-    stats.skipped = SnortConfig::get_conf()->pkt_skip - last_skipped;
+    stats.skipped = aux_counts.skipped;
     stats.idle = aux_counts.idle;
     stats.rx_bytes = aux_counts.rx_bytes;
 
     memset(&aux_counts, 0, sizeof(AuxCount));
-    last_skipped = stats.skipped;
 
     sfdaq_stats = new_sfdaq_stats;
     for ( unsigned i = 0; i < MAX_DAQ_VERDICT; i++ )
index c126c3c4ef385e2542bb9c3ac8e8e3169838abc9..b855a8b0f992820583fe1ee746f3ce07ea16d013 100644 (file)
@@ -28,7 +28,7 @@ namespace snort
 struct SnortConfig;
 }
 struct SFDAQConfig;
-struct SFDAQInstanceConfig;
+struct SFDAQModuleConfig;
 
 class SFDAQModule : public snort::Module
 {
@@ -51,8 +51,7 @@ public:
 
 private:
     SFDAQConfig* config;
-    SFDAQInstanceConfig* instance_config;
-    int instance_id;
+    SFDAQModuleConfig* module_config;
 };
 
 #endif
diff --git a/src/packet_io/sfdaq_static_modules.h.in b/src/packet_io/sfdaq_static_modules.h.in
new file mode 100644 (file)
index 0000000..b1d11df
--- /dev/null
@@ -0,0 +1,11 @@
+
+#include <daq_module_api.h>
+
+@DAQ_STATIC_MODULE_EXTERNS@
+
+static DAQ_Module_h static_daq_modules[] =
+{
+@DAQ_STATIC_MODULE_DATA_ARRAY@
+    nullptr
+};
+
index e60f2057db6bb6c1c9e810000e165ec55ee36d2f..b846a06b8837fb57f1a32529083f9b6801c4e51d 100644 (file)
 
 using namespace snort;
 
-TEST_CASE("Kitchen Sink", "[SFDAQModule]")
+
+TEST_CASE("parse sfdaq config", "[SFDAQModule]")
 {
-    SFDAQModule sfdm;
     SnortConfig sc;
+    SFDAQModule sfdm;
 
     /* Generate the configuration */
     sfdm.begin("daq", 0, &sc);
 
     Value module_dir1("/test/dir/1");
-    Value module_dir2("/test/dir/2");
     CHECK(sfdm.set("daq.module_dirs", module_dir1, &sc));
+
+    Value module_dir2("/test/dir/2");
     CHECK(sfdm.set("daq.module_dirs", module_dir2, &sc));
 
-    Value module_name("test_module");
-    CHECK(sfdm.set("daq.module", module_name, &sc));
+    Value input1("test_input1");
+    CHECK(sfdm.set("daq.inputs", input1, &sc));
 
-    Value input_spec("test_input");
-    CHECK(sfdm.set("daq.input_spec", input_spec, &sc));
+    Value input2("test_input2");
+    CHECK(sfdm.set("daq.inputs", input2, &sc));
 
-    Value var1("foo=bar");
-    Value var2("debug");
-    Value var3("hello=world");
-    CHECK(sfdm.set("daq.variables", var1, &sc));
-    CHECK(sfdm.set("daq.variables", var2, &sc));
-    CHECK(sfdm.set("daq.variables", var3, &sc));
+    Value input3("test_input3");
+    CHECK(sfdm.set("daq.inputs", input3, &sc));
 
     Value snaplen(static_cast<double>(6666));
     CHECK(sfdm.set("daq.snaplen", snaplen, &sc));
 
-    Value no_promisc(true);
-    CHECK(sfdm.set("daq.no_promisc", no_promisc, &sc));
+    Value batch_size(static_cast<double>(10));
+    CHECK(sfdm.set("daq.batch_size", batch_size, &sc));
 
-    CHECK(sfdm.begin("daq.instances", 0, &sc));
-    CHECK(sfdm.begin("daq.instances", 1, &sc));
+    CHECK(sfdm.begin("daq.modules", 0, &sc));
 
-    CHECK_FALSE(sfdm.end("daq.instances", 1, &sc));
-    CHECK(sfdm.begin("daq.instances", 2, &sc));
+    SECTION("empty module config")
+    {
+        // Empty module table entry should fail
+        CHECK(sfdm.begin("daq.modules", 1, &sc));
+        CHECK_FALSE(sfdm.end("daq.modules", 1, &sc));
+    }
+
+    CHECK(sfdm.begin("daq.modules", 2, &sc));
+
+    Value module_name("dump");
+    CHECK(sfdm.set("daq.modules.name", module_name, &sc));
 
-    Value instance_id(static_cast<double>(5));
-    CHECK(sfdm.set("daq.instances.id", instance_id, &sc));
+    Value mode_val("passive");
+    Parameter mode_param = { "mode", Parameter::PT_ENUM, "passive | inline | read-file", "passive", "DAQ module mode" };
+    mode_val.set(&mode_param);
+    CHECK(sfdm.set("daq.modules.mode", mode_val, &sc));
 
-    Value instance_input_spec("instance_5_input");
-    CHECK(sfdm.set("daq.instances.input_spec", instance_input_spec, &sc));
+    Value dump_var1("dump_var1=foo");
+    CHECK(sfdm.set("daq.modules.variables", dump_var1, &sc));
 
-    Value instance_var1("instance5_var1=foo");
-    Value instance_var2("instance5_var2");
-    CHECK(sfdm.set("daq.instances.variables", instance_var1, &sc));
-    CHECK(sfdm.set("daq.instances.variables", instance_var2, &sc));
+    Value dump_var2("dump_var2");
+    CHECK(sfdm.set("daq.modules.variables", dump_var2, &sc));
 
-    CHECK(sfdm.end("daq.instances", 2, &sc));
-    CHECK(sfdm.end("daq.instances", 0, &sc));
+    CHECK(sfdm.end("daq.modules", 2, &sc));
+    CHECK(sfdm.end("daq.modules", 0, &sc));
     CHECK(sfdm.end("daq", 0, &sc));
 
-    /* Validate the configuration */
-    SFDAQConfig *cfg = sc.daq_config;
+    SECTION("validate sfdaq config")
+    {
+        /* Validate the configuration */
+        SFDAQConfig* cfg = sc.daq_config;
+        REQUIRE((cfg->module_dirs.size() == 2));
+        CHECK(cfg->module_dirs[0] == module_dir1.get_string());
+        CHECK(cfg->module_dirs[1] == module_dir2.get_string());
+
+        REQUIRE((cfg->inputs.size() == 3));
+        CHECK(cfg->inputs[0] == input1.get_string());
+        CHECK(cfg->inputs[1] == input2.get_string());
+        CHECK(cfg->inputs[2] == input3.get_string());
+
+        CHECK((cfg->mru_size == 6666));
+        CHECK((cfg->batch_size == 10));
+
+        REQUIRE(cfg->module_configs.size() == 1);
+        for (auto it : cfg->module_configs)
+        {
+            SFDAQModuleConfig* mcfg = it;
+            CHECK((mcfg->name == module_name.get_string()));
+            CHECK((mcfg->mode == SFDAQModuleConfig::SFDAQ_MODE_PASSIVE));
+            REQUIRE((mcfg->variables.size() == 2));
+            CHECK(mcfg->variables[0].first == "dump_var1");
+            CHECK(mcfg->variables[0].second == "foo");
+            CHECK(mcfg->variables[1].first == dump_var2.get_string());
+            CHECK(mcfg->variables[1].second.empty());
+        }
+    }
 
-    REQUIRE((cfg->module_dirs.size() == 2));
-    CHECK(cfg->module_dirs[0] == module_dir1.get_string());
-    CHECK(cfg->module_dirs[1] == module_dir2.get_string());
+    SECTION("sfdaq command line config and overlay verification")
+    {
+        /* Secondary config to overlay from, for example, the command line */
+        SFDAQConfig overlay_cfg;
 
-    CHECK(cfg->module_name == module_name.get_string());
+        overlay_cfg.add_module_dir("cli_module_dir");
+        overlay_cfg.add_input("cli_input");
+        overlay_cfg.set_mru_size(3333);
+        overlay_cfg.set_batch_size(12);
 
-    CHECK(cfg->input_spec == input_spec.get_string());
+        SFDAQModuleConfig* cli_module_cfg = overlay_cfg.add_module_config("cli_module_name");
 
-    REQUIRE((cfg->variables.size() == 3));
-    CHECK(cfg->variables[0].first == "foo");
-    CHECK(cfg->variables[0].second == "bar");
-    CHECK(cfg->variables[1].first == "debug");
-    CHECK(cfg->variables[1].second.empty());
-    CHECK(cfg->variables[2].first == "hello");
-    CHECK(cfg->variables[2].second == "world");
+        cli_module_cfg->set_variable("cli_module_variable=abc");
+        cli_module_cfg->mode = SFDAQModuleConfig::SFDAQ_MODE_READ_FILE;
 
-    CHECK((cfg->mru_size == 6666));
+        SFDAQModuleConfig* cli_dump_cfg = overlay_cfg.add_module_config("dump");
 
-    REQUIRE(cfg->instances.size() == 1);
-    for (auto it : cfg->instances)
-    {
-        CHECK((it.first == 5));
-        SFDAQInstanceConfig* icfg = it.second;
-        CHECK(icfg->input_spec == instance_input_spec.get_string());
-        REQUIRE((icfg->variables.size() == 2));
-        CHECK(icfg->variables[0].first == "instance5_var1");
-        CHECK(icfg->variables[0].second == "foo");
-        CHECK(icfg->variables[1].first == instance_var2.get_string());
-        CHECK(icfg->variables[1].second.empty());
-    }
+        cli_dump_cfg->mode = SFDAQModuleConfig::SFDAQ_MODE_INLINE;
+        cli_dump_cfg->set_variable("dump_var3");
+        cli_dump_cfg->set_variable("dump_var4=bar");
+        cli_dump_cfg->set_variable("dump_var5=foo");
 
-    /* Secondary config to overlay from, for example, the command line */
-    SnortConfig sc2;
-
-    sc2.daq_config->add_module_dir("cli_module_dir");
-    sc2.daq_config->set_module_name("cli_module_name");
-    sc2.daq_config->set_input_spec(nullptr);
-    sc2.daq_config->set_input_spec("cli_input_spec");
-    sc2.daq_config->set_variable("cli_global_variable=abc");
-    sc2.daq_config->set_mru_size(3333);
-    sc2.daq_config->set_input_spec(nullptr, 2);
-    sc2.daq_config->set_input_spec("cli_instance_2_input", 2);
-    sc2.daq_config->set_input_spec("cli_instance_5_input", 5);
-    sc2.daq_config->set_variable("cli_instance_5_var1=def", 5);
-
-    cfg->overlay(sc2.daq_config);
-
-    REQUIRE(cfg->module_dirs.size() == 1);
-    CHECK(cfg->module_dirs[0] == "cli_module_dir");
-    CHECK(cfg->module_name == "cli_module_name");
-    CHECK(cfg->input_spec == "cli_input_spec");
-    REQUIRE(cfg->variables.size() == 1);
-    CHECK(cfg->variables[0].first == "cli_global_variable");
-    CHECK(cfg->variables[0].second == "abc");
-    CHECK((cfg->mru_size == 3333));
-    REQUIRE((cfg->instances.size() == 2));
-    for (auto it : cfg->instances)
-    {
-        CHECK((it.first == 2 || it.first == 5));
-        if (it.first == 2)
-        {
-            SFDAQInstanceConfig* icfg = it.second;
-            CHECK(icfg->input_spec == "cli_instance_2_input");
-            CHECK(icfg->variables.empty());
-        }
-        else if (it.first == 5)
+        SFDAQConfig* cfg = sc.daq_config;
+        cfg->overlay(&overlay_cfg);
+
+        REQUIRE(cfg->module_dirs.size() == 1);
+        CHECK(cfg->module_dirs[0] == "cli_module_dir");
+
+        REQUIRE((cfg->inputs.size() == 1));
+        CHECK(cfg->inputs[0] == "cli_input");
+
+        CHECK((cfg->mru_size == 3333));
+        CHECK((cfg->batch_size == 12));
+
+        REQUIRE(cfg->module_configs.size() == 2);
+        for (auto it : cfg->module_configs)
         {
-            SFDAQInstanceConfig* icfg = it.second;
-            CHECK(icfg->input_spec == "cli_instance_5_input");
-            REQUIRE(icfg->variables.size() == 1);
-            CHECK(icfg->variables[0].first == "cli_instance_5_var1");
-            CHECK(icfg->variables[0].second == "def");
+            SFDAQModuleConfig* mcfg = it;
+            CHECK((mcfg->name == "cli_module_name" or mcfg->name == "dump"));
+            if (mcfg->name == "cli_module_name")
+            {
+                CHECK(mcfg->mode == SFDAQModuleConfig::SFDAQ_MODE_READ_FILE);
+                REQUIRE((mcfg->variables.size() == 1));
+                CHECK(mcfg->variables[0].first == "cli_module_variable");
+                CHECK(mcfg->variables[0].second == "abc");
+            }
+            else if (mcfg->name == "dump")
+            {
+                CHECK(mcfg->mode == SFDAQModuleConfig::SFDAQ_MODE_INLINE);
+                REQUIRE((mcfg->variables.size() == 3));
+                CHECK(mcfg->variables[0].first == "dump_var3");
+                CHECK(mcfg->variables[0].second.empty());
+                CHECK(mcfg->variables[1].first == "dump_var4");
+                CHECK(mcfg->variables[1].second == "bar");
+                CHECK(mcfg->variables[2].first == "dump_var5");
+                CHECK(mcfg->variables[2].second == "foo");
+            }
         }
     }
 }
-
index 32fedd8ba8ec5ecebdaa951ab6b641823248ba8d..2cb6889dafd0bc8ec854561c597d7321bf8509e0 100644 (file)
@@ -28,7 +28,7 @@
 #include "detection/detect.h"
 #include "detection/detection_engine.h"
 #include "log/messages.h"
-#include "main/snort.h"
+#include "main/analyzer.h"
 #include "main/policy.h"
 
 #include "mstring.h"
@@ -44,6 +44,8 @@
 #define CHECKSUM_MODE_OPT__ICMP     "icmp"
 #define CHECKSUM_MODE_OPT__NO_ICMP  "noicmp"
 
+using namespace snort;
+
 static std::string lua_conf;
 static std::string snort_conf_dir;
 
@@ -67,7 +69,7 @@ static int GetChecksumFlags(const char* args)
     if (args == nullptr)
         return CHECKSUM_FLAG__ALL;
 
-    toks = snort::mSplit(args, " \t", 10, &num_toks, 0);
+    toks = mSplit(args, " \t", 10, &num_toks, 0);
     for (i = 0; i < num_toks; i++)
     {
         if (strcasecmp(toks[i], CHECKSUM_MODE_OPT__ALL) == 0)
@@ -132,7 +134,7 @@ static int GetChecksumFlags(const char* args)
         }
         else
         {
-            snort::ParseError("unknown command line checksum option: %s.", toks[i]);
+            ParseError("unknown command line checksum option: %s.", toks[i]);
             return ret_flags;
         }
     }
@@ -160,19 +162,19 @@ static int GetChecksumFlags(const char* args)
         ret_flags = negative_flags;
     }
 
-    snort::mSplitFree(&toks, num_toks);
+    mSplitFree(&toks, num_toks);
     return ret_flags;
 }
 
 void ConfigChecksumDrop(const char* args)
 {
-    NetworkPolicy* policy = snort::get_network_policy();
+    NetworkPolicy* policy = get_network_policy();
     policy->checksum_drop = GetChecksumFlags(args);
 }
 
 void ConfigChecksumMode(const char* args)
 {
-    NetworkPolicy* policy = snort::get_network_policy();
+    NetworkPolicy* policy = get_network_policy();
     policy->checksum_eval = GetChecksumFlags(args);
 }
 
@@ -180,7 +182,7 @@ void config_conf(const char* val)
 {
     lua_conf = val;
     SetSnortConfDir(lua_conf.c_str());
-    snort::Snort::set_main_hook(snort::DetectionEngine::inspect);
+    Analyzer::set_main_hook(DetectionEngine::inspect);
 }
 
 void SetSnortConfDir(const char* file)
index 2e475d403a49cc577e7905d343ccc45e377a3dfa..344c94edd6514cc3b5e0579905677079eaf15814 100644 (file)
@@ -112,18 +112,14 @@ static const luaL_Reg methods[] =
 
             if ( RawBufferIface.is(L, 2) )
             {
-                RawData rd(&daq, get_data(RawBufferIface.get(L, 2)));
+                RawData rd(nullptr, &daq, get_data(RawBufferIface.get(L, 2)), get_data_length(RawBufferIface.get(L, 2)));
                 result = self.decode(rd, cd, dd);
             }
             else
             {
                 size_t len = 0;
-                RawData rd(
-                    &daq,
-                    reinterpret_cast<const uint8_t*>(
-                        luaL_checklstring(L, 2, &len)
-                    )
-                );
+                const uint8_t* data = reinterpret_cast<const uint8_t*>(luaL_checklstring(L, 2, &len));
+                RawData rd(nullptr, &daq, data, len);
 
                 result = self.decode(rd, cd, dd);
             }
index 0cbaecbfaecdd4f039504506e3d2517556f29e50..669fcbc9b58f07461587f961a4f00136202ee715 100644 (file)
 
 #include "lua/lua_arg.h"
 
-static void set_fields(lua_State* L, int tindex, struct _daq_pkthdr& self)
+static void set_fields(lua_State* L, int tindex, DAQ_PktHdr_t& self)
 {
     Lua::Table table(L, tindex);
 
-    table.get_field("caplen", self.caplen);
     table.get_field("pktlen", self.pktlen);
     table.get_field("ingress_index", self.ingress_index);
     table.get_field("egress_index", self.egress_index);
@@ -47,11 +46,10 @@ static void set_fields(lua_State* L, int tindex, struct _daq_pkthdr& self)
     // FIXIT-L do we want to be able to set the priv_ptr field?
 }
 
-static void get_fields(lua_State* L, int tindex, struct _daq_pkthdr& self)
+static void get_fields(lua_State* L, int tindex, DAQ_PktHdr_t& self)
 {
     Lua::Table table(L, tindex);
 
-    table.set_field("caplen", self.caplen);
     table.set_field("pktlen", self.pktlen);
     table.set_field("ingress_index", self.ingress_index);
     table.set_field("egress_index", self.egress_index);
@@ -107,7 +105,7 @@ static const luaL_Reg metamethods[] =
     { nullptr, nullptr }
 };
 
-const struct Lua::TypeInterface<_daq_pkthdr> DAQHeaderIface =
+const struct Lua::TypeInterface<DAQ_PktHdr_t> DAQHeaderIface =
 {
     "DAQHeader",
     methods,
index b363b4561e4e9b92a5a65a1caea432a327d22909..8e5a28829c40115fead32c538c486ae6065449a1 100644 (file)
@@ -22,8 +22,8 @@
 
 #include "lua/lua_iface.h"
 
-struct _daq_pkthdr;
+struct _daq_pkt_hdr;
 
-extern const struct Lua::TypeInterface<_daq_pkthdr> DAQHeaderIface;
+extern const struct Lua::TypeInterface<_daq_pkt_hdr> DAQHeaderIface;
 
 #endif
index 434a1734568791bda68e861840ece654afb3b31d..91b2f5c4da217f38f6e30cc2715cb6089d179e5e 100644 (file)
@@ -32,6 +32,9 @@ inline const uint8_t* get_data(RawBuffer& rb)
 inline uint8_t* get_mutable_data(RawBuffer& rb)
 { return const_cast<uint8_t*>(get_data(rb)); }
 
+inline size_t get_data_length(RawBuffer& rb)
+{ return rb.size(); }
+
 extern const struct Lua::TypeInterface<RawBuffer> RawBufferIface;
 
 #endif
index bddf5625dc829aecef14d4fee5c848204c0e5b61..4e25fc1d4a3d88c4119fbe6aa5e7a4260cb6180b 100644 (file)
@@ -36,6 +36,7 @@ class Flow;
 class IpsAction;
 class IpsContext;
 class Obfuscator;
+class SFDAQInstance;
 
 /* packet status flags */
 #define PKT_REBUILT_FRAG     0x00000001  /* is a rebuilt fragment */
@@ -77,7 +78,8 @@ class Obfuscator;
 #define PKT_FILE_EVENT_SET   0x00400000
 #define PKT_IGNORE           0x00800000  /* this packet should be ignored, based on port */
 #define PKT_RETRANSMIT       0x01000000  // packet is a re-transmitted pkt.
-#define PKT_UNUSED_FLAGS     0xfe000000
+#define PKT_RETRY            0x02000000  /* this packet is being re-evaluated from the internal retry queue */
+#define PKT_UNUSED_FLAGS     0xfc000000
 
 #define PKT_TS_OFFLOADED        0x01
 
@@ -130,16 +132,21 @@ struct SO_PUBLIC Packet
     // FIXIT-M Consider moving ip_proto_next below `pkth`.
     IpProtocol ip_proto_next;      /* the protocol ID after IP and all IP6 extension */
     bool disable_inspect;
-    // nothing after this point is zeroed ...
+    // nothing after this point is zeroed by reset() ...
 
-    // Everything beyond this point is set by PacketManager::decode()
-    IpsContext* context;   // set by control
+    IpsContext* context;
     Active* active;
     Active* active_inst;
     IpsAction** action;
     IpsAction* action_inst;
-    const DAQ_PktHdr_t* pkth;    // packet meta data
-    const uint8_t* pkt;          // raw packet data
+
+    DAQ_Msg_h daq_msg;              // DAQ message this packet came from
+    SFDAQInstance* daq_instance;    // DAQ instance the message came from
+
+    // Everything beyond this point is set by PacketManager::decode()
+    const DAQ_PktHdr_t* pkth;   // packet meta data
+    const uint8_t* pkt;         // raw packet data
+    uint32_t pktlen;            // raw packet data length
 
     // These are both set before PacketManager::decode() returns
     const uint8_t* data;        /* packet payload pointer */
@@ -272,6 +279,9 @@ struct SO_PUBLIC Packet
     bool is_rebuilt() const
     { return (packet_flags & (PKT_REBUILT_STREAM|PKT_REBUILT_FRAG)) != 0; }
 
+    bool is_retry() const
+    { return (packet_flags & PKT_RETRY) != 0; }
+
     bool is_offloaded() const
     { return (ts_packet_flags & PKT_TS_OFFLOADED) != 0; }
 
index e424245f1fae1208612a43a4a13dea7e95aa28b1..adb54552615284738993b23cfb07952c6dc9e6d1 100644 (file)
@@ -123,18 +123,11 @@ static_assert(CODEC_ENCAP_LAYER == (CODEC_UNSURE_ENCAP | CODEC_SAVE_LAYER),
     "If this is an encapsulated layer, you must also set UNSURE_ENCAP"
     " and SAVE_LAYER");
 
-RawData::RawData(const DAQ_PktHdr_t* h, const uint8_t* p)
-{
-    pkth = h;
-    data = p;
-    len = h->caplen;
-}
-
 //-------------------------------------------------------------------------
 // Encode/Decode functions
 //-------------------------------------------------------------------------
 void PacketManager::decode(
-    Packet* p, const DAQ_PktHdr_t* pkthdr, const uint8_t* pkt, bool cooked)
+    Packet* p, const DAQ_PktHdr_t* pkthdr, const uint8_t* pkt, uint32_t pktlen, bool cooked, bool retry)
 {
     Profile profile(decodePerfStats);
 
@@ -143,7 +136,7 @@ void PacketManager::decode(
     ProtocolIndex mapped_prot = CodecManager::grinder;
     ProtocolId prev_prot_id = CodecManager::grinder_id;
 
-    RawData raw(pkthdr, pkt);
+    RawData raw(p->daq_msg, pkthdr, pkt, pktlen);
     CodecData codec_data(ProtocolId::FINISHED_DECODE);
 
     if ( cooked )
@@ -153,6 +146,9 @@ void PacketManager::decode(
     p->reset();
     p->pkth = pkthdr;
     p->pkt = pkt;
+    p->pktlen = pktlen;
+    if (retry)
+        p->packet_flags |= PKT_RETRY;
     layer::set_packet_pointer(p);
 
     s_stats[total_processed]++;
@@ -668,7 +664,7 @@ int PacketManager::format_tcp(
 
     // setup pkt capture header
     DAQ_PktHdr_t* pkth = const_cast<DAQ_PktHdr_t*>(c->pkth);
-    pkth->caplen = 0;
+    c->pktlen = 0;
     pkth->pktlen = 0;
     pkth->ts = p->pkth->ts;
 
@@ -774,7 +770,7 @@ int PacketManager::encode_format(
 
     // setup pkt capture header
     DAQ_PktHdr_t* pkth = const_cast<DAQ_PktHdr_t*>(c->pkth);
-    pkth->caplen = len;
+    c->pktlen = len;
     pkth->pktlen = len;
     pkth->ts = p->pkth->ts;
 
@@ -842,7 +838,7 @@ void PacketManager::encode_update(Packet* p)
     if ( !(p->packet_flags & PKT_MODIFIED) || (p->packet_flags & PKT_RESIZED) )
     {
         DAQ_PktHdr_t* pkth = const_cast<DAQ_PktHdr_t*>(p->pkth);
-        pkth->caplen = len;
+        p->pktlen = len;
         pkth->pktlen = len;
     }
 }
index 2e5a363aedfd751e670d40e2eede5544ec4f395d..21450d8ab1f243466801f3510873d1805402401a 100644 (file)
@@ -61,7 +61,8 @@ public:
     static void thread_term();
 
     // decode this packet and set all relevant packet fields.
-    static void decode(Packet*, const struct _daq_pkthdr*, const uint8_t*, bool cooked = false);
+    static void decode(Packet*, const struct _daq_pkt_hdr*, const uint8_t* pkt,
+        uint32_t pktlen, bool cooked = false, bool retry = false);
 
     // update the packet's checksums and length variables. Call this function
     // after Snort has changed any data in this packet
index 1bb713bfb74a95707c540f5a6acb20533543a7cc..4251fa9e7947d0a6181ef7e298aff5263d29c1a0 100644 (file)
@@ -1431,7 +1431,7 @@ void DCE2_SmbInitDeletePdu()
 
 static void DCE2_SmbInjectDeletePdu(DCE2_SmbFileTracker* ftracker)
 {
-    Packet* inject_pkt = snort::Snort::get_packet();
+    Packet* inject_pkt = DetectionEngine::get_current_wire_packet();
     Packet* p = DetectionEngine::get_current_packet();
 
     if ( inject_pkt->flow != p->flow )
index d76e19b66f49fea671b4d810ba3e8026e88aeb01..c096feb7c7b9febdc902497f3d24338996d7838c 100644 (file)
@@ -85,7 +85,7 @@ int FileSession::process(Packet* p)
     if (file_flows &&
         file_flows->file_process(p, p->data, p->dsize, position(p), c->upload))
     {
-        const char* file_name = SFDAQ::get_interface_spec();
+        const char* file_name = SFDAQ::get_input_spec();
         if (file_name)
             file_flows->set_file_name((const uint8_t*)file_name, strlen(file_name));
     }
index 1a133efc83a9d6f555b13a05b0e7ca1fe7106f0d..bda68f334bca7faa28d2770c0dd7c5b271a6eabd 100644 (file)
 #include "detection/detect.h"
 #include "detection/detection_engine.h"
 #include "log/messages.h"
-#include "main/snort.h"
+#include "main/analyzer.h"
 #include "main/snort_config.h"
 #include "memory/memory_cap.h"
 #include "packet_io/active.h"
-#include "packet_io/sfdaq.h"
+#include "packet_io/sfdaq_config.h"
 #include "profiler/profiler_defs.h"
 #include "protocols/ipv4_options.h"
 #include "time/timersub.h"
@@ -739,7 +739,7 @@ static void FragRebuild(FragTracker* ft, Packet* p)
         "Processing rebuilt packet:\n");
 
     ip_stats.reassembles++;
-    ip_stats.reassembled_bytes += dpkt->pkth->caplen;
+    ip_stats.reassembled_bytes += dpkt->pktlen;
 
 #if defined(DEBUG_FRAG_EX) && defined(DEBUG_MSGS)
     /*
@@ -752,7 +752,7 @@ static void FragRebuild(FragTracker* ft, Packet* p)
 
     DetectionEngine de;
     de.set_encode_packet(p);
-    snort::Snort::process_packet(dpkt, dpkt->pkth, dpkt->pkt, true);
+    Analyzer::get_local_analyzer()->process_rebuilt_packet(dpkt, dpkt->pkth, dpkt->pkt, dpkt->pktlen);
     de.set_encode_packet(nullptr);
 
     trace_log(stream_ip, "Done with rebuilt packet, marking rebuilt...\n");
@@ -946,7 +946,7 @@ void Defrag::process(Packet* p, FragTracker* ft)
     }
 
     ip_stats.total++;
-    ip_stats.fragmented_bytes += p->pkth->caplen + 4; /* 4 for the CRC */
+    ip_stats.fragmented_bytes += p->pktlen + 4; /* 4 for the CRC */
 
     DeepProfile profile(fragPerfStats);
 
@@ -1439,7 +1439,7 @@ left_overlap_last:
         }
     }
 
-    if ((uint16_t)fragLength > SFDAQ::get_snap_len())
+    if ((uint16_t)fragLength > SnortConfig::get_conf()->daq_config->get_mru_size())
     {
         trace_logf(stream_ip,
             "Overly large fragment %d 0x%x 0x%x %d\n",
@@ -1814,7 +1814,7 @@ int Defrag::new_tracker(Packet* p, FragTracker* ft)
     fragStart = p->data;
 
     /* Just to double check */
-    if (!fragLength or fragLength > SFDAQ::get_snap_len())
+    if (!fragLength or fragLength > SnortConfig::get_conf()->daq_config->get_mru_size())
     {
         trace_logf(stream_ip,
             "Bad fragment length:%d(0x%x) off:0x%x(%d)\n",
index de9e80998970c26ff397afc80105708545dd7362..ba410a289bb191c65534aae3ba568e8999874fb0 100644 (file)
@@ -38,13 +38,13 @@ static void set_retransmit_flag(snort::Packet* p)
     if ( snort::PacketTracer::is_active() )
     {
         snort::PacketTracer::log("Packet was retransmitted and %s from the retry queue.\n",
-        (p->pkth->flags & DAQ_PKT_FLAG_RETRY_PACKET) ? "is" : "is not");
+            p->is_retry() ? "is" : "is not");
     }
 
     // Mark the packet as being a re-transmit if it's not from the retry
     // queue. That way we can avoid adding re-transmitted packets to
     // the retry queue.
-    if ( !(p->pkth->flags & DAQ_PKT_FLAG_RETRY_PACKET) )
+    if ( !p->is_retry() )
         p->packet_flags |= PKT_RETRANSMIT;
 }
 
index 16bff360e39955c57b0dda10271fda6e7c21df1e..ade9912e7221aad5998e91c9513a02c2f7289a1f 100644 (file)
@@ -267,7 +267,7 @@ int TcpNormalizer::validate_paws_timestamp(
 {
     if ( ( (int)( ( tsd.get_ts() - tns.peer_tracker->get_ts_last() ) + tns.paws_ts_fudge ) ) < 0 )
     {
-        if ( tsd.get_pkt()->pkth->flags & DAQ_PKT_FLAG_RETRY_PACKET )
+        if ( tsd.get_pkt()->is_retry() )
         {
             //  Retry packets can legitimately have old timestamps
             //  in TCP options (if a re-transmit comes in before
index f97fde5e9627dce494e06e47d937e8ba04370dc1..b59dc062429a60e996565b6ff2b1d342da0c0fe3 100644 (file)
@@ -27,7 +27,7 @@
 
 #include "detection/detection_engine.h"
 #include "log/log.h"
-#include "main/snort.h"
+#include "main/analyzer.h"
 #include "memory/memory_cap.h"
 #include "profiler/profiler.h"
 #include "protocols/packet_manager.h"
@@ -584,7 +584,7 @@ int TcpReassembler::_flush_to_seq(
 
             NoProfile exclude(s5TcpFlushPerfStats);
 
-            if ( !Snort::inspect(pdu) )
+            if ( !Analyzer::get_local_analyzer()->inspect_rebuilt(pdu) )
                 last_pdu = pdu;
             else
                 last_pdu = nullptr;
@@ -670,7 +670,7 @@ int TcpReassembler::do_zero_byte_flush(TcpReassemblerState& trs, Packet* p, uint
 
         show_rebuilt_packet(trs, pdu);
         NoProfile profile_exclude(s5TcpFlushPerfStats);
-        Snort::inspect(pdu);
+        Analyzer::get_local_analyzer()->inspect_rebuilt(pdu);
 
         if ( trs.tracker->splitter )
             trs.tracker->splitter->update();
@@ -822,6 +822,7 @@ static Packet* set_packet(Flow* flow, uint32_t flags, bool c2s)
     memset(ph, 0, sizeof(*ph));
     packet_gettimeofday(&ph->ts);
 
+    p->pktlen = 0;
     p->data = nullptr;
     p->dsize = 0;
 
index e510791afe85ee33704fd014c7cc4f4dd86c0af3..82da5a5b08c14178540f7173b1cc8188256f2012 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "detection/detection_engine.h"
 #include "detection/rules.h"
-#include "main/snort.h"
+#include "main/analyzer.h"
 #include "memory/memory_cap.h"
 #include "profiler/profiler_defs.h"
 #include "protocols/packet.h"
@@ -166,7 +166,7 @@ void UserTracker::detect(
     up->packet_flags |= (p->packet_flags & (PKT_STREAM_EST|PKT_STREAM_UNEST_UNI));
 
     trace_logf(stream_user, "detect[%d]\n", up->dsize);
-    snort::Snort::inspect(up);
+    Analyzer::get_local_analyzer()->inspect_rebuilt(up);
 }
 
 int UserTracker::scan(Packet* p, uint32_t& flags)
index 512d15bac0c1a8d3da50c3680e12320541af658b..b6607d4182477a670014c9c3daaf33ec3f0e77d0 100644 (file)
@@ -64,10 +64,13 @@ int64_t timersub_ms(const struct timeval* end, const struct timeval* start)
 
 void packet_time_update(const struct timeval* cur_tv)
 {
-    if ( !s_first_packet )
-        s_first_packet = cur_tv->tv_sec;
+    if (timercmp(cur_tv, &s_recent_packet, >))
+    {
+        if ( !s_first_packet )
+            s_first_packet = cur_tv->tv_sec;
 
-    s_recent_packet = *cur_tv;
+        s_recent_packet = *cur_tv;
+    }
 }
 
 uint32_t packet_first_time()
index e55f35ba050af45caad98a1b2e5fc2bd23c7ba7f..24a66f5402d240cbeb64399b1b4d0f21e817ed5d 100644 (file)
@@ -76,6 +76,7 @@ struct AuxCount
     PegCount internal_whitelist;
     PegCount idle;
     PegCount rx_bytes;
+    PegCount skipped;
 };
 
 extern ProcessCount proc_stats;
index 1fe44e799a36e2d14e4bef9eb2f9269fba612b92..316533c2eacfedc411b3f088b83f4e0f6e922971 100644 (file)
@@ -285,7 +285,7 @@ void CreatePidFile(pid_t pid)
     else
     {
         const char* error = get_error(errno);
-        ErrorMessage("Failed to create pid file %s, Error: %s",
+        ErrorMessage("Failed to create pid file %s, Error: %s\n",
             SnortConfig::get_conf()->pid_filename.c_str(), error);
         SnortConfig::get_conf()->pid_filename.clear();
     }
@@ -335,13 +335,6 @@ bool SetUidGid(int user_id, int group_id)
     if (group_id == -1 && user_id == -1)
         return true;
 
-    // FIXIT-L Move this check to Snort::drop_privileges()
-    if (!SFDAQ::unprivileged())
-    {
-        ParseError("Cannot drop privileges - %s DAQ does not support unprivileged operation.\n", SFDAQ::get_type());
-        return false;
-    }
-
     if (group_id != -1)
     {
         if (setgid(group_id) < 0)
index 6fa05ccdef047b8e254aa1979a50ed2971194123..be046f46805dcf1c3498df5f7bae97ef67a1e1cd 100644 (file)
@@ -4,6 +4,9 @@ add_library( config_states OBJECT
     config_binding.cc
     config_checksums.cc
     config_classification.cc
+    config_daq.cc
+    config_daq_mode.cc
+    config_daq_var.cc
     config_decode_esp.cc
     config_default_rule_state.cc
     config_deleted.cc
diff --git a/tools/snort2lua/config_states/config_daq.cc b/tools/snort2lua/config_states/config_daq.cc
new file mode 100644 (file)
index 0000000..eef361f
--- /dev/null
@@ -0,0 +1,76 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2018-2018 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// 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 along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+// config_daq.cc author Carter Waxman <cwaxman@cisco.com>
+
+#include <sstream>
+#include <vector>
+
+#include "conversion_state.h"
+#include "helpers/converter.h"
+#include "helpers/s2l_util.h"
+
+namespace config
+{
+namespace
+{
+class Daq : public ConversionState
+{
+public:
+    Daq(Converter& c) : ConversionState(c) { }
+
+    bool convert(std::istringstream& data_stream) override;
+};
+} // namespace
+
+bool Daq::convert(std::istringstream& data_stream)
+{
+    bool retval = true;
+    std::string name;
+
+    if ( data_stream >> name )
+    {
+        table_api.open_top_level_table("daq");
+        table_api.open_table("modules");
+        table_api.open_table("");
+        table_api.add_option("name", name);
+        table_api.add_diff_option_comment("config daq:", "name");
+        table_api.close_table();
+        table_api.close_table();
+        table_api.close_table();
+    }
+
+    return retval;
+}
+
+/**************************
+ *******  A P I ***********
+ **************************/
+
+static ConversionState* ctor(Converter& c)
+{ return new Daq(c); }
+
+static const ConvertMap daq_api =
+{
+    "daq",
+    ctor,
+};
+
+const ConvertMap* daq_map = &daq_api;
+
+} // namespace config
+
diff --git a/tools/snort2lua/config_states/config_daq_mode.cc b/tools/snort2lua/config_states/config_daq_mode.cc
new file mode 100644 (file)
index 0000000..a674da4
--- /dev/null
@@ -0,0 +1,83 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2018-2018 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// 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 along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+// config_daq_mode.cc author Carter Waxman <cwaxman@cisco.com>
+
+#include <sstream>
+#include <vector>
+
+#include "conversion_state.h"
+#include "helpers/converter.h"
+#include "helpers/s2l_util.h"
+
+namespace config
+{
+namespace
+{
+class DaqMode : public ConversionState
+{
+public:
+    DaqMode(Converter& c) : ConversionState(c) { }
+    bool convert(std::istringstream& data_stream) override;
+};
+} // namespace
+
+bool DaqMode::convert(std::istringstream& data_stream)
+{
+    bool retval = true;
+    std::string mode;
+
+    if ( data_stream >> mode )
+    {
+        if ( mode == "read-file" or mode == "passive" or mode == "inline" )
+        {
+            table_api.open_top_level_table("daq");
+            table_api.open_table("modules");
+            table_api.open_table("");
+            table_api.add_option("mode", mode);
+            table_api.add_diff_option_comment("config daq_mode:", "mode");
+            table_api.close_table();
+            table_api.close_table();
+            table_api.close_table();
+        }
+        else
+        {
+            retval = false;
+            data_api.failed_conversion(data_stream, mode);
+        }
+    }
+
+    return retval;
+}
+
+/**************************
+ *******  A P I ***********
+ **************************/
+
+static ConversionState* ctor(Converter& c)
+{ return new DaqMode(c); }
+
+static const ConvertMap daq_mode_api =
+{
+    "daq_mode",
+    ctor,
+};
+
+const ConvertMap* daq_mode_map = &daq_mode_api;
+
+} // namespace config
+
diff --git a/tools/snort2lua/config_states/config_daq_var.cc b/tools/snort2lua/config_states/config_daq_var.cc
new file mode 100644 (file)
index 0000000..8d2f6cd
--- /dev/null
@@ -0,0 +1,80 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2018-2018 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// 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 along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+// config_daq_var.cc author Carter Waxman <cwaxman@cisco.com>
+
+#include <sstream>
+
+#include "conversion_state.h"
+#include "helpers/converter.h"
+#include "helpers/s2l_util.h"
+
+namespace config
+{
+namespace
+{
+class DaqVar : public ConversionState
+{
+public:
+    DaqVar(Converter& c) : ConversionState(c) { }
+
+    bool convert(std::istringstream& data_stream) override;
+};
+} // namespace
+
+bool DaqVar::convert(std::istringstream& data_stream)
+{
+    bool retval = true;
+    std::string tmp, var;
+
+    while ( data_stream >> tmp )
+        var += tmp;
+
+    if ( !var.empty() )
+    {
+        table_api.open_top_level_table("daq");
+        table_api.open_table("modules");
+        table_api.open_table("");
+        table_api.open_table("variables");
+        table_api.add_option(var);
+        table_api.close_table();
+        table_api.add_diff_option_comment("config daq_var:", "variables");
+        table_api.close_table();
+        table_api.close_table();
+        table_api.close_table();
+    }
+
+    return retval;
+}
+
+/**************************
+ *******  A P I ***********
+ **************************/
+
+static ConversionState* ctor(Converter& c)
+{ return new DaqVar(c); }
+
+static const ConvertMap daq_var_api =
+{
+    "daq_var",
+    ctor,
+};
+
+const ConvertMap* daq_var_map = &daq_var_api;
+
+} // namespace config
+
index 974adc65deb518e07af48a0cdc69998afcf945ec..b6b465651a69f597e5b44fa163ff708020d20a0d 100644 (file)
@@ -532,19 +532,6 @@ static const ConvertMap disable_inline_init_failopen_api =
 
 const ConvertMap* disable_inline_init_failopen_map = &disable_inline_init_failopen_api;
 
-/*************************************************
- *****************  daq_mode  *******************
- *************************************************/
-
-static const std::string daq_mode = "daq_mode";
-static const ConvertMap daq_mode_api =
-{
-    daq_mode,
-    deleted_ctor<& daq_mode>,
-};
-
-const ConvertMap* daq_mode_map = &daq_mode_api;
-
 /*************************************************
  *************  decode_data_link  ****************
  *************************************************/
@@ -586,4 +573,17 @@ static const ConvertMap sidechannel_api =
 
 const ConvertMap* sidechannel_map = &sidechannel_api;
 
+/*************************************************
+ *****************  no_promisc *******************
+ *************************************************/
+
+static const std::string no_promisc = "no_promisc";
+static const ConvertMap no_promisc_api =
+{
+    no_promisc,
+    deleted_ctor<& no_promisc>,
+};
+
+const ConvertMap* no_promisc_map = &no_promisc_api;
+
 } // namespace config
index c15f7bc9722ebe860ee43280af26d95971823976..5722ffecdf3fa0fecc9616e9cbc73982e232d143 100644 (file)
@@ -302,19 +302,6 @@ static const ConvertMap nopcre_api =
 
 const ConvertMap* nopcre_map = &nopcre_api;
 
-/*************************************************
- ******************  no_promisc  *****************
- *************************************************/
-
-static const std::string no_promisc = "no_promisc";
-static const ConvertMap no_promisc_api =
-{
-    no_promisc,
-    config_true_no_opt_ctor<& no_promisc, & daq>
-};
-
-const ConvertMap* no_promisc_map = &no_promisc_api;
-
 /*************************************************
  ******************  obfuscate  ******************
  *************************************************/
index c4d0ce98adecb08dd1340dc9c8383995c194dedb..8f5c4c1bcb23921d1eef7fb5a75dee3bc17af3dd 100644 (file)
@@ -119,7 +119,6 @@ static ConversionState* config_string_ctor(Converter& c)
  *************************************************/
 
 static const std::string alerts = "alerts";
-static const std::string daq = "daq";
 static const std::string mode = "mode";
 static const std::string packets = "packets";
 static const std::string process = "process";
@@ -152,23 +151,11 @@ static const ConvertMap chroot_api =
 
 const ConvertMap* chroot_map = &chroot_api;
 
-/*************************************************
- *********************  daq  *********************
- *************************************************/
-
-static const std::string module = "module";
-static const ConvertMap daq_api =
-{
-    daq,
-    config_string_ctor<& daq, & daq, & module>,
-};
-
-const ConvertMap* daq_map = &daq_api;
-
 /*************************************************
  *******************  daq_dir  *******************
  *************************************************/
 
+static const std::string daq = "daq";
 static const std::string daq_dir = "daq_dir";
 static const std::string module_dirs = "module_dirs";
 static const ConvertMap daq_dir_api =
@@ -179,20 +166,6 @@ static const ConvertMap daq_dir_api =
 
 const ConvertMap* daq_dir_map = &daq_dir_api;
 
-/*************************************************
- *******************  daq_var  *******************
- *************************************************/
-
-static const std::string daq_var = "daq_var";
-static const std::string variables = "variables";
-static const ConvertMap daq_var_api =
-{
-    daq_var,
-    config_string_ctor<& daq_var, & daq, & variables, true>,
-};
-
-const ConvertMap* daq_var_map = &daq_var_api;
-
 /*************************************************
  *******************  logdir  ********************
  *************************************************/
index bb25e76fb112244208f581cd59207ed1e59bfe86..327cc87a020463da35a95d3746ead55e20065986 100644 (file)
@@ -25,9 +25,6 @@
 
 static inline Table* find_table(std::vector<Table*> vec, const std::string& name)
 {
-    if (name.empty())
-        return nullptr;
-
     for ( auto* t : vec)
         if (name == t->get_name())
             return t;