Skip to content

Commit

Permalink
plugins: add example low level flow logging pluging
Browse files Browse the repository at this point in the history
This is an example what adding plugin examples to the Suricata repo
could look like.

This plugin is integrated in with autoconf/automake. A standalone
Makefile should be provided, perhaps with a cmake example as well.

Note that the examples directory was added as EXTRA_DIST as we don't
want normal builds to recurse into it and attempt to build the plugin,
its just an example.
  • Loading branch information
jasonish committed Sep 19, 2023
1 parent aa98631 commit 16492f2
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 1 deletion.
3 changes: 2 additions & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ EXTRA_DIST = ChangeLog COPYING LICENSE suricata.yaml.in \
$(SURICATA_UPDATE_DIR) \
lua \
acsite.m4 \
scripts/generate-images.sh
scripts/generate-images.sh \
examples
SUBDIRS = $(HTP_DIR) rust src qa rules doc contrib etc python ebpf \
$(SURICATA_UPDATE_DIR)

Expand Down
2 changes: 2 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2612,6 +2612,8 @@ AC_CONFIG_FILES(suricata.yaml etc/Makefile etc/suricata.logrotate etc/suricata.s
AC_CONFIG_FILES(python/Makefile python/suricata/config/defaults.py)
AC_CONFIG_FILES(ebpf/Makefile)
AC_CONFIG_FILES(libsuricata-config)
AC_CONFIG_FILES(examples/plugins/c-flow-logger/Makefile)

AC_OUTPUT

SURICATA_BUILD_CONF="Suricata Configuration:
Expand Down
17 changes: 17 additions & 0 deletions examples/plugins/c-flow-logger/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
plugindir = ${libdir}/suricata/plugins

if BUILD_SHARED_LIBRARY
plugin_LTLIBRARIES = flowlogger.la
flowlogger_la_LDFLAGS = -module -shared
flowlogger_la_SOURCES = flowlogger.c

flowlogger_la_CPPFLAGS = -I$(abs_top_srcdir)/rust/gen -I$(abs_top_srcdir)/rust/dist

else

all-local:
@echo
@echo "Shared library support must be enabled to build plugins."
@echo

endif
26 changes: 26 additions & 0 deletions examples/plugins/c-flow-logger/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Example Flow Logging Plugin

This is an example of a low level flow logging plugin for Suricata
8.0.

## Building

In in the Suricata source code and you did not use the
`--disable-shared` `./configure` option, you should be able to just
run `make` to build the plugin.

Note that due to Automake and friends, the plugin will be compiled to
`.libs/flowlogger.so.0.0.0`.

### Standalone Building

The file `Makefile.example` is an example of how you might build a
plugin that is distributed separately from the Suricata source code.
It has the following dependencies:

- Suricata is installed
- The Suricata library is installed: `make install-library`
- The Suricata development headers are installed: `make install-headers`
- The program `libsuricata-config` is in your path (installed with `make install-library`)

Then run: `make -f Makefile.example`
83 changes: 83 additions & 0 deletions examples/plugins/c-flow-logger/flowlogger.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/* Copyright (C) 2023 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* 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
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/

#include "suricata-common.h"
#include "suricata-plugin.h"

#include "output-flow.h"
#include "util-print.h"

static TmEcode ThreadInit(ThreadVars *tv, const void *initdata, void **data)
{
return TM_ECODE_OK;
}

static TmEcode ThreadDeinit(ThreadVars *tv, void *data)
{
// Nothing to do. If we allocated data in ThreadInit we would free
// it here.
return TM_ECODE_OK;
}

static int FlowLogger(ThreadVars *tv, void *thread_data, Flow *f)
{
char src_ip[46] = { 0 }, dst_ip[46] = { 0 };
Port sp, dp;

if ((f->flags & FLOW_DIR_REVERSED) == 0) {
if (FLOW_IS_IPV4(f)) {
PrintInet(AF_INET, (const void *)&(f->src.addr_data32[0]), src_ip, sizeof(src_ip));
PrintInet(AF_INET, (const void *)&(f->dst.addr_data32[0]), dst_ip, sizeof(dst_ip));
} else if (FLOW_IS_IPV6(f)) {
PrintInet(AF_INET6, (const void *)&(f->src.address), src_ip, sizeof(src_ip));
PrintInet(AF_INET6, (const void *)&(f->dst.address), dst_ip, sizeof(dst_ip));
}
sp = f->sp;
dp = f->dp;
} else {
if (FLOW_IS_IPV4(f)) {
PrintInet(AF_INET, (const void *)&(f->dst.addr_data32[0]), src_ip, sizeof(src_ip));
PrintInet(AF_INET, (const void *)&(f->src.addr_data32[0]), dst_ip, sizeof(dst_ip));
} else if (FLOW_IS_IPV6(f)) {
PrintInet(AF_INET6, (const void *)&(f->dst.address), src_ip, sizeof(src_ip));
PrintInet(AF_INET6, (const void *)&(f->src.address), dst_ip, sizeof(dst_ip));
}
sp = f->dp;
dp = f->sp;
}

SCLogNotice("Flow: %s:%u -> %s:%u", src_ip, sp, dst_ip, dp);

return 0;
}

static void Init(void)
{
SCOutputRegisterFlowLogger("custom-flow-logger", FlowLogger, NULL, ThreadInit, ThreadDeinit);
}

const SCPlugin PluginRegistration = {
.name = "FlowLogger",
.author = "Jason Ish",
.license = "GPLv2",
.Init = Init,
};

static const SCPlugin *SCPluginRegister(void)
{
return &PluginRegistration;
}

0 comments on commit 16492f2

Please sign in to comment.