SUBDIRS += test
endif
-if BUILD_SIDE_CHANNEL
-snort_LDADD += \
-side_channel/libsidechannel.a \
-side_channel/plugins/libsscm.a
-SUBDIRS += side_channel
-endif
-
#include <unistd.h>
#include <pcap.h>
#include <timersub.h>
-#include <pthread.h>
#include <string.h>
#include <grp.h>
#include <pwd.h>
}
-/*
- * Function: SnortFatalExit(void)
- *
- * Purpose: When a fatal error occurs, this function cleanly
- * shuts down the program
- *
- * Arguments: none
- *
- * Returns: void function
- */
-NORETURN void SnortFatalExit(void)
-{
- // -----------------------------
- // bail now if we are reentering
- if ( already_fatal )
- exit(1);
- else
- already_fatal = 1;
-
- if (!snort_conf || (!ScDaemonMode() && !ScLogSyslog()))
- fprintf(stderr,"Fatal Error, Quitting..\n");
-
-#if 0
- // FIXIT need to stop analyzers / workers
- // and they should handle the DAQ break / abort
- if ( SnortIsInitializing() )
- {
- DAQ_Abort();
- exit(1);
- }
- else
-#endif
- {
- DAQ_BreakLoop(1);
- pthread_exit(NULL);
- }
-}
-
/*
* Function: FatalError(const char *, ...)
*
#endif
{
// FIXIT this makes no sense from main thread
- //DAQ_BreakLoop(1);
- // FIXIT pthread_exit() segfaults; use c++11 <thread> instead of pthread_*()
// FIXIT exit() segfaults too; looks like something borked in dylib
exit(EXIT_FAILURE);
}
void ErrorMessageThrottled(ThrottleInfo*,const char*, ...) __attribute__((format (printf, 2, 3)));
+// FIXIT do not call FatalError() during runtime
NORETURN void FatalError(const char*, ...) __attribute__((format (printf, 1, 2)));
-NORETURN void SnortFatalExit(void);
void PrintPacketData(const uint8_t*, const uint32_t);
char* ObfuscateIpToText(sfip_t*);
#include "test/unit_test.h"
#endif
-#ifdef SIDE_CHANNEL
-#include "side_channel/sidechannel.h"
-#endif
-
#include "framework/so_rule.h"
//-------------------------------------------------------------------------
const struct timespec main_sleep = { 0, 100000000 }; // 0.1 sec
-#ifdef SIDE_CHANNEL
-pthread_mutex_t snort_process_lock;
-static bool snort_process_lock_held = false;
-#endif
-
static const char* prompt = "o\")~ ";
//-------------------------------------------------------------------------
// FIXIT return true if something was done to avoid sleeping
static bool house_keeping()
{
-#ifdef SIDE_CHANNEL
- if (ScSideChannelEnabled() && !snort_process_lock_held)
- {
- pthread_mutex_lock(&snort_process_lock);
- snort_process_lock_held = true;
- }
-#endif
-
signal_check();
-#ifdef SIDE_CHANNEL
- SideChannelDrainRX(0);
-#endif
IdleProcessingExecute();
periodic_check();
#include "stream/stream.h"
#include "ips_options/replace.h"
-#ifdef SIDE_CHANNEL
-#include "side_channel/sidechannel.h"
-#endif
-
#ifdef INTEL_SOFT_CPM
#include "search/intel_soft_cpm.h"
#endif
static int snort_exiting = 0;
static pid_t snort_main_thread_pid = 0;
-static pthread_t snort_main_thread_id = 0;
static int snort_argc = 0;
static char** snort_argv = NULL;
#endif
InitProtoNames();
-#ifdef SIDE_CHANNEL
- pthread_mutex_init(&snort_process_lock, NULL);
-#endif
if (snort_cmd_line_conf != NULL) // FIXIT can this be deleted?
{
OrderRuleLists(snort_conf, "activation dynamic drop sdrop reject alert pass log");
}
if ( !InspectorManager::configure(snort_conf) )
- SnortFatalExit();
+ FatalError("can't initialize inspectors\n");
InspectorManager::print_config(snort_conf); // FIXIT make optional
#endif
EventManager::configure_outputs(snort_conf);
-
-#ifdef SIDE_CHANNEL
- RegisterSideChannelModules();
- ConfigureSideChannelModules(snort_conf);
- SideChannelConfigure(snort_conf);
- SideChannelInit();
- SideChannelStartTXThread();
-#endif
}
// this function should only include initialization that must be done as a
/* Drop privileges if requested, when initialization is done */
SetUidGid(ScUid(), ScGid());
-#ifdef SIDE_CHANNEL
- SideChannelPostInit();
-#endif
-
snort_initializing = false;
}
snort_argc = argc;
snort_argv = argv;
- // must be done now in case of fatal error
- // and again after daemonization
- snort_main_thread_id = pthread_self();
OpenLogger();
SnortInit(argc, argv);
// this must follow daemonization
snort_main_thread_pid = gettid();
- snort_main_thread_id = pthread_self();
/* Change groups */
InitGroups(ScUid(), ScGid());
snort_exiting = 1;
snort_initializing = false; /* just in case we cut out early */
-#ifdef SIDE_CHANNEL
- SideChannelStopTXThread();
- SideChannelCleanUp();
-#endif
IdleProcessingCleanUp();
IpsManager::global_term(snort_conf);
/* E X T E R N S ************************************************************/
extern THREAD_LOCAL SnortConfig* snort_conf;
-#ifdef SIDE_CHANNEL
-extern pthread_mutex_t snort_process_lock;
-#endif
-
/* P R O T O T Y P E S ******************************************************/
static inline int ScTestMode(void)
return snort_conf->pcap_log_file;
}
-#ifdef SIDE_CHANNEL
-static inline int ScSideChannelEnabled(void)
-{
- return snort_conf->side_channel_config.enabled;
-}
-#endif
-
// use of macro avoids depending on generators.h
#define EventIsInternal(gid) (gid == GENERATOR_INTERNAL)
#include "utils/strvec.h"
#include "file_api/file_service.h"
#include "target_based/sftarget_reader.h"
-#include "side_channel/sidechannel.h"
#include "parser/parser.h"
#include "parser/config_file.h"
#include "parser/vars.h"
// private implementation
//-------------------------------------------------------------------------
-#ifdef SIDE_CHANNEL
-static void FreeSideChannelModuleConfigs(SideChannelModuleConfig *head)
-{
- while (head != NULL)
- {
- SideChannelModuleConfig *tmp = head;
-
- head = head->next;
-
- if (tmp->keyword != NULL)
- free(tmp->keyword);
-
- if (tmp->opts != NULL)
- free(tmp->opts);
-
- if (tmp->file_name != NULL)
- free(tmp->file_name);
-
- free(tmp);
- }
-}
-#endif
-
static void FreeRuleStateList(RuleState *head)
{
while (head != NULL)
free(sc->profile_preprocs.filename);
#endif
-#ifdef SIDE_CHANNEL
- FreeSideChannelModuleConfigs(sc->side_channel_config.module_configs);
-#endif
-
if (sc->base_version != NULL)
free(sc->base_version);
free_file_config(sc->file_config);
-#ifdef SIDE_CHANNEL
- if (sc->side_channel_config.opts)
- free(sc->side_channel_config.opts);
-#endif
-
if ( sc->var_list )
FreeVarList(sc->var_list);
return -1;
}
-#ifdef SIDE_CHANNEL
- if (SideChannelVerifyConfig(sc) != 0)
- {
- ErrorMessage("Snort Reload: Changing the side channel configuration requires a restart.\n");
- return -1;
- }
-#endif
-
return 0;
}
} PathType;
-#ifdef SIDE_CHANNEL
-typedef struct _SideChannelModuleConfig
-{
- char *keyword;
- char *opts;
- char *file_name;
- int file_line;
- struct _SideChannelModuleConfig *next;
-} SideChannelModuleConfig;
-
-typedef struct _SideChannelConfig
-{
- bool enabled;
- char *opts;
- SideChannelModuleConfig *module_configs;
-} SideChannelConfig;
-#endif
-
// SnortState members are updated during runtime
// an array in SnortConfig is used instead of thread_locals because these
// must get changed on reload
//------------------------------------------------------
// FIXIT non-module stuff - separate config from derived state?
-#ifdef SIDE_CHANNEL
- DynamicLibInfo *dyn_side_channels; // FIXIT needs redoing
-#endif
-
char pid_filename[STD_BUF]; /* used with pid_path */ // FIXIT delete these
char pidfile_suffix[MAX_PIDFILE_SUFFIX + 1]; /* -R */
char *output_dir;
struct VarNode* var_list;
-#ifdef SIDE_CHANNEL
- SideChannelConfig side_channel_config;
-#endif
int max_threads;
unsigned remote_control;
#include "file_api/file_service_config.h"
#include "packet_io/sfdaq.h"
-#ifdef SIDE_CHANNEL
-# include "side_channel/sidechannel.h"
-#endif
-
#include "target_based/sftarget_reader.h"
// FIXIT defines should be avoided here - the actual option
#define SNORT_CONF_KEYWORD__FILE "file"
#define SNORT_CONF_KEYWORD__INCLUDE "include"
-/* Rest of the keywords */
-// FIXIT config_* keywords were config * but moved here temporarily
-// until they are properly modularized
-#ifdef SIDE_CHANNEL
-#define SNORT_CONF_KEYWORD__CFG_SIDE_CHANNEL "config_sidechannel"
-#define SNORT_CONF_KEYWORD__SIDE_CHANNEL "sidechannel"
-#endif
-
/* Macros *********************************************************************/
#define ENABLE_ALL_RULES 1
#define ENABLE_RULE 1
#include "keywords.h"
#include "vars.h"
-#ifdef SIDE_CHANNEL
-# include "side_channel/sidechannel.h"
-#endif
-
struct Location
{
string file;
}
}
-#ifdef SIDE_CHANNEL
-static void ConfigSideChannel(SnortConfig *sc, const char *args)
-{
- if (sc == NULL)
- return;
- sc->side_channel_config.enabled = true;
- if (args != NULL)
- sc->side_channel_config.opts = SnortStrdup(args);
-}
-
-static void ParseSideChannelModule(SnortConfig *sc, const char *args)
-{
- char **toks;
- int num_toks;
- char *opts = NULL;
- SideChannelModuleConfig *config;
-
- toks = mSplit(args, ":", 2, &num_toks, '\\');
-
- if (num_toks > 1)
- opts = toks[1];
-
- config = (SideChannelModuleConfig *) SnortAlloc(sizeof(SideChannelModuleConfig));
-
- if (sc->side_channel_config.module_configs == NULL)
- {
- sc->side_channel_config.module_configs = config;
- }
- else
- {
- SideChannelModuleConfig *tmp = sc->side_channel_config.module_configs;
-
- while (tmp->next != NULL)
- tmp = tmp->next;
-
- tmp->next = config;
- }
-
- config->keyword = SnortStrdup(toks[0]);
- if (opts != NULL)
- config->opts = SnortStrdup(opts);
-
- /* This could come from parsing the command line (No, actually, I don't think that it could...) */
- const char* fname;
- unsigned fline;
- get_parse_location(fname, fline);
-
- if ( fname )
- {
- config->file_name = SnortStrdup(fname);
- config->file_line = fline;
- }
-
- mSplitFree(&toks, num_toks);
-}
-#endif /* SIDE_CHANNEL */
-
static void ParseFile(SnortConfig *sc, const char *args)
{
parse_file_rule(args, &(sc->file_config));
{ SNORT_CONF_KEYWORD__RULE_TYPE, KEYWORD_TYPE__ALL, 1, 0, ParseRuleTypeDeclaration },
#endif
- // this stuff needs to be rewritten as a proper plugin
-#ifdef SIDE_CHANNEL
- { SNORT_CONF_KEYWORD__CFG_SIDE_CHANNEL, KEYWORD_TYPE__MAIN, 1, 1, ConfigSideChannel },
- { SNORT_CONF_KEYWORD__SIDE_CHANNEL, KEYWORD_TYPE__MAIN, 1, 1, ParseSideChannelModule },
-#endif
-
{ NULL, KEYWORD_TYPE__ALL, 0, 0, NULL } /* Marks end of array */
};
#include "keywords.h"
#include "vars.h"
#include "managers/ips_manager.h"
-
-#ifdef SIDE_CHANNEL
-# include "side_channel/sidechannel.h"
-#endif
-
#include "target_based/sftarget_reader.h"
typedef void (*ParseRuleOptFunc)(SnortConfig *, RuleTreeNode *, OptTreeNode *, const char *);
#include "managers/ips_manager.h"
#include "config_file.h"
#include "keywords.h"
-
-#ifdef SIDE_CHANNEL
-# include "side_channel/sidechannel.h"
-#endif
-
#include "target_based/sftarget_reader.h"
#define SRC 0
#include "parse_conf.h"
#include "parse_rule.h"
#include "vars.h"
-
-#ifdef SIDE_CHANNEL
-# include "side_channel/sidechannel.h"
-#endif
-
#include "target_based/sftarget_reader.h"
rule_index_map_t *ruleIndexMap = NULL; /* rule index -> sid:gid map */
return sc;
}
-#ifdef SIDE_CHANNEL
-void ConfigureSideChannelModules(SnortConfig *sc)
-{
- SideChannelModuleConfig *config;
- int rval;
-
- for (config = sc->side_channel_config.module_configs; config != NULL; config = config->next)
- {
- push_parse_location(config->file_name, config->file_line);
-
- rval = ConfigureSideChannelModule(config->keyword, config->opts);
- if (rval == -ENOENT)
- ParseError("Unknown side channel plugin: '%s'", config->keyword);
-
- pop_parse_location();
- }
-}
-
-#endif /* SIDE_CHANNEL */
-
void FreeRuleTreeNode(RuleTreeNode *rtn)
{
RuleFpList *idx, *tmp;
#include "framework/ips_option.h"
#include "config_file.h"
#include "keywords.h"
-
-#ifdef SIDE_CHANNEL
-# include "side_channel/sidechannel.h"
-#endif
-
#include "target_based/sftarget_reader.h"
//-------------------------------------------------------------------------
+++ /dev/null
-
-add_subdirectory(plugins)
-
-add_library ( sidechannel STATIC
- dmq.cc
- dmq.h
- rbmq.cc
- rbmq.h
- sidechannel.cc
- sidechannel.h
- sidechannel_define.h
-)
-
+++ /dev/null
-AUTOMAKE_OPTIONS=foreign no-dependencies
-
-noinst_LIBRARIES = libsidechannel.a
-
-SUBDIRS = \
-plugins
-
-libsidechannel_a_SOURCES = \
-dmq.cc dmq.h \
-rbmq.cc rbmq.h \
-sidechannel.cc sidechannel.h \
-sidechannel_define.h
-
-AM_CXXFLAGS = @AM_CXXFLAGS@
-
+++ /dev/null
-/*
- * 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.
- *
-** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
- * Copyright (C) 2012-2013 Sourcefire, Inc.
- *
- * Author: Michael Altizer <maltizer@sourcefire.com>
- *
- */
-
-#include "dmq.h"
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef SIDE_CHANNEL
-#include <errno.h>
-#include "util.h"
-
-#ifdef SC_USE_DMQ
-#define DMQ_NODE_FLAG_EXTERNAL 0x01
-
-typedef struct _dmq_node
-{
- struct _dmq_node *next;
- uint32_t length;
- uint32_t allocated;
- uint8_t flags;
- uint8_t *data;
- SCMQMsgFreeFunc msgFreeFunc;
-} DMQ_Node;
-
-typedef struct _dmq
-{
- DMQ_Node *head;
- DMQ_Node *tail;
- DMQ_Node *free_list;
- uint16_t user_header_size;
- uint32_t length;
- uint32_t internal_size;
- uint32_t external_size;
- uint32_t overhead_size;
- uint32_t length_limit;
- uint32_t internal_size_limit;
- uint32_t max_length;
- uint32_t max_internal_size;
-} DMQ;
-
-DMQ *DMQ_Alloc(uint32_t msg_ring_entries, uint16_t msg_ring_header_size, uint32_t data_ring_size)
-{
- DMQ_Node *node;
- DMQ *mq;
- uint32_t i;
-
- mq = (DMQ*)SnortAlloc(sizeof(DMQ));
-
- mq->head = mq->tail = mq->free_list = NULL;
-
- mq->user_header_size = msg_ring_header_size;
-
- mq->length = 0;
- mq->internal_size = 0;
- mq->external_size = 0;
- mq->overhead_size = 0;
-
- mq->length_limit = msg_ring_entries;
- mq->internal_size_limit = data_ring_size;
-
- /* Preallocate the Queue nodes. */
- for (i = 0; i < mq->length_limit; i++)
- {
- node = (DMQ_Node*)SnortAlloc(sizeof(DMQ_Node) + mq->user_header_size);
- node->next = mq->free_list;
- mq->free_list = node;
- mq->overhead_size += sizeof(DMQ_Node) + mq->user_header_size;
- }
-
- LogMessage("%s: Preallocated %u bytes for queue node structures.\n", __FUNCTION__, mq->overhead_size);
-
- return mq;
-}
-
-int DMQ_ReserveMsg(DMQ *mq, uint32_t length, void **hdr_ptr, uint8_t **msg_ptr, void **msg_handle)
-{
- DMQ_Node *node;
-
- if (!mq->free_list)
- return -ENOSPC;
-
- if (length > (mq->internal_size_limit - mq->internal_size))
- return -ENOMEM;
-
- node = mq->free_list;
- mq->free_list = node->next;
-
- node->next = NULL;
- node->length = length;
- node->allocated = length;
- node->flags = 0;
- node->data = (uint8_t*)SnortAlloc(length);
- node->msgFreeFunc = NULL;
-
- *hdr_ptr = (uint8_t *) node + sizeof(DMQ_Node);
- *msg_ptr = node->data;
- *msg_handle = (void *) node;
-
- mq->internal_size += length;
- if (mq->internal_size > mq->max_internal_size)
- mq->max_internal_size = mq->internal_size;
-
- return 0;
-}
-
-int DMQ_CommitReservedMsg(DMQ *mq, void *msg_handle, uint32_t length, SCMQMsgFreeFunc msgFreeFunc)
-{
- DMQ_Node *node = (DMQ_Node *) msg_handle;
-
- if (!node)
- return -EINVAL;
-
- if (length > node->length)
- {
- ErrorMessage("%s: Attempted to commit illegally enlarged message! (%u vs %u)\n", __FUNCTION__, length, node->length);
- return -EINVAL;
- }
-
- node->length = length;
-
- if (mq->head)
- {
- mq->tail->next = node;
- mq->tail = node;
- }
- else
- mq->head = mq->tail = node;
-
- mq->length++;
- if (mq->length > mq->max_length)
- mq->max_length = mq->length;
-
- return 0;
-}
-
-static void DMQ_DestroyNode(DMQ *mq, DMQ_Node *node)
-{
- if (node->msgFreeFunc)
- node->msgFreeFunc(node->data);
-
- if (!(node->flags & DMQ_NODE_FLAG_EXTERNAL))
- {
- mq->internal_size -= node->allocated;
- free(node->data);
- }
- else
- mq->external_size -= node->length;
-
- node->next = mq->free_list;
- mq->free_list = node;
-}
-
-int DMQ_DiscardReservedMsg(DMQ *mq, void *msg_handle)
-{
- DMQ_Node *node = (DMQ_Node *) msg_handle;
-
- if (!node)
- return -EINVAL;
-
- DMQ_DestroyNode(mq, node);
-
- return 0;
-}
-
-int DMQ_CommitExternalMsg(DMQ *mq, const void *hdr, uint8_t *msg, uint32_t length, SCMQMsgFreeFunc msgFreeFunc)
-{
- DMQ_Node *node;
-
- if (!mq->free_list)
- return -ENOMEM;
-
- node = mq->free_list;
- mq->free_list = node->next;
-
- if (mq->user_header_size)
- {
- if (!hdr)
- return -EINVAL;
- memcpy((uint8_t *) node + sizeof(DMQ_Node), hdr, mq->user_header_size);
- }
-
- node->next = NULL;
- node->length = length;
- node->allocated = 0;
- node->flags = DMQ_NODE_FLAG_EXTERNAL;
- node->data = msg;
- node->msgFreeFunc = msgFreeFunc;
-
- if (mq->head)
- {
- mq->tail->next = node;
- mq->tail = node;
- }
- else
- mq->head = mq->tail = node;
-
- mq->length++;
- if (mq->length > mq->max_length)
- mq->max_length = mq->length;
-
- mq->external_size += length;
-
- return 0;
-}
-
-int DMQ_ReadMsg(DMQ *mq, const void **hdr_ptr, const uint8_t **msg_ptr, uint32_t *length, void **msg_handle)
-{
- DMQ_Node *node;
-
- if (!mq->head)
- return -ENOENT;
-
- node = mq->head;
- mq->head = node->next;
- if (!mq->head)
- mq->tail = NULL;
- node->next = NULL;
-
- if (mq->user_header_size)
- *hdr_ptr = (uint8_t *) node + sizeof(DMQ_Node);
- else
- *hdr_ptr = NULL;
- *msg_ptr = node->data;
- *length = node->length;
- *msg_handle = (void *) node;
-
- mq->length--;
-
- return 0;
-}
-
-int DMQ_AckMsg(DMQ *mq, void *msg_handle)
-{
- DMQ_Node *node = (DMQ_Node *) msg_handle;
-
- if (!node)
- return -EINVAL;
-
- DMQ_DestroyNode(mq, node);
-
- return 0;
-}
-
-int DMQ_IsEmpty(DMQ *mq)
-{
- return (mq->head == NULL);
-}
-
-void DMQ_Stats(DMQ_Ptr mq, const char *indent)
-{
- LogMessage("%s Length: %u (%u max)\n", indent, mq->length, mq->max_length);
- LogMessage("%s Size: %u internal (%u max), %u external, %u overhead\n",
- indent, mq->internal_size, mq->max_internal_size, mq->external_size, mq->overhead_size);
-}
-
-#endif /* SC_USE_DMQ */
-
-#endif /* SIDE_CHANNEL */
+++ /dev/null
-/*
- * 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.
- *
-** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
- * Copyright (C) 2012-2013 Sourcefire, Inc.
- *
- * Author: Michael Altizer <maltizer@sourcefire.com>
- *
- */
-
-#ifndef DMQ_H
-#define DMQ_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdint.h>
-
-#include "sidechannel_define.h"
-
-#ifdef SC_USE_DMQ
-
-typedef struct _dmq *DMQ_Ptr;
-
-DMQ_Ptr DMQ_Alloc(uint32_t msg_ring_entries, uint16_t msg_ring_header_size, uint32_t data_ring_size);
-int DMQ_ReserveMsg(DMQ_Ptr mq, uint32_t length, void **hdr_ptr, uint8_t **msg_ptr, void **msg_handle);
-int DMQ_CommitReservedMsg(DMQ_Ptr mq, void *msg_handle, uint32_t length, SCMQMsgFreeFunc msgFreeFunc);
-int DMQ_DiscardReservedMsg(DMQ_Ptr mq, void *msg_handle);
-int DMQ_CommitExternalMsg(DMQ_Ptr mq, const void *hdr, uint8_t *msg, uint32_t length, SCMQMsgFreeFunc msgFreeFunc);
-int DMQ_ReadMsg(DMQ_Ptr mq, const void **hdr_ptr, const uint8_t **msg_ptr, uint32_t *length, void **msg_handle);
-int DMQ_AckMsg(DMQ_Ptr mq, void *msg_handle);
-int DMQ_IsEmpty(DMQ_Ptr mq);
-void DMQ_Stats(DMQ_Ptr mq, const char *indent);
-
-#endif /* SC_USE_DMQ */
-
-#endif /* DMQ_H */
+++ /dev/null
-
-
-add_library ( scm STATIC
- sscm_logger.cc
- sscm_logger.h
-)
+++ /dev/null
-## $Id
-AUTOMAKE_OPTIONS=foreign no-dependencies
-
-noinst_LIBRARIES = libsscm.a
-
-libsscm_a_SOURCES = \
-sscm_logger.cc sscm_logger.h
-
-AM_CXXFLAGS = @AM_CXXFLAGS@
+++ /dev/null
-/*
- * 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.
- *
-** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
- * Copyright (C) 2012-2013 Sourcefire, Inc.
- *
- * Author: Michael Altizer <maltizer@sourcefire.com>
- *
- */
-#include "sscm_logger.h"
-
-#include <fcntl.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "side_channel/sidechannel.h"
-#include "util.h"
-
-#define CONF_SEPARATORS " \t\n\r,"
-#define CONF_RX_FILE "rx-log-file"
-#define CONF_TX_FILE "tx-log-file"
-#define CONF_PRIMER_FILE "primer-file"
-
-enum ConfState
-{
- STATE_START,
- STATE_RX_FILE,
- STATE_TX_FILE,
- STATE_PRIMER_FILE
-};
-
-static char rx_log_file[PATH_MAX]; // FIXIT 1 / process
-static int rx_log_fd = -1;
-static char tx_log_file[PATH_MAX];
-static int tx_log_fd = -1;
-static char primer_log_file[PATH_MAX];
-
-static int LoggerRXHandler(SCMsgHdr *hdr, const uint8_t *msg, uint32_t length)
-{
- SideChannelWriteMsgToFile(rx_log_fd, hdr, msg, length);
- return 0;
-}
-
-static int LoggerTXHandler(SCMsgHdr *hdr, const uint8_t *msg, uint32_t length)
-{
- SideChannelWriteMsgToFile(tx_log_fd, hdr, msg, length);
- return 0;
-}
-
-static int ConfigLogger(char *args)
-{
- char *token;
- char* lasts = "";
- char *argcpy = args;
- enum ConfState confState = STATE_START;
-
- for (token = strtok_r(argcpy, CONF_SEPARATORS, &lasts);
- token;
- token = strtok_r(NULL, CONF_SEPARATORS, &lasts))
- {
- switch (confState)
- {
- case STATE_START:
- if (strcmp(token, CONF_RX_FILE) == 0)
- confState = STATE_RX_FILE;
- else if (strcmp(token, CONF_TX_FILE) == 0)
- confState = STATE_TX_FILE;
- else if (strcmp(token, CONF_PRIMER_FILE) == 0)
- confState = STATE_PRIMER_FILE;
- else
- FatalError("Invalid logger side channel configuration token: '%s'\n", token);
- break;
- case STATE_RX_FILE:
- snprintf(rx_log_file, sizeof(rx_log_file), "%s", token);
- confState = STATE_START;
- break;
- case STATE_TX_FILE:
- snprintf(tx_log_file, sizeof(tx_log_file), "%s", token);
- confState = STATE_START;
- break;
- case STATE_PRIMER_FILE:
- snprintf(primer_log_file, sizeof(primer_log_file), "%s", token);
- confState = STATE_START;
- break;
- default:
- break;
- }
- }
-
- return 0;
-}
-
-static int InitLogger(void)
-{
- if (rx_log_file[0] != '\0')
- {
- LogMessage("Opening '%s' for side channel RX logging...\n", rx_log_file);
- rx_log_fd = open(rx_log_file, O_WRONLY|O_CREAT|O_TRUNC, 0664);
- if (rx_log_fd == -1)
- FatalError("Could not open Logger SCM RX log file '%s': %s (%d)\n", rx_log_file, get_error(errno), errno);
- SideChannelRegisterRXHandler(SC_MSG_TYPE_ANY, LoggerRXHandler, NULL);
- }
- if (tx_log_file[0] != '\0')
- {
- LogMessage("Opening '%s' for side channel TX logging...\n", tx_log_file);
- tx_log_fd = open(tx_log_file, O_WRONLY|O_CREAT|O_TRUNC, 0664);
- if (tx_log_fd == -1)
- FatalError("Could not open Logger SCM TX log file '%s': %s (%d)\n", tx_log_file, get_error(errno), errno);
- SideChannelRegisterTXHandler(SC_MSG_TYPE_ANY, LoggerTXHandler, NULL);
- }
-
- return 0;
-}
-
-static int PostInitLogger(void)
-{
- SCMsgHdr hdr;
- uint32_t length;
- uint8_t *msg;
- unsigned int messages;
- int fd;
-
- if (primer_log_file[0] != '\0')
- {
- fd = open(primer_log_file, O_RDONLY, 0664);
- if (fd == -1)
- FatalError("Could not open Logger SCM Primer log file '%s': %s (%d)\n", primer_log_file, get_error(errno), errno);
- messages = 0;
- while (SideChannelReadMsgFromFile(fd, &hdr, &msg, &length) == 0)
- {
- if (length == 0)
- msg = NULL;
- SideChannelEnqueueDataRX(&hdr, msg, length, free);
- messages++;
- }
- close(fd);
- LogMessage("Primed the side channel with %u messages from '%s'...\n", messages, primer_log_file);
- }
-
- return 0;
-}
-
-static void ShutdownLogger(void)
-{
- if (rx_log_fd != -1)
- {
- close(rx_log_fd);
- rx_log_fd = -1;
- SideChannelUnregisterRXHandler(SC_MSG_TYPE_ANY, LoggerRXHandler);
- }
- if (tx_log_fd)
- {
- close(tx_log_fd);
- tx_log_fd = -1;
- SideChannelUnregisterTXHandler(SC_MSG_TYPE_ANY, LoggerTXHandler);
- }
-}
-
-static const SCMFunctionBundle loggerFuncs = { // FIXIT 1 / process
- ConfigLogger,
- InitLogger,
- PostInitLogger,
- NULL,
- NULL,
- ShutdownLogger
-};
-
-int SetupLoggerSCM(void)
-{
- RegisterSideChannelModule("logger", &loggerFuncs);
- return 0;
-}
+++ /dev/null
-/*
- * 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.
- *
-** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
- * Copyright (C) 2012-2013 Sourcefire, Inc.
- *
- * Author: Michael Altizer <maltizer@sourcefire.com>
- *
- */
-
-#ifndef SSCM_LOGGER_H
-#define SSCM_LOGGER_H
-
-int SetupLoggerSCM(void);
-
-#endif
+++ /dev/null
-/*
- * 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.
- *
-** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
- * Copyright (C) 2012-2013 Sourcefire, Inc.
- *
- * Author: Michael Altizer <maltizer@sourcefire.com>
- *
- */
-
-#include "rbmq.h"
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef SIDE_CHANNEL
-#include <assert.h>
-#include <errno.h>
-#include "util.h"
-
-#ifndef SC_USE_DMQ
-#define RBMQ_MSG_FLAG_EXTERNAL 0x01
-
-enum {
- RBMQ_MSG_STATE_UNUSED = 0,
- RBMQ_MSG_STATE_RESERVED,
- RBMQ_MSG_STATE_COMMITTED,
- RBMQ_MSG_STATE_READ,
- RBMQ_MSG_STATE_ACKED,
- RBMQ_MSG_STATE_DISCARDED
-};
-
-typedef struct _rbmq_msg
-{
- uint32_t length;
- uint8_t flags;
- uint8_t state;
- uint8_t *data;
- SCMQMsgFreeFunc msgFreeFunc;
-} RBMQ_Msg;
-
-typedef struct _rmbq_internal_data_hdr
-{
- uint32_t msg_index;
- uint32_t prev_offset;
-} RBMQ_InternalDataHdr;
-
-typedef struct _rbmq_msg_ring
-{
- RBMQ_Msg *msgs;
- uint8_t *headers;
- uint32_t last_reserved;
- uint32_t last_read;
- uint32_t last_acked;
- uint32_t entries;
- uint16_t header_size;
-} RBMQ_MsgRing;
-
-typedef struct _rbmq_data_ring
-{
- uint8_t *data;
- uint32_t read_offset;
- uint32_t write_offset;
- uint32_t size;
-} RBMQ_DataRing;
-
-typedef struct _rbmq
-{
- RBMQ_MsgRing msg_ring;
- RBMQ_DataRing data_ring;
-} RBMQ;
-
-static inline uint32_t IncrementMessageIndex(RBMQ *mq, uint32_t index)
-{
- return (++index == mq->msg_ring.entries) ? 0 : index;
-}
-
-static inline uint32_t DecrementMessageIndex(RBMQ *mq, uint32_t index)
-{
- return (index == 0) ? (mq->msg_ring.entries - 1) : (index - 1);
-}
-
-/* Returns 0 if the message handle is within bounds for the control ring, non-zero otherwise. */
-static inline int ValidateMsgHandle(RBMQ *mq, void *msg_handle)
-{
- return (msg_handle < (void *)(&mq->msg_ring.msgs[0]) || msg_handle > (void *)(&mq->msg_ring.msgs[mq->msg_ring.entries - 1]));
-}
-
-RBMQ *RBMQ_Alloc(uint32_t msg_ring_entries, uint16_t msg_ring_header_size, uint32_t data_ring_size)
-{
- RBMQ *mq;
-
- mq = SnortAlloc(sizeof(RBMQ));
- memset(mq, 0, sizeof(RBMQ));
-
- /* Initialize the control ring. */
- mq->msg_ring.msgs = SnortAlloc(msg_ring_entries * sizeof(RBMQ_Msg));
- mq->msg_ring.headers = SnortAlloc(msg_ring_entries * msg_ring_header_size);
- mq->msg_ring.entries = msg_ring_entries;
- mq->msg_ring.header_size = msg_ring_header_size;
- memset(mq->msg_ring.msgs, 0, mq->msg_ring.entries * sizeof(RBMQ_Msg));
- mq->msg_ring.last_reserved = 0;
- mq->msg_ring.last_read = 0;
- mq->msg_ring.last_acked = 0;
-
- /* Initialize the data ring. */
- mq->data_ring.data = SnortAlloc(data_ring_size);
- mq->data_ring.size = data_ring_size;
- memset(mq->data_ring.data, 0, mq->data_ring.size);
-
- return mq;
-}
-
-void RBMQ_Destroy(RBMQ *mq)
-{
- RBMQ_Msg *msg_info;
- uint32_t idx;
-
- /* Free the data for any unprocessed messages. */
- idx = mq->msg_ring.last_acked;
- while (idx != mq->msg_ring.last_reserved)
- {
- idx++;
- if (idx == mq->msg_ring.entries)
- idx = 0;
- msg_info = &mq->msg_ring.msgs[idx];
- if (msg_info->msgFreeFunc)
- msg_info->msgFreeFunc(msg_info->data);
- }
-
- /* Release all of our resources. */
- free(mq->data_ring.data);
- free(mq->msg_ring.msgs);
-}
-
-int RBMQ_ReserveMsg(RBMQ *mq, uint32_t length, void **hdr_ptr, uint8_t **msg_ptr, void **msg_handle)
-{
- RBMQ_InternalDataHdr *idh;
- RBMQ_Msg *msg_info;
- uint32_t msg_index, msg_len, start_offset;
-
- /* Find the next entry in the message ring to reserve. */
- msg_index = IncrementMessageIndex(mq, mq->msg_ring.last_reserved);
- msg_info = &mq->msg_ring.msgs[msg_index];
-
- /* Bail if the entry is in use. */
- if (msg_info->state != RBMQ_MSG_STATE_UNUSED)
- return -ENOMEM;
-
- /* Make sure that we can reserve the requested space in the data ring. */
- msg_len = length + sizeof(RBMQ_InternalDataHdr);
- if (mq->data_ring.write_offset < mq->data_ring.read_offset)
- {
- if ((mq->data_ring.read_offset - mq->data_ring.write_offset) < msg_len)
- return -ENOMEM;
- start_offset = mq->data_ring.write_offset;
- }
- else if ((mq->data_ring.size - mq->data_ring.write_offset) < msg_len)
- {
- if (mq->data_ring.read_offset < msg_len)
- return -ENOMEM;
- start_offset = 0;
- }
- else
- start_offset = mq->data_ring.write_offset;
-
- idh = (RBMQ_InternalDataHdr *) (mq->data_ring.data + start_offset);
- idh->msg_index = msg_index;
- idh->prev_offset = mq->data_ring.write_offset;
-
- /* Update the write offset in the data ring, wrapping as necessary. */
- mq->data_ring.write_offset = start_offset + msg_len;
- if (mq->data_ring.write_offset == mq->data_ring.size)
- mq->data_ring.write_offset = 0;
-
- msg_info->length = length;
- /* Type is filled in during the commit. */
- msg_info->flags = 0;
- msg_info->state = RBMQ_MSG_STATE_RESERVED;
- msg_info->data = (uint8_t *) idh + sizeof(RBMQ_InternalDataHdr);
- msg_info->msgFreeFunc = NULL;
-
- /* Update the last reservation index in the control ring. */
- mq->msg_ring.last_reserved = msg_index;
-
- if (mq->msg_ring.header_size)
- *hdr_ptr = mq->msg_ring.headers + (msg_index * mq->msg_ring.header_size);
- else
- *hdr_ptr = NULL;
- *msg_ptr = msg_info->data;
- *msg_handle = (void *) msg_info;
-
- return 0;
-}
-
-int RBMQ_CommitReservedMsg(RBMQ *mq, void *msg_handle, uint32_t length, SCMQMsgFreeFunc msgFreeFunc)
-{
- RBMQ_Msg *msg_info;
-
- if (ValidateMsgHandle(mq, msg_handle))
- return -EINVAL;
-
- msg_info = (RBMQ_Msg *) msg_handle;
-
- /* Sanity checks... */
- if (msg_info->state != RBMQ_MSG_STATE_RESERVED)
- {
- ErrorMessage("%s: Attempted to commit an unreserved message! (State: %hhu)\n", __FUNCTION__, msg_info->state);
- return -EINVAL;
- }
-
- if (length > msg_info->length)
- {
- ErrorMessage("%s: Attempted to commit illegally enlarged message! (%u vs %u)\n", __FUNCTION__, length, msg_info->length);
- return -EINVAL;
- }
-
- /* If the committed length is less than the reserved length and it was the last message reserved,
- truncate the internal data ring usage. */
- if (length < msg_info->length && msg_info == &mq->msg_ring.msgs[mq->msg_ring.last_reserved])
- {
- if (mq->data_ring.write_offset != 0)
- mq->data_ring.write_offset -= (msg_info->length - length);
- else
- mq->data_ring.write_offset = mq->data_ring.size - (msg_info->length - length);
- msg_info->length = length;
- }
-
- msg_info->state = RBMQ_MSG_STATE_COMMITTED;
- msg_info->msgFreeFunc = msgFreeFunc;
-
- return 0;
-}
-
-int RBMQ_DiscardReservedMsg(RBMQ *mq, void *msg_handle)
-{
- RBMQ_InternalDataHdr *idh;
- RBMQ_Msg *msg_info;
- uint32_t idx;
-
- if (ValidateMsgHandle(mq, msg_handle))
- return -EINVAL;
-
- msg_info = (RBMQ_Msg *) msg_handle;
-
- /* Sanity checks... */
- if (msg_info->state != RBMQ_MSG_STATE_RESERVED)
- {
- ErrorMessage("%s: Attempted to discard an unreserved message! (State: %hhu)\n", __FUNCTION__, msg_info->state);
- return -EINVAL;
- }
-
- msg_info->state = RBMQ_MSG_STATE_DISCARDED;
-
- /* Working backward from the last entry reserved (in order), release discarded messages as allowed.
- Any discarded messages that we can't release here will have to wait until something gets ACK'd. */
- idx = mq->msg_ring.last_reserved;
- msg_info = &mq->msg_ring.msgs[idx];
- while (msg_info->state == RBMQ_MSG_STATE_DISCARDED)
- {
- /* Clean up the data ring state if this was internally allocated. Only internally allocated
- messages can be discarded, so this should be safe. */
- idh = (RBMQ_InternalDataHdr *) (msg_info->data - sizeof(RBMQ_InternalDataHdr));
- mq->data_ring.write_offset = idh->prev_offset;
-
- /* Reset the state to unused so that it can be reserved again. */
- msg_info->state = RBMQ_MSG_STATE_UNUSED;
-
- /* Finally, update the last reserved index. */
- idx = DecrementMessageIndex(mq, idx);
- mq->msg_ring.last_reserved = idx;
- msg_info = &mq->msg_ring.msgs[idx];
- }
-
- return 0;
-}
-
-int RBMQ_CommitExternalMsg(RBMQ *mq, const void *hdr, uint8_t *msg, uint32_t length, SCMQMsgFreeFunc msgFreeFunc)
-{
- RBMQ_Msg *msg_info;
- uint32_t idx;
-
- /* V Reserve and commit the message all in one step. V */
-
- /* Find the next entry in the message ring to reserve. */
- idx = IncrementMessageIndex(mq, mq->msg_ring.last_reserved);
- msg_info = &mq->msg_ring.msgs[idx];
-
- /* Bail if the entry is in use. */
- if (msg_info->state != RBMQ_MSG_STATE_UNUSED)
- return -ENOMEM;
-
- /* Require a header if there is a header size specified for the control ring and copy it over. */
- if (mq->msg_ring.header_size)
- {
- if (!hdr)
- return -EINVAL;
- memcpy(mq->msg_ring.headers + (idx * mq->msg_ring.header_size), hdr, mq->msg_ring.header_size);
- }
-
- msg_info->length = length;
- msg_info->flags = RBMQ_MSG_FLAG_EXTERNAL;
- msg_info->state = RBMQ_MSG_STATE_COMMITTED;
- msg_info->data = msg;
- msg_info->msgFreeFunc = msgFreeFunc;
-
- /* Update the last reservation index in the control ring. */
- mq->msg_ring.last_reserved = idx;
-
- return 0;
-}
-
-int RBMQ_ReadMsg(RBMQ *mq, const void **hdr_ptr, const uint8_t **msg_ptr, uint32_t *length, void **msg_handle)
-{
- RBMQ_Msg *msg_info;
- uint32_t idx;
-
- /* Find the next entry in the message ring to read. */
- idx = IncrementMessageIndex(mq, mq->msg_ring.last_read);
- msg_info = &mq->msg_ring.msgs[idx];
-
- /* Skip over discarded messages -- the next ACK should clear them out. */
- while (msg_info->state == RBMQ_MSG_STATE_DISCARDED)
- {
- mq->msg_ring.last_read = idx;
- idx = IncrementMessageIndex(mq, idx);
- msg_info = &mq->msg_ring.msgs[idx];
- }
-
- /* Return an error if there is not a committed entry ready to be read. */
- if (msg_info->state != RBMQ_MSG_STATE_COMMITTED)
- return -ENOENT;
-
- if (mq->msg_ring.header_size)
- *hdr_ptr = mq->msg_ring.headers + (idx * mq->msg_ring.header_size);
- else
- *hdr_ptr = NULL;
- *msg_ptr = msg_info->data;
- *length = msg_info->length;
- *msg_handle = msg_info;
-
- msg_info->state = RBMQ_MSG_STATE_READ;
- mq->msg_ring.last_read = idx;
-
- return 0;
-}
-
-int RBMQ_AckMsg(RBMQ *mq, void *msg_handle)
-{
- RBMQ_Msg *msg_info;
- uint32_t idx;
-
- /* Sanity checking... */
- if (ValidateMsgHandle(mq, msg_handle))
- return -EINVAL;
-
- msg_info = (RBMQ_Msg *) msg_handle;
- if (msg_info->state != RBMQ_MSG_STATE_READ)
- {
- ErrorMessage("%s: Attempted to ACK an unread message! (State: %hhu)\n", __FUNCTION__, msg_info->state);
- return -EINVAL;
- }
-
- /* Call the user defined free function to release the message data if it exists. */
- if (msg_info->data && msg_info->msgFreeFunc)
- msg_info->msgFreeFunc(msg_info->data);
-
- msg_info->state = RBMQ_MSG_STATE_ACKED;
-
- /* Working forward from the last entry ACK'd (in order), release ACK'd and discarded messages as allowed. */
- do {
- idx = IncrementMessageIndex(mq, mq->msg_ring.last_acked);
- msg_info = &mq->msg_ring.msgs[idx];
- if (msg_info->state != RBMQ_MSG_STATE_ACKED && msg_info->state != RBMQ_MSG_STATE_DISCARDED)
- break;
-
- /* Clean up the data ring state if this was internally allocated. We are guaranteed that internal
- allocations will be sequential in relation to sequential control entries.*/
- if (!(msg_info->flags & RBMQ_MSG_FLAG_EXTERNAL))
- mq->data_ring.read_offset = msg_info->data + msg_info->length - mq->data_ring.data;
-
- /* Reset the state to unused so it can be reserved again. */
- msg_info->state = RBMQ_MSG_STATE_UNUSED;
-
- /* Finally, update the last ACK'd index to accurately represent how far processing has gotten. */
- mq->msg_ring.last_acked = idx;
- } while (mq->msg_ring.last_acked != mq->msg_ring.last_read);
-
- return 0;
-}
-
-int RBMQ_IsEmpty(RBMQ *mq)
-{
- RBMQ_Msg *msg_info;
- uint32_t idx;
-
- /* Find the next entry in the message ring to read and return true if it's not committed. */
- idx = IncrementMessageIndex(mq, mq->msg_ring.last_read);
- msg_info = &mq->msg_ring.msgs[idx];
-
- return (msg_info->state != RBMQ_MSG_STATE_COMMITTED);
-}
-
-void RBMQ_Stats(RBMQ_Ptr mq, const char *indent)
-{
-}
-
-#endif /* !SC_USE_DMQ */
-
-#endif /* SIDE_CHANNEL */
+++ /dev/null
-/*
- * 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.
- *
-** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
- * Copyright (C) 2012-2013 Sourcefire, Inc.
- *
- * Author: Michael Altizer <maltizer@sourcefire.com>
- *
- */
-
-#ifndef RBMQ_H
-#define RBMQ_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdint.h>
-
-#include "sidechannel_define.h"
-
-#ifndef SC_USE_DMQ
-
-typedef struct _rbmq *RBMQ_Ptr;
-
-RBMQ_Ptr RBMQ_Alloc(uint32_t msg_ring_entries, uint16_t msg_ring_header_size, uint32_t data_ring_size);
-int RBMQ_ReserveMsg(RBMQ_Ptr mq, uint32_t length, void **hdr_ptr, uint8_t **msg_ptr, void **msg_handle);
-int RBMQ_CommitReservedMsg(RBMQ_Ptr mq, void *msg_handle, uint32_t length, SCMQMsgFreeFunc msgFreeFunc);
-int RBMQ_DiscardReservedMsg(RBMQ_Ptr mq, void *msg_handle);
-int RBMQ_CommitExternalMsg(RBMQ_Ptr mq, const void *hdr, uint8_t *msg, uint32_t length, SCMQMsgFreeFunc msgFreeFunc);
-int RBMQ_ReadMsg(RBMQ_Ptr mq, const void **hdr_ptr, const uint8_t **msg_ptr, uint32_t *length, void **msg_handle);
-int RBMQ_AckMsg(RBMQ_Ptr mq, void *msg_handle);
-int RBMQ_IsEmpty(RBMQ_Ptr mq);
-void RBMQ_Stats(RBMQ_Ptr mq, const char *indent);
-
-#endif /* !SC_USE_DMQ */
-
-#endif /* RBMQ_H */
+++ /dev/null
-/*
- * 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.
- *
-** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
- * Copyright (C) 2012-2013 Sourcefire, Inc.
- *
- * Author: Michael Altizer <maltizer@sourcefire.com>
- *
- */
-
-#include "sidechannel.h"
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef SIDE_CHANNEL
-#include <pthread.h>
-#include <signal.h>
-
-#include "dmq.h"
-#include "rbmq.h"
-#include "plugins/sscm_logger.h"
-#include "helpers/process.h"
-
-#define DEFAULT_RX_QUEUE_DEPTH 1024
-#define DEFAULT_RX_QUEUE_DATA_SIZE 10485760
-#define DEFAULT_TX_QUEUE_DEPTH 1024
-#define DEFAULT_TX_QUEUE_DATA_SIZE 10485760
-
-#define CONF_SEPARATORS " \t\n\r,"
-#define CONF_RX_QUEUE_DATA_SIZE "rx-queue-data-size"
-#define CONF_RX_QUEUE_DEPTH "rx-queue-depth"
-#define CONF_TX_QUEUE_DATA_SIZE "tx-queue-data-size"
-#define CONF_TX_QUEUE_DEPTH "tx-queue-depth"
-#define CONF_DISABLE_TX_THREAD "disable-tx-thread"
-
-#ifdef SC_USE_DMQ
-#define RBMQ_Ptr DMQ_Ptr
-#define RBMQ_Alloc DMQ_Alloc
-#define RBMQ_ReserveMsg DMQ_ReserveMsg
-#define RBMQ_CommitReservedMsg DMQ_CommitReservedMsg
-#define RBMQ_DiscardReservedMsg DMQ_DiscardReservedMsg
-#define RBMQ_CommitExternalMsg DMQ_CommitExternalMsg
-#define RBMQ_ReadMsg DMQ_ReadMsg
-#define RBMQ_AckMsg DMQ_AckMsg
-#define RBMQ_IsEmpty DMQ_IsEmpty
-#define RBMQ_Stats DMQ_Stats
-#endif
-
-enum ConfState
-{
- STATE_START,
- STATE_RX_QUEUE_DATA_SIZE,
- STATE_RX_QUEUE_DEPTH,
- STATE_TX_QUEUE_DATA_SIZE,
- STATE_TX_QUEUE_DEPTH
-};
-
-typedef struct _SC_CONFIG
-{
- uint32_t rx_queue_max_data_size;
- uint32_t rx_queue_max_depth;
- uint32_t tx_queue_max_data_size;
- uint32_t tx_queue_max_depth;
- bool disable_tx_thread;
- bool enabled;
-} SCConfig;
-
-typedef struct _SC_MODULE
-{
- struct _SC_MODULE *next;
- char *keyword;
- SCMFunctionBundle funcs;
- bool enabled;
-} SCModule;
-
-typedef struct _SC_HANDLER
-{
- struct _SC_HANDLER *next;
- uint16_t type;
- SCMProcessMsgFunc processMsgFunc;
- void *data;
-} SCHandler;
-
-typedef struct _SC_MESSAGE_QUEUE
-{
- RBMQ_Ptr queue;
- pthread_mutex_t mutex;
- pthread_cond_t cond;
- uint32_t max_data_size;
- uint32_t max_depth;
-} SCMessageQueue;
-
-static struct { // FIXIT 1 / process
- uint64_t rx_messages_total;
- uint64_t rx_messages_processed_ib;
- uint64_t rx_messages_processed_oob;
- uint64_t tx_messages_total;
- uint64_t tx_messages_processed;
-} Side_Channel_Stats;
-
-static volatile int stop_processing = 0;
-static volatile int tx_thread_running = 0;
-
-static pid_t tx_thread_pid;
-static pthread_t tx_thread_id;
-static pthread_t *p_tx_thread_id;
-
-static SCConfig sc_config;
-
-static SCMessageQueue rx_queue;
-static SCMessageQueue tx_queue;
-
-static SCModule *modules;
-static SCHandler *rx_handlers;
-static SCHandler *tx_handlers;
-
-#ifdef PERF_PROFILING
-//static THREAD_LOCAL PreprocStats sideChannelRxPerfStats; // FIXIT not in use
-#endif
-
-void RegisterSideChannelModules(void)
-{
- if (!ScSideChannelEnabled())
- return;
-
- SetupLoggerSCM();
-}
-
-void RegisterSideChannelModule(const char *keyword, SCMFunctionBundle *funcs)
-{
- SCModule *module, *tmp, *last = NULL;
-
- if (!ScSideChannelEnabled())
- return;
-
- if (!keyword)
- FatalError("No keyword given while registering a side channel module!\n");
-
- if (!funcs)
- FatalError("No function bundle given while registering side channel '%s'!\n", keyword);
-
- for (tmp = modules; tmp; tmp = tmp->next)
- {
- if (strcasecmp(tmp->keyword, keyword) == 0)
- FatalError("Duplicate side channel keyword: %s\n", keyword);
- last = tmp;
- }
- module = (SCModule*)SnortAlloc(sizeof(SCModule));
-
- module->next = NULL;
- module->keyword = SnortStrdup(keyword);
- module->funcs = *funcs;
- module->enabled = 0;
-
- LogMessage("Register SCM '%s' with configFunc=%p, initFunc=%p, postInitFunc=%p, idleFunc=%p, statsFunc=%p, shutdownFunc=%p\n",
- keyword, module->funcs.configFunc, module->funcs.initFunc, module->funcs.postInitFunc,
- module->funcs.idleFunc, module->funcs.statsFunc, module->funcs.shutdownFunc);
-
- if (last)
- last->next = module;
- else
- modules = module;
-}
-
-int ConfigureSideChannelModule(const char *keyword, char *opts)
-{
- SCModule *module;
-
- for (module = modules; module; module = module->next)
- {
- if (strcasecmp(module->keyword, keyword) == 0)
- break;
- }
- if (!module)
- return -ENOENT;
-
- module->funcs.configFunc(opts);
- module->enabled = 1;
-
- return 0;
-}
-
-static int SCRegisterHandler(SCHandler **handlers, uint16_t type, SCMProcessMsgFunc processMsgFunc, void *data)
-{
- SCHandler *handler;
-
- if (!ScSideChannelEnabled())
- return 0;
-
- handler = (SCHandler*)SnortAlloc(sizeof(SCHandler));
-
- handler->next = NULL;
- handler->type = type;
- handler->processMsgFunc = processMsgFunc;
- handler->data = data;
-
- handler->next = *handlers;
- *handlers = handler;
-
- return 0;
-}
-
-int SideChannelRegisterRXHandler(uint16_t type, SCMProcessMsgFunc processMsgFunc, void *data)
-{
- return SCRegisterHandler(&rx_handlers, type, processMsgFunc, data);
-}
-
-int SideChannelRegisterTXHandler(uint16_t type, SCMProcessMsgFunc processMsgFunc, void *data)
-{
- return SCRegisterHandler(&tx_handlers, type, processMsgFunc, data);
-}
-
-static void SCUnregisterHandler(SCHandler **handlers, uint16_t type, SCMProcessMsgFunc processMsgFunc)
-{
- SCHandler *handler, *prev;
-
- if (!ScSideChannelEnabled())
- return;
-
- for (prev = NULL, handler = *handlers; handler; prev = handler, handler = handler->next)
- {
- if (handler->type == type && handler->processMsgFunc == processMsgFunc)
- break;
- }
-
- if (handler)
- {
- if (!prev)
- *handlers = handler->next;
- else
- prev->next = handler->next;
-
- free(handler);
- }
-}
-
-void SideChannelUnregisterRXHandler(uint16_t type, SCMProcessMsgFunc processMsgFunc)
-{
- SCUnregisterHandler(&rx_handlers, type, processMsgFunc);
-}
-
-void SideChannelUnregisterTXHandler(uint16_t type, SCMProcessMsgFunc processMsgFunc)
-{
- SCUnregisterHandler(&tx_handlers, type, processMsgFunc);
-}
-
-static int SCPreallocMessage(SCMessageQueue *mq, uint32_t length, SCMsgHdr **hdr_ptr, uint8_t **msg_ptr, void **msg_handle)
-{
- int rval;
-
- pthread_mutex_lock(&mq->mutex);
- rval = RBMQ_ReserveMsg(mq->queue, length, (void **) hdr_ptr, msg_ptr, msg_handle);
- pthread_mutex_unlock(&mq->mutex);
-
- return rval;
-}
-
-int SideChannelPreallocMessageRX(uint32_t length, SCMsgHdr **hdr_ptr, uint8_t **msg_ptr, void **msg_handle)
-{
- return SCPreallocMessage(&rx_queue, length, hdr_ptr, msg_ptr, msg_handle);
-}
-
-int SideChannelPreallocMessageTX(uint32_t length, SCMsgHdr **hdr_ptr, uint8_t **msg_ptr, void **msg_handle)
-{
- return SCPreallocMessage(&tx_queue, length, hdr_ptr, msg_ptr, msg_handle);
-}
-
-static int SCDiscardMessage(SCMessageQueue *mq, void *msg_handle)
-{
- int rval;
-
- pthread_mutex_lock(&mq->mutex);
- rval = RBMQ_DiscardReservedMsg(mq->queue, msg_handle);
- pthread_mutex_unlock(&mq->mutex);
-
- return rval;
-}
-
-int SideChannelDiscardMessageRX(void *msg_handle)
-{
- return SCDiscardMessage(&rx_queue, msg_handle);
-}
-
-int SideChannelDiscardMessageTX(void *msg_handle)
-{
- return SCDiscardMessage(&tx_queue, msg_handle);
-}
-
-static int SCEnqueueMessage(SCMessageQueue *mq, SCMsgHdr *hdr, const uint8_t *msg, uint32_t length, void *msg_handle, SCMQMsgFreeFunc msgFreeFunc)
-{
- int rval;
-
- if (!msg_handle)
- {
- SCMsgHdr *hdr_ptr;
- uint8_t *msg_ptr;
-
- rval = RBMQ_ReserveMsg(mq->queue, length, (void **) &hdr_ptr, &msg_ptr, &msg_handle);
- if (rval != 0)
- {
- ErrorMessage("%s: Could not reserve message: %d\n", __FUNCTION__, rval);
- return rval;
- }
- memcpy(msg_ptr, msg, length);
- memcpy(hdr_ptr, hdr, sizeof(SCMsgHdr));
- rval = RBMQ_CommitReservedMsg(mq->queue, msg_handle, length, msgFreeFunc);
- if (rval != 0)
- {
- ErrorMessage("%s: Could not commit reserved message: %d\n", __FUNCTION__, rval);
- return rval;
- }
- }
- else
- rval = RBMQ_CommitReservedMsg(mq->queue, msg_handle, length, msgFreeFunc);
-
- return rval;
-}
-
-static inline void SCProcessMessage(SCHandler *handlers, SCMsgHdr *hdr, const uint8_t *msg, uint32_t length)
-{
- SCHandler *handler;
-
- for (handler = handlers; handler; handler = handler->next)
- {
- if (hdr->type == handler->type || handler->type == SC_MSG_TYPE_ANY)
- handler->processMsgFunc(hdr, msg, length);
- }
-}
-
-static int SCDrainAndProcess(SCMessageQueue *mq, SCHandler *handlers)
-{
- SCHandler *handler;
- SCMsgHdr *hdr;
- uint32_t length;
- const uint8_t *msg;
- void *msg_handle;
- int rval;
-
- /* Read a message from the queue. */
- pthread_mutex_lock(&mq->mutex);
- rval = RBMQ_ReadMsg(mq->queue, (const void **) &hdr, &msg, &length, &msg_handle);
- pthread_mutex_unlock(&mq->mutex);
- if (rval != 0)
- return 1;
-
- /* Handle it. */
- SCProcessMessage(handlers, hdr, msg, length);
-
- /* And, finally, acknowledge it. */
- pthread_mutex_lock(&mq->mutex);
- rval = RBMQ_AckMsg(mq->queue, msg_handle);
- pthread_mutex_unlock(&mq->mutex);
- if (rval != 0)
- WarningMessage("Error ACK'ing message %p!\n", msg_handle);
-
- return 0;
-}
-
-/* Called by an out-of-band thread (probably a Side Channel Module). */
-int SideChannelEnqueueMessageRX(SCMsgHdr *hdr, const uint8_t *msg, uint32_t length, void *msg_handle, SCMQMsgFreeFunc msgFreeFunc)
-{
- int rval;
-
- /*
- * Because the Snort main thread relinquishes control to DAQ_Acquire for up to a second,
- * we potentially need to preempt it and process RX messages as they are being enqueued
- * to avoid backups and overruns.
- * This should be safe since the main thread holds the snort_process_lock mutex while it
- * is not in DAQ_Acquire().
- */
- while (pthread_mutex_trylock(&snort_process_lock) == 0)
- {
- /* If there are no more messages in the RX queue, process the new message without enqueuing it and return. */
- if (SCDrainAndProcess(&rx_queue, rx_handlers) != 0)
- {
- SCProcessMessage(rx_handlers, hdr, msg, length);
- if (msgFreeFunc)
- msgFreeFunc((uint8_t *) msg);
- if (msg_handle)
- {
- pthread_mutex_lock(&rx_queue.mutex);
- RBMQ_DiscardReservedMsg(rx_queue.queue, msg_handle);
- pthread_mutex_unlock(&rx_queue.mutex);
- }
- Side_Channel_Stats.rx_messages_total++;
- Side_Channel_Stats.rx_messages_processed_oob++;
-
- pthread_mutex_unlock(&snort_process_lock);
- return 0;
- }
- else
- Side_Channel_Stats.rx_messages_processed_oob++;
-
- pthread_mutex_unlock(&snort_process_lock);
- }
-
- /* Finally, enqueue the message if we really have to. */
- pthread_mutex_lock(&rx_queue.mutex);
- rval = SCEnqueueMessage(&rx_queue, hdr, msg, length, msg_handle, msgFreeFunc);
- /* TODO: Error check the above call. */
- Side_Channel_Stats.rx_messages_total++;
- pthread_mutex_unlock(&rx_queue.mutex);
-
- return rval;
-}
-
-/* Called in the Snort main thread. */
-int SideChannelEnqueueMessageTX(SCMsgHdr *hdr, const uint8_t *msg, uint32_t length, void *msg_handle, SCMQMsgFreeFunc msgFreeFunc)
-{
- int rval, empty;
-
- /* Only bother queuing if the TX thread is running, otherwise just immediately process. */
- if (tx_thread_running)
- {
- pthread_mutex_lock(&tx_queue.mutex);
- empty = RBMQ_IsEmpty(tx_queue.queue);
- rval = SCEnqueueMessage(&tx_queue, hdr, msg, length, msg_handle, msgFreeFunc);
- /* TODO: Error check the above call. */
- Side_Channel_Stats.tx_messages_total++;
- /* If the queue was empty, signal any waiters. */
- if (empty)
- pthread_cond_signal(&tx_queue.cond);
- pthread_mutex_unlock(&tx_queue.mutex);
- }
- else
- {
- SCProcessMessage(tx_handlers, hdr, msg, length);
- Side_Channel_Stats.tx_messages_total++;
- Side_Channel_Stats.tx_messages_processed++;
- if (msgFreeFunc)
- msgFreeFunc((uint8_t *) msg);
- if (msg_handle)
- {
- pthread_mutex_lock(&tx_queue.mutex);
- RBMQ_DiscardReservedMsg(tx_queue.queue, msg_handle);
- pthread_mutex_unlock(&tx_queue.mutex);
- }
- rval = 0;
- }
-
- return rval;
-}
-
-static int SCEnqueueData(SCMessageQueue *mq, SCMsgHdr *hdr, uint8_t *msg, uint32_t length, SCMQMsgFreeFunc msgFreeFunc)
-{
- return RBMQ_CommitExternalMsg(mq->queue, hdr, msg, length, msgFreeFunc);
-}
-
-/* Called by an out-of-band thread (probably a Side Channel Module). */
-int SideChannelEnqueueDataRX(SCMsgHdr *hdr, uint8_t *msg, uint32_t length, SCMQMsgFreeFunc msgFreeFunc)
-{
- int rval;
-
- pthread_mutex_lock(&rx_queue.mutex);
- rval = SCEnqueueData(&rx_queue, hdr, msg, length, msgFreeFunc);
- /* TODO: Error check the above call. */
- Side_Channel_Stats.rx_messages_total++;
- pthread_mutex_unlock(&rx_queue.mutex);
-
- return rval;
-}
-
-/* Called in the Snort main thread. */
-int SideChannelEnqueueDataTX(SCMsgHdr *hdr, uint8_t *msg, uint32_t length, SCMQMsgFreeFunc msgFreeFunc)
-{
- int rval, empty;
-
- /* Only bother queuing if the TX thread is running, otherwise just immediately process. */
- if (tx_thread_running)
- {
- pthread_mutex_lock(&tx_queue.mutex);
- empty = RBMQ_IsEmpty(tx_queue.queue);
- rval = SCEnqueueData(&tx_queue, hdr, msg, length, msgFreeFunc);
- /* TODO: Error check the above call. */
- Side_Channel_Stats.tx_messages_total++;
- /* If the queue was empty, signal any waiters. */
- if (empty)
- pthread_cond_signal(&tx_queue.cond);
- pthread_mutex_unlock(&tx_queue.mutex);
- }
- else
- {
- SCProcessMessage(tx_handlers, hdr, msg, length);
- Side_Channel_Stats.tx_messages_total++;
- Side_Channel_Stats.tx_messages_processed++;
- msgFreeFunc(msg);
- rval = 0;
- }
-
- return rval;
-}
-
-/* Called in the Snort main thread. */
-uint32_t SideChannelDrainRX(unsigned max_msgs)
-{
- uint32_t processed = 0;
-
- if (!ScSideChannelEnabled())
- return 0;
-
- if (RBMQ_IsEmpty(rx_queue.queue))
- return 0;
-
- while (!max_msgs || processed < max_msgs)
- {
- if (stop_processing || SCDrainAndProcess(&rx_queue, rx_handlers) != 0)
- break;
-
- Side_Channel_Stats.rx_messages_processed_ib++;
- processed++;
- }
-
- return processed;
-}
-
-static void *SideChannelThread(void *arg)
-{
- struct timespec ts;
- struct timeval tv;
- SCHandler *handler;
- SCModule *module;
- SCMsgHdr *hdr;
- uint32_t length;
- const uint8_t *msg;
- void *msg_handle;
- int rval;
-
- tx_thread_pid = gettid();
- tx_thread_running = 1;
-
- pthread_mutex_lock(&tx_queue.mutex);
- while (!stop_processing)
- {
- /* If the message queue is empty, we will stop without unlocking it so we can immediately start a timed wait. */
- while ((rval = RBMQ_ReadMsg(tx_queue.queue, (const void **) &hdr, &msg, &length, &msg_handle)) == 0)
- {
- pthread_mutex_unlock(&tx_queue.mutex);
-
- for (handler = tx_handlers; handler; handler = handler->next)
- {
- if (hdr->type == handler->type || handler->type == SC_MSG_TYPE_ANY)
- handler->processMsgFunc(hdr, msg, length);
- }
-
- pthread_mutex_lock(&tx_queue.mutex);
- rval = RBMQ_AckMsg(tx_queue.queue, msg_handle);
- if (rval != 0)
- WarningMessage("Error ACK'ing message %p!\n", msg_handle);
- /* Again, not unlocking so that we're already locked for the three places we can go
- from here, which are all expecting it (dequeue, timed wait, or done). */
-
- Side_Channel_Stats.tx_messages_processed++;
- if (stop_processing)
- goto done;
- }
- gettimeofday(&tv, NULL);
- ts.tv_sec = tv.tv_sec + 10;
- ts.tv_nsec = tv.tv_usec * 1000;
- rval = pthread_cond_timedwait(&tx_queue.cond, &tx_queue.mutex, &ts);
- /* If we timed out waiting for new output messages to process, run the registered idle routines. */
- if (rval == ETIMEDOUT && !stop_processing)
- {
- for (module = modules; module; module = module->next)
- {
- if (module->enabled && module->funcs.idleFunc)
- module->funcs.idleFunc();
- }
- }
- }
-done:
- pthread_mutex_unlock(&tx_queue.mutex);
-
- LogMessage("Side Channel thread exiting...\n");
-
- return NULL;
-}
-
-static void SCParseConfiguration(SnortConfig *sc, SCConfig *config)
-{
- long int value;
- char *token, *argcpy, *endptr;
- enum ConfState confState = STATE_START;
-
- memset(config, 0, sizeof(SCConfig));
-
- config->enabled = sc->side_channel_config.enabled;
- if (!config->enabled)
- return;
-
- config->rx_queue_max_data_size = DEFAULT_RX_QUEUE_DATA_SIZE;
- config->rx_queue_max_depth = DEFAULT_RX_QUEUE_DEPTH;
- config->tx_queue_max_data_size = DEFAULT_TX_QUEUE_DATA_SIZE;
- config->tx_queue_max_depth = DEFAULT_TX_QUEUE_DEPTH;
- config->disable_tx_thread = false;
-
- if (!sc->side_channel_config.opts)
- return;
-
- argcpy = sc->side_channel_config.opts;
- char* lasts = "";
-
- for (token = strtok_r(argcpy, CONF_SEPARATORS, &lasts);
- token;
- token = strtok_r(NULL, CONF_SEPARATORS, &lasts))
- {
- switch (confState)
- {
- case STATE_START:
- if (strcmp(token, CONF_RX_QUEUE_DATA_SIZE) == 0)
- confState = STATE_RX_QUEUE_DATA_SIZE;
- else if (strcmp(token, CONF_RX_QUEUE_DEPTH) == 0)
- confState = STATE_RX_QUEUE_DEPTH;
- else if (strcmp(token, CONF_TX_QUEUE_DATA_SIZE) == 0)
- confState = STATE_TX_QUEUE_DATA_SIZE;
- else if (strcmp(token, CONF_TX_QUEUE_DEPTH) == 0)
- confState = STATE_TX_QUEUE_DEPTH;
- else if (strcmp(token, CONF_DISABLE_TX_THREAD) == 0)
- config->disable_tx_thread = true;
- else
- FatalError("Invalid side channel configuration token: '%s'\n", token);
- break;
- case STATE_RX_QUEUE_DATA_SIZE:
- confState = STATE_START;
- value = SnortStrtoul(token, &endptr, 0);
- if (errno != 0 || *endptr != '\0')
- FatalError("Invalid argument for side channel RX queue data size: '%s'\n", token);
- config->rx_queue_max_data_size = value;
- break;
- case STATE_RX_QUEUE_DEPTH:
- confState = STATE_START;
- value = SnortStrtoul(token, &endptr, 0);
- if (errno != 0 || *endptr != '\0')
- FatalError("Invalid argument for side channel RX queue depth: '%s'\n", token);
- config->rx_queue_max_depth = value;
- break;
- case STATE_TX_QUEUE_DATA_SIZE:
- confState = STATE_START;
- value = SnortStrtoul(token, &endptr, 0);
- if (errno != 0 || *endptr != '\0')
- FatalError("Invalid argument for side channel TX queue data size: '%s'\n", token);
- config->tx_queue_max_data_size = value;
- break;
- case STATE_TX_QUEUE_DEPTH:
- confState = STATE_START;
- value = SnortStrtoul(token, &endptr, 0);
- if (errno != 0 || *endptr != '\0')
- FatalError("Invalid argument for side channel TX queue depth: '%s'\n", token);
- config->tx_queue_max_depth = value;
- break;
- default:
- break;
- }
- }
-}
-
-int SideChannelVerifyConfig(SnortConfig *sc)
-{
- SCConfig config;
-
- SCParseConfiguration(sc, &config);
-
- return memcmp(&config, &sc_config, sizeof(SCConfig));
-}
-
-void SideChannelConfigure(SnortConfig *sc)
-{
- if (!sc->side_channel_config.enabled)
- return;
-
- SCParseConfiguration(sc, &sc_config);
-
- rx_queue.max_data_size = sc_config.rx_queue_max_data_size;
- rx_queue.max_depth = sc_config.rx_queue_max_depth;
- tx_queue.max_data_size = sc_config.tx_queue_max_data_size;
- tx_queue.max_depth = sc_config.tx_queue_max_depth;
-
- LogMessage("Side Channel config:\n");
- LogMessage(" RX Queue Max Data Size: %u\n", sc_config.rx_queue_max_data_size);
- LogMessage(" RX Queue Max Depth: %u\n", sc_config.rx_queue_max_depth);
- LogMessage(" TX Queue Max Data Size: %u\n", sc_config.tx_queue_max_data_size);
- LogMessage(" RX Queue Max Depth: %u\n", sc_config.tx_queue_max_depth);
-}
-
-void SideChannelInit(void)
-{
- SCModule *module;
-
- if (!ScSideChannelEnabled())
- return;
-
- pthread_mutex_init(&rx_queue.mutex, NULL);
- pthread_cond_init(&rx_queue.cond, NULL);
- rx_queue.queue = RBMQ_Alloc(rx_queue.max_depth, sizeof(SCMsgHdr), rx_queue.max_data_size);
-
- pthread_cond_init(&tx_queue.cond, NULL);
- pthread_mutex_init(&tx_queue.mutex, NULL);
- tx_queue.queue = RBMQ_Alloc(tx_queue.max_depth, sizeof(SCMsgHdr), tx_queue.max_data_size);
-
- for (module = modules; module; module = module->next)
- {
- if (module->enabled && module->funcs.initFunc)
- module->funcs.initFunc();
- }
-}
-
-void SideChannelStartTXThread(void)
-{
- const struct timespec thread_sleep = { 0, 100 };
- SCModule *module;
- sigset_t mask;
- int found, rval;
-
- if (!ScSideChannelEnabled())
- return;
-
- if (sc_config.disable_tx_thread)
- return;
-
- /* Avoid starting the TX thread if there are no TX handlers or TX idle tasks registered. */
- found = 0;
- for (module = modules; module; module = module->next)
- {
- if (module->enabled && module->funcs.idleFunc)
- {
- found = 1;
- break;
- }
- }
- if (!found && !tx_handlers)
- {
- LogMessage("Not starting unnecessary Side Channel TX thread.\n");
- return;
- }
-
- /* Spin off the Side Channel handler thread. */
- sigemptyset(&mask);
- sigaddset(&mask, SIGTERM);
- sigaddset(&mask, SIGQUIT);
- sigaddset(&mask, SIGPIPE);
- sigaddset(&mask, SIGINT);
- sigaddset(&mask, SIGNAL_SNORT_RELOAD);
- sigaddset(&mask, SIGNAL_SNORT_DUMP_STATS);
- sigaddset(&mask, SIGUSR1);
- sigaddset(&mask, SIGUSR2);
- sigaddset(&mask, SIGNAL_SNORT_ROTATE_STATS);
- sigaddset(&mask, SIGNAL_SNORT_CHILD_READY);
- sigaddset(&mask, SIGNAL_SNORT_READ_ATTR_TBL);
- sigaddset(&mask, SIGVTALRM);
- pthread_sigmask(SIG_SETMASK, &mask, NULL);
-
- if ((rval = pthread_create(&tx_thread_id, NULL, &SideChannelThread, NULL)) != 0)
- {
- sigemptyset(&mask);
- pthread_sigmask(SIG_SETMASK, &mask, NULL);
- FatalError("Side Channel: Unable to create thread: %s\n", get_error(rval));
- }
- while (!tx_thread_running)
- nanosleep(&thread_sleep, NULL);
-
- p_tx_thread_id = &tx_thread_id;
- sigemptyset(&mask);
- pthread_sigmask(SIG_SETMASK, &mask, NULL);
- LogMessage("Side Channel TX thread started tid=%p (pid=%u)\n", (void *) tx_thread_id, tx_thread_pid);
-}
-
-void SideChannelStopTXThread(void)
-{
- int rval;
-
- if (!ScSideChannelEnabled())
- return;
-
- if (p_tx_thread_id != NULL)
- {
- stop_processing = 1;
- pthread_mutex_lock(&tx_queue.mutex);
- pthread_cond_signal(&tx_queue.cond);
- pthread_mutex_unlock(&tx_queue.mutex);
- if ((rval = pthread_join(*p_tx_thread_id, NULL)) != 0)
- WarningMessage("Side channel TX thread termination returned an error: %s\n", get_error(rval));
- }
-}
-
-int SideChannelPostInit(void)
-{
- SCModule *module;
-
- if (!ScSideChannelEnabled())
- return 0;
-
- for (module = modules; module; module = module->next)
- {
- if (module->enabled && module->funcs.postInitFunc)
- module->funcs.postInitFunc();
- }
-
- return 0;
-}
-
-void SideChannelStats(const char *separator)
-{
- SCModule *module;
-
- if (!ScSideChannelEnabled())
- return;
-
- LogMessage("%s\n", separator);
- LogMessage("Side Channel:\n");
- LogMessage(" RX Messages Total: %" PRIu64 "\n", Side_Channel_Stats.rx_messages_total);
- LogMessage(" RX Messages Processed (IB): %" PRIu64 "\n", Side_Channel_Stats.rx_messages_processed_ib);
- LogMessage(" RX Messages Processed (OOB): %" PRIu64 "\n", Side_Channel_Stats.rx_messages_processed_oob);
- LogMessage(" TX Messages Total: %" PRIu64 "\n", Side_Channel_Stats.tx_messages_total);
- LogMessage(" TX Messages Processed: %" PRIu64 "\n", Side_Channel_Stats.tx_messages_processed);
-
- for (module = modules; module; module = module->next)
- {
- if (module->enabled && module->funcs.statsFunc)
- {
- LogMessage("%s\n", separator);
- module->funcs.statsFunc(0);
- }
- }
-
- LogMessage(" RX Queue Stats:\n");
- RBMQ_Stats(rx_queue.queue, " ");
-
- LogMessage(" TX Queue Stats:\n");
- RBMQ_Stats(tx_queue.queue, " ");
-}
-
-void SideChannelCleanUp(void)
-{
- SCModule *module;
-
- if (!ScSideChannelEnabled())
- return;
-
- while ((module = modules))
- {
- if (module->enabled)
- {
- if (module->funcs.statsFunc)
- module->funcs.statsFunc(1);
-
- if (module->funcs.shutdownFunc)
- module->funcs.shutdownFunc();
- }
- modules = module->next;
- free(module->keyword);
- free(module);
- }
- pthread_cond_destroy(&tx_queue.cond);
- pthread_mutex_destroy(&tx_queue.mutex);
- pthread_cond_destroy(&rx_queue.cond);
- pthread_mutex_destroy(&rx_queue.mutex);
-}
-
-/*
- * WARNING: Messages are being written in and read assuming host byte order.
- */
-
-static inline ssize_t Write(int fd, const void *buf, size_t count)
-{
- ssize_t n;
- errno = 0;
-
- while ((n = write(fd, buf, count)) <= (ssize_t) count)
- {
- if (n == (ssize_t) count)
- return 0;
-
- if (n > 0)
- count -= n;
- else if (errno != EINTR)
- break;
- }
-
- return -1;
-}
-
-int SideChannelWriteMsgToFile(int fd, SCMsgHdr *hdr, const uint8_t *msg, uint32_t length)
-{
- if (Write(fd, &hdr->type, sizeof(hdr->type)) != 0)
- return -1;
-
- if (Write(fd, &hdr->timestamp, sizeof(hdr->timestamp)) != 0)
- return -1;
-
- if (Write(fd, &length, sizeof(length)) != 0)
- return -1;
-
- if (Write(fd, msg, length) != 0)
- return -1;
-
- return 0;
-}
-
-static inline ssize_t Read(int fd, void *buf, size_t count)
-{
- ssize_t n;
- errno = 0;
-
- while ((n = read(fd, buf, count)) <= (ssize_t) count)
- {
- if (n == (ssize_t) count)
- return 0;
-
- if (n > 0)
- {
- count -= n;
- buf = (uint8_t *) buf + n;
- }
- else if (n == 0)
- break;
- else if (errno != EINTR)
- {
- ErrorMessage("Error reading Logger SCM log file: %s (%d)\n", get_error(errno), errno);
- break;
- }
- }
- return -1;
-}
-
-int SideChannelReadMsgFromFile(int fd, SCMsgHdr *hdr, uint8_t **msg_ptr, uint32_t *length_ptr)
-{
- uint64_t timestamp;
- uint32_t length;
- uint16_t type;
- uint8_t *msg;
-
- if (Read(fd, &type, sizeof(type)) != 0)
- return -1;
-
- if (Read(fd, ×tamp, sizeof(timestamp)) != 0)
- return -1;
-
- if (Read(fd, &length, sizeof(length)) != 0)
- return -1;
-
- if (length > 0)
- {
- msg = (uint8_t*)SnortAlloc(length);
- if (Read(fd, msg, length) != 0)
- {
- free(msg);
- return -1;
- }
- }
- else
- msg = NULL;
-
- hdr->type = type;
- hdr->timestamp = timestamp;
- *length_ptr = length;
- *msg_ptr = msg;
-
- return 0;
-}
-
-#endif /* SIDE_CHANNEL */
+++ /dev/null
-/*
- * 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.
- *
-** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
- * Copyright (C) 2012-2013 Sourcefire, Inc.
- *
- * Author: Michael Altizer <maltizer@sourcefire.com>
- *
- */
-
-#ifndef SIDECHANNEL_H
-#define SIDECHANNEL_H
-
-#include "sidechannel_define.h"
-#include "snort.h"
-
-void SideChannelConfigure(SnortConfig *sc);
-void SideChannelInit(void);
-void SideChannelStartTXThread(void);
-void SideChannelStopTXThread(void);
-void SideChannelCleanUp(void);
-
-void RegisterSideChannelModule(const char *keyword, SCMFunctionBundle *funcs);
-void RegisterSideChannelModules(void);
-int SideChannelRegisterRXHandler(uint16_t type, SCMProcessMsgFunc processMsgFunc, void *data);
-int SideChannelRegisterTXHandler(uint16_t type, SCMProcessMsgFunc processMsgFunc, void *data);
-void SideChannelUnregisterRXHandler(uint16_t type, SCMProcessMsgFunc processMsgFunc);
-void SideChannelUnregisterTXHandler(uint16_t type, SCMProcessMsgFunc processMsgFunc);
-
-/* RX Functions */
-int SideChannelPreallocMessageRX(uint32_t length, SCMsgHdr **hdr_ptr, uint8_t **msg_ptr, void **msg_handle);
-int SideChannelDiscardMessageRX(void *msg_handle);
-int SideChannelEnqueueMessageRX(SCMsgHdr *hdr, const uint8_t *msg, uint32_t length, void *msg_handle, SCMQMsgFreeFunc msgFreeFunc);
-int SideChannelEnqueueDataRX(SCMsgHdr *hdr, uint8_t *msg, uint32_t length, SCMQMsgFreeFunc msgFreeFunc);
-uint32_t SideChannelDrainRX(unsigned max_msgs);
-
-/* TX Functions */
-int SideChannelPreallocMessageTX(uint32_t length, SCMsgHdr **hdr_ptr, uint8_t **msg_ptr, void **msg_handle);
-int SideChannelDiscardMessageTX(void *msg_handle);
-int SideChannelEnqueueMessageTX(SCMsgHdr *hdr, const uint8_t *msg, uint32_t length, void *msg_handle, SCMQMsgFreeFunc msgFreeFunc);
-int SideChannelEnqueueDataTX(SCMsgHdr *hdr, uint8_t *msg, uint32_t length, SCMQMsgFreeFunc msgFreeFunc);
-
-/* I/O Functions */
-int SideChannelWriteMsgToFile(int fd, SCMsgHdr *hdr, const uint8_t *msg, uint32_t length);
-int SideChannelReadMsgFromFile(int fd, SCMsgHdr *hdr, uint8_t **msg_ptr, uint32_t *length_ptr);
-
-int SideChannelVerifyConfig(SnortConfig *sc);
-
-int ConfigureSideChannelModule(const char *keyword, char *opts);
-void SideChannelStats(const char *separator);
-int SideChannelPostInit(void);
-
-#endif
+++ /dev/null
-/*
- * 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.
- *
-** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
- * Copyright (C) 2012-2013 Sourcefire, Inc.
- *
- * Author: Michael Altizer <maltizer@sourcefire.com>
- *
- */
-
-#ifndef SIDECHANNEL_DEFINE_H
-#define SIDECHANNEL_DEFINE_H
-
-#include <stdint.h>
-
-#define SC_USE_DMQ 1
-
-/* You get 16 bits worth of types. Use them wisely. */
-enum
-{
- SC_MSG_TYPE_NONE = 0,
- SC_MSG_TYPE_FLOW_STATE_TRACKING,
- SC_MSG_TYPE_ANY = 0xFFFF
-};
-
-typedef struct _SC_MESSAGE_HEADER
-{
- uint16_t type;
- uint64_t timestamp;
-} SCMsgHdr;
-
-typedef struct _SC_MESSAGE_QUEUE_NODE *SCMessageQueueNodePtr;
-
-typedef void (*SCMQMsgFreeFunc)(void *);
-
-typedef int (*SCMConfigFunc)(char *);
-typedef int (*SCMInitFunc)(void);
-typedef int (*SCMPostInitFunc)(void);
-typedef void (*SCMStatsFunc)(int exiting);
-typedef void (*SCMIdleFunc)(void);
-typedef int (*SCMProcessMsgFunc)(SCMsgHdr *hdr, const uint8_t *msg, uint32_t length);
-typedef void (*SCMShutdownFunc)(void);
-
-typedef struct _SCM_FUNCTION_BUNDLE {
- SCMConfigFunc configFunc;
- SCMInitFunc initFunc;
- SCMPostInitFunc postInitFunc;
- SCMIdleFunc idleFunc;
- SCMStatsFunc statsFunc;
- SCMShutdownFunc shutdownFunc;
-} SCMFunctionBundle;
-
-#endif /* SIDECHANNEL_DEFINE_H */
#include "managers/inspector_manager.h"
#include "managers/packet_manager.h"
-#ifdef SIDE_CHANNEL
-#include "side_channel/sidechannel.h"
-#endif
-
#define STATS_SEPARATOR \
"--------------------------------------------------"
show_stats((PegCount*)&gpc, pc_names, array_size(pc_names), "detection");
-#ifdef SIDE_CHANNEL
- SideChannelStats(STATS_SEPARATOR);
-#endif
-
proc_stats.attribute_table_hosts = SFAT_NumberOfHosts();
show_stats((PegCount*)&proc_stats, proc_names, array_size(proc_names), "process");
}
#include <unistd.h>
#include <pcap.h>
#include <timersub.h>
-#include <pthread.h>
#include <string.h>
#include <grp.h>
#include <pwd.h>
#include "target_based/sftarget_reader.h"
#include "stream/stream.h"
-#ifdef SIDE_CHANNEL
-#include "side_channel/sidechannel.h"
-#endif
-
#ifdef PATH_MAX
#define PATH_MAX_UTIL PATH_MAX
#else
#define PATH_MAX_UTIL 1024
-#endif /* PATH_MAX */
+#endif
// You may need to adjust this on the systems which don't have standard paths
// defined.
if ( pv )
return pv;
+ // FIXIT do not FatalError() on runtime allocation failures
FatalError("Unable to allocate memory! (%lu requested)\n", size);
return NULL;