plugins: support for capture plugins

Allow a plugin to register itself as a capture source. This isn't that
much different than how current sources register, it just happens
a little later on during startup.

One "slot" is reserved for capture plugins, but multiple plugins
implementing a capture can be loaded.  The --capture-plugin command
line option must be used to tell Suricata which plugin
to use.

This is still very much a work in progress, but can load
PF_RING as a capture plugin.
pull/5282/head
Jason Ish 5 years ago committed by Victor Julien
parent 8fb35236e6
commit e10d107415

@ -28,6 +28,7 @@
#define COUNTERS #define COUNTERS
#include "suricata-common.h" #include "suricata-common.h"
#include "suricata-plugin.h"
#include "threadvars.h" #include "threadvars.h"
#include "util-debug.h" #include "util-debug.h"
#include "decode-events.h" #include "decode-events.h"
@ -479,6 +480,9 @@ typedef struct Packet_
WinDivertPacketVars windivert_v; WinDivertPacketVars windivert_v;
#endif /* WINDIVERT */ #endif /* WINDIVERT */
/* A chunk of memory that a plugin can use for its packet vars. */
uint8_t plugin_v[PLUGIN_VAR_SIZE];
/** libpcap vars: shared by Pcap Live mode and Pcap File mode */ /** libpcap vars: shared by Pcap Live mode and Pcap File mode */
PcapPacketVars pcap_v; PcapPacketVars pcap_v;
}; };

@ -573,7 +573,7 @@ static TmEcode UnixSocketPcapFilesCheck(void *data)
PreRunInit(RUNMODE_PCAP_FILE); PreRunInit(RUNMODE_PCAP_FILE);
PreRunPostPrivsDropInit(RUNMODE_PCAP_FILE); PreRunPostPrivsDropInit(RUNMODE_PCAP_FILE);
RunModeDispatch(RUNMODE_PCAP_FILE, NULL); RunModeDispatch(RUNMODE_PCAP_FILE, NULL, NULL, NULL);
/* Un-pause all the paused threads */ /* Un-pause all the paused threads */
TmThreadWaitOnThreadInit(); TmThreadWaitOnThreadInit();

