]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
plugins: support for capture plugins
authorJason Ish <jason.ish@oisf.net>
Sat, 4 Jul 2020 06:33:08 +0000 (00:33 -0600)
committerVictor Julien <victor@inliniac.net>
Thu, 6 Aug 2020 15:15:10 +0000 (17:15 +0200)
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.

src/decode.h
src/runmode-unix-socket.c
src/runmodes.c
src/runmodes.h
src/suricata-plugin.h
src/suricata.c
src/suricata.h
src/tm-modules.c
src/tm-threads-common.h
src/util-plugin.c
src/util-plugin.h

index 0424b487b7db56690f630a9c325ec6c8ca50e030..9e868dcc35eb38cbf9eb3dfc31a01f16cf17fdbb 100644 (file)
@@ -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;
     };
index 656ebc1474405a9f6ce7d06e67f8e6d032b35542..f4bbe1e659155df9379606d70fabe97046a0cb87 100644 (file)
@@ -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();
index 688a2496fcf88c1ee4e6724a960513438762e7fc..b64f1d4e96937aee9e09ab744f9b39076e4b56af 100644 (file)
@@ -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;
index b4370790093377eaa9ea7a5f2173e8ef85d9ca59..63b75d2bd60a85f6d68f0f658b4da87d1fa6f48b 100644 (file)
@@ -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));
index 233c5d82e17ac2e79bad22cfe409d545199aa1e5..c399640da4693a3cb8dbebc81293689664eb7b15 100644 (file)
 
 #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 */
index 6c96302e03febd201630cd9a0d924c39faf31b26..372c82a40238b4afcbbcb7901229da5ae4ba1d43 100644 (file)
@@ -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();
     }
index 7bd87a0e16a1f9fdbd199b693fdcf8198db87f9a..43bb8ab0c525b58d9bb2449a1ad87d3f2e79c320 100644 (file)
@@ -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;
 
 
index 9f0ec6e7df51b66aba620dd3ba56b9ed624928d6..5d0f59d1afcfb6ac9cd8d3a894c1800d9e284e0f 100644 (file)
@@ -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);
index 665d52135c8364af9d5612e95fb05161bff9bd6f..be8c103c9733848b0082bf17da5881dcd7d6c281 100644 (file)
@@ -41,6 +41,8 @@ typedef enum {
     TMM_DECODEPCAPFILE,
     TMM_RECEIVEPFRING,
     TMM_DECODEPFRING,
+    TMM_RECEIVEPLUGIN,
+    TMM_DECODEPLUGIN,
     TMM_RESPONDREJECT,
     TMM_DECODEIPFW,
     TMM_VERDICTIPFW,
index a4c6501eace9222a97df7863904f75f60320adfd..87748816011941706c24983f0224894f798a22da 100644 (file)
@@ -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)
index 55c21e911f3213a2a84848342e3664101267a199..f15821f532507cc313cd61569cca36be116a4c44 100644 (file)
@@ -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__ */