Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[draft] flow callbacks for ndpi - v1 #11935

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2293,6 +2293,19 @@ fi
])
AC_SUBST(RUST_FEATURES)

# nDPI support (no library checks for this stub)
AC_ARG_ENABLE(ndpi,
AS_HELP_STRING([--enable-ndpi], [Enable nDPI support]),
[enable_ndpi=$enableval],[enable_ndpi=no])
if test "x$enable_ndpi" = "xyes"; then
AM_CONDITIONAL([BUILD_NDPI], [true])
ndpi_comment=""
else
AM_CONDITIONAL([BUILD_NDPI], [false])
ndpi_comment="#"
fi
AC_SUBST([ndpi_comment])

AC_ARG_ENABLE(warnings,
AS_HELP_STRING([--enable-warnings], [Enable supported C compiler warnings]),[enable_warnings=$enableval],[enable_warnings=no])
AS_IF([test "x$enable_warnings" = "xyes"], [
Expand Down Expand Up @@ -2513,6 +2526,7 @@ AC_CONFIG_FILES(examples/plugins/ci-capture/Makefile)
AC_CONFIG_FILES(examples/lib/simple/Makefile examples/lib/simple/Makefile.example)
AC_CONFIG_FILES(plugins/Makefile)
AC_CONFIG_FILES(plugins/pfring/Makefile)
AC_CONFIG_FILES(plugins/ndpi-dummy/Makefile)

AC_OUTPUT

Expand Down
4 changes: 4 additions & 0 deletions plugins/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@ SUBDIRS =
if BUILD_PFRING
SUBDIRS += pfring
endif

if BUILD_NDPI
SUBDIRS += ndpi-dummy
endif
8 changes: 8 additions & 0 deletions plugins/ndpi-dummy/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pkglib_LTLIBRARIES = ndpi.la

ndpi_la_LDFLAGS = -module -avoid-version -shared

ndpi_la_SOURCES = ndpi.c

install-exec-hook:
cd $(DESTDIR)$(pkglibdir) && $(RM) $(pkglib_LTLIBRARIES)
84 changes: 84 additions & 0 deletions plugins/ndpi-dummy/ndpi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/* Copyright (C) 2024 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.
*/

/* License note: While this "glue" code to the nDPI library is GPLv2,
* nDPI is itself LGPLv3 which is known to be incompatible with the
* GPLv2. */

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

#include "flow-callbacks.h"
#include "flow-storage.h"

static FlowStorageId flow_storage_id = { .id = -1 };

static void *FlowStorageAlloc(unsigned int size)
{
SCLogNotice("Allocating nDPI flow storage, size=%d", size);
return NULL;
}

static void FlowStorageFree(void *ptr)
{
SCLogNotice("De-allocating nDPI flow storage");
int *dummy_storage = ptr;
SCLogNotice("%d", *dummy_storage);
SCFree(ptr);
}

static void OnFlowInit(Flow *f, const Packet *p)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I'd expect a OnFlowDestruct too, although perhaps we don't need it directly here, as the FlowStorage API knowns how to destroy the user data.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, for completeness should probably add it. Not needed for storage cleanup using the storage API, and someone else uses the flow event for their private cleanup, but it does feel missing.

{
SCLogNotice("...");
static int counter = 0;
int *dummy_storage = SCCalloc(1, sizeof(int));
*dummy_storage = counter++;
FlowSetStorageById(f, flow_storage_id, dummy_storage);
}

static void OnFlowUpdate(Flow *f, Packet *p, ThreadVars *tv)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should there be user data here as well? general user data? Perhaps not needed for ndpi

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess more for the library, but if someone wanted to create a simple flow logger, they'd want to pass a file pointer around these callbacks to log a new flow creation, or a flow destruction, etc.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably should have user data, was being short sighted and only looking at the case at hand which doesn't need it.

{
SCLogNotice("...");
int *dummy_storage = FlowGetStorageById(f, flow_storage_id);
SCLogNotice("dummy_storage=%d", *dummy_storage);
}

static void NdpiInit(void)
{
SCLogNotice("Initializing nDPI plugin");

flow_storage_id = FlowStorageRegister("ndpi", sizeof(void *), NULL, FlowStorageFree);
if (flow_storage_id.id < 0) {
FatalError("Failed to register nDPI flow storage");
}

SCFlowRegisterInitCallback(OnFlowInit);
SCFlowRegisterUpdateCallback(OnFlowUpdate);
}

const SCPlugin PluginRegistration = {
.name = "ndpi-dummy",
.author = "FirstName LastName",
.license = "GPLv2",
.Init = NdpiInit,
};

const SCPlugin *SCPluginRegister()
{
return &PluginRegistration;
}
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ noinst_HEADERS = \
feature.h \
flow-bit.h \
flow-bypass.h \
flow-callbacks.h \
flow.h \
flow-hash.h \
flow-manager.h \
Expand Down Expand Up @@ -902,6 +903,7 @@ libsuricata_c_a_SOURCES = \
feature.c \
flow-bit.c \
flow-bypass.c \
flow-callbacks.c \
flow.c \
flow-hash.c \
flow-manager.c \
Expand Down
88 changes: 88 additions & 0 deletions src/flow-callbacks.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/* Copyright (C) 2024 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 "flow-callbacks.h"

typedef struct FlowInitCallback_ {
SCFlowInitCallbackFn fn;
struct FlowInitCallback_ *next;
} FlowInitCallback;

static FlowInitCallback *init_callbacks = NULL;

typedef struct FlowUpdateCallback_ {
SCFlowUpdateCallbackFn fn;
struct FlowUpdateCallback_ *next;
} FlowUpdateCallback;

static FlowUpdateCallback *update_callbacks = NULL;

bool SCFlowRegisterInitCallback(SCFlowInitCallbackFn fn)
{
FlowInitCallback *cb = SCCalloc(1, sizeof(*cb));
if (cb == NULL) {
return false;
}
cb->fn = fn;
if (init_callbacks == NULL) {
init_callbacks = cb;
} else {
FlowInitCallback *current = init_callbacks;
while (current->next != NULL) {
current = current->next;
}
current->next = cb;
}
return true;
}

void SCFlowRunInitCallbacks(Flow *f, const Packet *p)
{
FlowInitCallback *cb = init_callbacks;
while (cb != NULL) {
cb->fn(f, p);
cb = cb->next;
}
}

bool SCFlowRegisterUpdateCallback(SCFlowUpdateCallbackFn fn)
{
FlowUpdateCallback *cb = SCCalloc(1, sizeof(*cb));
if (cb == NULL) {
return false;
}
cb->fn = fn;
if (update_callbacks == NULL) {
update_callbacks = cb;
} else {
FlowUpdateCallback *current = update_callbacks;
while (current->next != NULL) {
current = current->next;
}
current->next = cb;
}
return true;
}

void SCFlowRunUpdateCallbacks(Flow *f, Packet *p, ThreadVars *tv)
{
FlowUpdateCallback *cb = update_callbacks;
while (cb != NULL) {
cb->fn(f, p, tv);
cb = cb->next;
}
}
60 changes: 60 additions & 0 deletions src/flow-callbacks.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/* Copyright (C) 2024 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.
*/

#ifndef SURICATA_FLOW_CALLBACKS_H
#define SURICATA_FLOW_CALLBACKS_H

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

typedef void (*SCFlowInitCallbackFn)(Flow *f, const Packet *p);

/** \brief Register a flow init callback.
*
* Register a user provided function to be called every time a flow is
* initialized for use.
*
* \returns true if callback was registered, otherwise false if the
* callback could not be registered due to memory allocation error.
*/
bool SCFlowRegisterInitCallback(SCFlowInitCallbackFn fn);

/** \internal
*
* Run all registered flow init callbacks.
*/
void SCFlowRunInitCallbacks(Flow *f, const Packet *p);

typedef void (*SCFlowUpdateCallbackFn)(Flow *f, Packet *p, ThreadVars *tv);

/** \brief Register a flow update callback.
*
* Register a user provided function to be called everytime a flow is
* updated.
*
* \returns true if callback was registered, otherwise false if the
* callback could not be registered due to memory allocation error.
*/
bool SCFlowRegisterUpdateCallback(SCFlowUpdateCallbackFn fn);

/** \internal
*
* Run all registered flow update callbacks.
*/
void SCFlowRunUpdateCallbacks(Flow *f, Packet *p, ThreadVars *tv);

#endif /* SURICATA_FLOW_CALLBACKS_H */
3 changes: 3 additions & 0 deletions src/flow-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "flow.h"
#include "flow-private.h"
#include "flow-util.h"
#include "flow-callbacks.h"
#include "flow-var.h"
#include "app-layer.h"

Expand Down Expand Up @@ -203,6 +204,8 @@ void FlowInit(Flow *f, const Packet *p)
FlowSetStorageById(f, MacSetGetFlowStorageID(), ms);
}

SCFlowRunInitCallbacks(f, p);

SCReturn;
}

Expand Down
3 changes: 3 additions & 0 deletions src/flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "flow-storage.h"
#include "flow-bypass.h"
#include "flow-spare-pool.h"
#include "flow-callbacks.h"

#include "stream-tcp-private.h"

Expand Down Expand Up @@ -503,6 +504,8 @@ void FlowHandlePacketUpdate(Flow *f, Packet *p, ThreadVars *tv, DecodeThreadVars
SCLogDebug("setting FLOW_NOPAYLOAD_INSPECTION flag on flow %p", f);
DecodeSetNoPayloadInspectionFlag(p);
}

SCFlowRunUpdateCallbacks(f, p, tv);
}

/** \brief Entry point for packet flow handling
Expand Down
1 change: 1 addition & 0 deletions suricata.yaml.in
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ stats:
# Plugins -- Experimental -- specify the filename for each plugin shared object
plugins:
@pfring_comment@- @prefix@/lib/@PACKAGE_NAME@/pfring.so
@ndpi_comment@- @prefix@/lib/@PACKAGE_NAME@/ndpi.so
# - /path/to/plugin.so

# Configure the type of alert (and other) logging you would like.
Expand Down
Loading