@ -38,6 +38,7 @@
#include "runmodes.h" #include "runmodes.h"
#include "util-unittest.h" #include "util-unittest.h"
#include "util-misc.h" #include "util-misc.h"
#include "util-plugin.h"
#include "output.h" #include "output.h"
@ -54,6 +55,8 @@
#include "flow-bypass.h" #include "flow-bypass.h"
#include "counters.h" #include "counters.h"
#include "suricata-plugin.h"
int debuglog_enabled = 0; int debuglog_enabled = 0;
int threading_set_cpu_affinity = FALSE; int threading_set_cpu_affinity = FALSE;
@ -122,6 +125,8 @@ static const char *RunModeTranslateModeToName(int runmode)
#else #else
return "PFRING(DISABLED)"; return "PFRING(DISABLED)";
#endif #endif
case RUNMODE_PLUGIN:
return "PLUGIN";
case RUNMODE_NFQ: case RUNMODE_NFQ:
return "NFQ"; return "NFQ";
case RUNMODE_NFLOG: case RUNMODE_NFLOG:
@ -275,7 +280,8 @@ void RunModeListRunmodes(void)
/** /**
*/ */
void RunModeDispatch(int runmode, const char *custom_mode) void RunModeDispatch(int runmode, const char *custom_mode,
const char *capture_plugin_name, const char *capture_plugin_args)
{ {
char *local_custom_mode = NULL; char *local_custom_mode = NULL;
@ -301,6 +307,15 @@ void RunModeDispatch(int runmode, const char *custom_mode)
custom_mode = RunModeIdsPfringGetDefaultMode(); custom_mode = RunModeIdsPfringGetDefaultMode();
break; break;
#endif #endif
case RUNMODE_PLUGIN: {
SCCapturePlugin *plugin = SCPluginFindCaptureByName(capture_plugin_name);
if (plugin == NULL) {
FatalError(SC_ERR_PLUGIN, "No capture plugin found with name %s",
capture_plugin_name);
}
custom_mode = (const char *)plugin->GetDefaultMode();
break;
}
case RUNMODE_NFQ: case RUNMODE_NFQ:
custom_mode = RunModeIpsNFQGetDefaultMode(); custom_mode = RunModeIpsNFQGetDefaultMode();
break; break;

@ -40,6 +40,7 @@ enum RunModes {
RUNMODE_NAPATECH, RUNMODE_NAPATECH,
RUNMODE_UNIX_SOCKET, RUNMODE_UNIX_SOCKET,
RUNMODE_WINDIVERT, RUNMODE_WINDIVERT,
RUNMODE_PLUGIN,
RUNMODE_USER_MAX, /* Last standard running mode */ RUNMODE_USER_MAX, /* Last standard running mode */
RUNMODE_LIST_KEYWORDS, RUNMODE_LIST_KEYWORDS,
RUNMODE_LIST_APP_LAYERS, RUNMODE_LIST_APP_LAYERS,
@ -77,7 +78,7 @@ char *RunmodeGetActive(void);
const char *RunModeGetMainMode(void); const char *RunModeGetMainMode(void);
void RunModeListRunmodes(void); void RunModeListRunmodes(void);
void RunModeDispatch(int, const char *); void RunModeDispatch(int, const char *, const char *capture_plugin_name, const char *capture_plugin_args);
void RunModeRegisterRunModes(void); void RunModeRegisterRunModes(void);
void RunModeRegisterNewRunMode(enum RunModes, const char *, const char *, void RunModeRegisterNewRunMode(enum RunModes, const char *, const char *,
int (*RunModeFunc)(void)); int (*RunModeFunc)(void));

@ -25,6 +25,12 @@
#include "conf.h" #include "conf.h"
/**
* The size of the data chunk inside each packet structure a plugin
* has for private data (Packet->plugin_v).
*/
#define PLUGIN_VAR_SIZE 64
/** /**
* Structure to define a Suricata plugin. * Structure to define a Suricata plugin.
*/ */
@ -50,4 +56,13 @@ typedef struct SCPluginFileType_ {
bool SCPluginRegisterFileType(SCPluginFileType *); bool SCPluginRegisterFileType(SCPluginFileType *);
typedef struct SCCapturePlugin_ {
char *name;
void (*Init)(const char *args, int plugin_slot, int receive_slot, int decode_slot);
const char *(*GetDefaultMode)(void);
TAILQ_ENTRY(SCCapturePlugin_) entries;
} SCCapturePlugin;
int SCPluginRegisterCapture(SCCapturePlugin *);
#endif /* __SURICATA_PLUGIN_H */ #endif /* __SURICATA_PLUGIN_H */

@ -1202,6 +1202,9 @@ static TmEcode ParseCommandLine(int argc, char** argv, SCInstance *suri)
{"no-random", 0, &g_disable_randomness, 1}, {"no-random", 0, &g_disable_randomness, 1},
{"strict-rule-keywords", optional_argument, 0, 0}, {"strict-rule-keywords", optional_argument, 0, 0},
{"capture-plugin", required_argument, 0, 0},
{"cpature-plugin-args", required_argument, 0, 0},
#ifdef BUILD_UNIX_SOCKET #ifdef BUILD_UNIX_SOCKET
{"unix-socket", optional_argument, 0, 0}, {"unix-socket", optional_argument, 0, 0},
#endif #endif
@ -1293,6 +1296,13 @@ static TmEcode ParseCommandLine(int argc, char** argv, SCInstance *suri)
return TM_ECODE_FAILED; return TM_ECODE_FAILED;
#endif /* HAVE_PFRING */ #endif /* HAVE_PFRING */
} }
else if (strcmp((long_opts[option_index]).name , "capture-plugin") == 0){
suri->run_mode = RUNMODE_PLUGIN;
suri->capture_plugin_name = optarg;
}
else if (strcmp((long_opts[option_index]).name , "capture-plugin-args") == 0){
suri->capture_plugin_args = optarg;
}
else if (strcmp((long_opts[option_index]).name , "af-packet") == 0) else if (strcmp((long_opts[option_index]).name , "af-packet") == 0)
{ {
if (ParseCommandLineAfpacket(suri, optarg) != TM_ECODE_OK) { if (ParseCommandLineAfpacket(suri, optarg) != TM_ECODE_OK) {
@ -2550,7 +2560,7 @@ int PostConfLoadedSetup(SCInstance *suri)
FeatureTrackingRegister(); /* must occur prior to output mod registration */ FeatureTrackingRegister(); /* must occur prior to output mod registration */
RegisterAllModules(); RegisterAllModules();
SCPluginsLoad(); SCPluginsLoad(suri->capture_plugin_name, suri->capture_plugin_args);
AppLayerHtpNeedFileInspection(); AppLayerHtpNeedFileInspection();
@ -2792,7 +2802,8 @@ int SuricataMain(int argc, char **argv)
} }
SCSetStartTime(&suricata); SCSetStartTime(&suricata);
RunModeDispatch(suricata.run_mode, suricata.runmode_custom_mode); RunModeDispatch(suricata.run_mode, suricata.runmode_custom_mode,
suricata.capture_plugin_name, suricata.capture_plugin_args);
if (suricata.run_mode != RUNMODE_UNIX_SOCKET) { if (suricata.run_mode != RUNMODE_UNIX_SOCKET) {
UnixManagerThreadSpawnNonRunmode(); UnixManagerThreadSpawnNonRunmode();
} }

@ -158,6 +158,9 @@ typedef struct SCInstance_ {
const char *progname; /**< pointer to argv[0] */ const char *progname; /**< pointer to argv[0] */
const char *conf_filename; const char *conf_filename;
char *strict_rule_parsing_string; char *strict_rule_parsing_string;
const char *capture_plugin_name;
const char *capture_plugin_args;
} SCInstance; } SCInstance;

@ -213,6 +213,8 @@ const char * TmModuleTmmIdToString(TmmId id)
CASE_CODE (TMM_DECODEPCAPFILE); CASE_CODE (TMM_DECODEPCAPFILE);
CASE_CODE (TMM_RECEIVEPFRING); CASE_CODE (TMM_RECEIVEPFRING);
CASE_CODE (TMM_DECODEPFRING); CASE_CODE (TMM_DECODEPFRING);
CASE_CODE (TMM_RECEIVEPLUGIN);
CASE_CODE (TMM_DECODEPLUGIN);
CASE_CODE (TMM_RESPONDREJECT); CASE_CODE (TMM_RESPONDREJECT);
CASE_CODE (TMM_DECODEIPFW); CASE_CODE (TMM_DECODEIPFW);
CASE_CODE (TMM_VERDICTIPFW); CASE_CODE (TMM_VERDICTIPFW);

@ -41,6 +41,8 @@ typedef enum {
TMM_DECODEPCAPFILE, TMM_DECODEPCAPFILE,
TMM_RECEIVEPFRING, TMM_RECEIVEPFRING,
TMM_DECODEPFRING, TMM_DECODEPFRING,
TMM_RECEIVEPLUGIN,
TMM_DECODEPLUGIN,
TMM_RESPONDREJECT, TMM_RESPONDREJECT,
TMM_DECODEIPFW, TMM_DECODEIPFW,
TMM_VERDICTIPFW, TMM_VERDICTIPFW,

@ -26,6 +26,8 @@
static TAILQ_HEAD(, SCPluginFileType_) output_types = static TAILQ_HEAD(, SCPluginFileType_) output_types =
TAILQ_HEAD_INITIALIZER(output_types); TAILQ_HEAD_INITIALIZER(output_types);
static TAILQ_HEAD(, SCCapturePlugin_) capture_plugins = TAILQ_HEAD_INITIALIZER(capture_plugins);
static void InitPlugin(char *path) static void InitPlugin(char *path)
{ {
void *lib = dlopen(path, RTLD_NOW); void *lib = dlopen(path, RTLD_NOW);
@ -48,7 +50,7 @@ static void InitPlugin(char *path)
} }
} }
void SCPluginsLoad(void) void SCPluginsLoad(const char *capture_plugin_name, const char *capture_plugin_args)
{ {
ConfNode *conf = ConfGetNode("plugins"); ConfNode *conf = ConfGetNode("plugins");
if (conf == NULL) { if (conf == NULL) {
@ -82,6 +84,16 @@ void SCPluginsLoad(void)
InitPlugin(plugin->val); InitPlugin(plugin->val);
} }
} }
if (run_mode == RUNMODE_PLUGIN) {
SCCapturePlugin *capture = SCPluginFindCaptureByName(capture_plugin_name);
if (capture == NULL) {
FatalError(SC_ERR_PLUGIN, "No capture plugin found with name %s",
capture_plugin_name);
}
capture->Init(capture_plugin_args, RUNMODE_PLUGIN, TMM_RECEIVEPLUGIN,
TMM_DECODEPLUGIN);
}
} }
/** /**
@ -139,6 +151,24 @@ SCPluginFileType *SCPluginFindFileType(const char *name)
return NULL; return NULL;
} }
int SCPluginRegisterCapture(SCCapturePlugin *plugin)
{
TAILQ_INSERT_TAIL(&capture_plugins, plugin, entries);
SCLogNotice("Capture plugin registered: %s", plugin->name);
return 0;
}
SCCapturePlugin *SCPluginFindCaptureByName(const char *name)
{
SCCapturePlugin *plugin = NULL;
TAILQ_FOREACH(plugin, &capture_plugins, entries) {
if (strcmp(name, plugin->name) == 0) {
return plugin;
}
}
return plugin;
}
#else #else
void PluginsLoad(void) void PluginsLoad(void)

@ -20,7 +20,8 @@
#include "suricata-plugin.h" #include "suricata-plugin.h"
void SCPluginsLoad(void); void SCPluginsLoad(const char *capture_plugin_name, const char *capture_plugin_args);
SCPluginFileType *SCPluginFindFileType(const char *name); SCPluginFileType *SCPluginFindFileType(const char *name);
SCCapturePlugin *SCPluginFindCaptureByName(const char *name);
#endif /* __UTIL_PLUGIN_H__ */ #endif /* __UTIL_PLUGIN_H__ */

Loading…
Cancel
Save