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
#include "suricata-common.h"
#include "suricata-plugin.h"
#include "threadvars.h"
#include "util-debug.h"
#include "decode-events.h"
@ -479,6 +480,9 @@ typedef struct Packet_
WinDivertPacketVars windivert_v;
#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 */
PcapPacketVars pcap_v;
};

@ -573,7 +573,7 @@ static TmEcode UnixSocketPcapFilesCheck(void *data)
PreRunInit(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 */
TmThreadWaitOnThreadInit();

@ -38,6 +38,7 @@
#include "runmodes.h"
#include "util-unittest.h"
#include "util-misc.h"
#include "util-plugin.h"
#include "output.h"
@ -54,6 +55,8 @@
#include "flow-bypass.h"
#include "counters.h"
#include "suricata-plugin.h"
int debuglog_enabled = 0;
int threading_set_cpu_affinity = FALSE;
@ -122,6 +125,8 @@ static const char *RunModeTranslateModeToName(int runmode)
#else
return "PFRING(DISABLED)";
#endif
case RUNMODE_PLUGIN:
return "PLUGIN";
case RUNMODE_NFQ:
return "NFQ";
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;
@ -301,6 +307,15 @@ void RunModeDispatch(int runmode, const char *custom_mode)
custom_mode = RunModeIdsPfringGetDefaultMode();
break;
#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:
custom_mode = RunModeIpsNFQGetDefaultMode();
break;

@ -40,6 +40,7 @@ enum RunModes {
RUNMODE_NAPATECH,
RUNMODE_UNIX_SOCKET,
RUNMODE_WINDIVERT,
RUNMODE_PLUGIN,
RUNMODE_USER_MAX, /* Last standard running mode */
RUNMODE_LIST_KEYWORDS,
RUNMODE_LIST_APP_LAYERS,
@ -77,7 +78,7 @@ char *RunmodeGetActive(void);
const char *RunModeGetMainMode(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 RunModeRegisterNewRunMode(enum RunModes, const char *, const char *,
int (*RunModeFunc)(void));

@ -25,6 +25,12 @@
#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.
*/
@ -50,4 +56,13 @@ typedef struct 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 */

@ -1202,6 +1202,9 @@ static TmEcode ParseCommandLine(int argc, char** argv, SCInstance *suri)
{"no-random", 0, &g_disable_randomness, 1},
{"strict-rule-keywords", optional_argument, 0, 0},
{"capture-plugin", required_argument, 0, 0},
{"cpature-plugin-args", required_argument, 0, 0},
#ifdef BUILD_UNIX_SOCKET
{"unix-socket", optional_argument, 0, 0},
#endif
@ -1293,6 +1296,13 @@ static TmEcode ParseCommandLine(int argc, char** argv, SCInstance *suri)
return TM_ECODE_FAILED;
#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)
{
if (ParseCommandLineAfpacket(suri, optarg) != TM_ECODE_OK) {
@ -2550,7 +2560,7 @@ int PostConfLoadedSetup(SCInstance *suri)
FeatureTrackingRegister(); /* must occur prior to output mod registration */
RegisterAllModules();
SCPluginsLoad();
SCPluginsLoad(suri->capture_plugin_name, suri->capture_plugin_args);
AppLayerHtpNeedFileInspection();
@ -2792,7 +2802,8 @@ int SuricataMain(int argc, char **argv)
}
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) {
UnixManagerThreadSpawnNonRunmode();
}

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

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

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

@ -26,6 +26,8 @@
static TAILQ_HEAD(, SCPluginFileType_) output_types =
TAILQ_HEAD_INITIALIZER(output_types);
static TAILQ_HEAD(, SCCapturePlugin_) capture_plugins = TAILQ_HEAD_INITIALIZER(capture_plugins);
static void InitPlugin(char *path)
{
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");
if (conf == NULL) {
@ -82,6 +84,16 @@ void SCPluginsLoad(void)
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;
}
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
void PluginsLoad(void)

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

Loading…
Cancel
Save