From 30bd2a27ff2680674d6f57e6b9d7f6c1b3b742f1 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Fri, 11 Oct 2024 11:48:50 -0600 Subject: [PATCH] threads: add initialization callbacks For library users and plugins that need to hook into the thread life cycle, perhaps to initialize some thread storage. --- src/Makefile.am | 2 ++ src/thread-callbacks.c | 55 ++++++++++++++++++++++++++++++++++++++++++ src/thread-callbacks.h | 54 +++++++++++++++++++++++++++++++++++++++++ src/tm-threads.c | 3 +++ 4 files changed, 114 insertions(+) create mode 100644 src/thread-callbacks.c create mode 100644 src/thread-callbacks.h diff --git a/src/Makefile.am b/src/Makefile.am index 6032c1962d..aaca859654 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -438,6 +438,7 @@ noinst_HEADERS = \ suricata-common.h \ suricata.h \ suricata-plugin.h \ + thread-callbacks.h \ thread-storage.h \ threads-debug.h \ threads.h \ @@ -991,6 +992,7 @@ libsuricata_c_a_SOURCES = \ stream-tcp-sack.c \ stream-tcp-util.c \ suricata.c \ + thread-callbacks.c \ thread-storage.c \ threads.c \ tm-modules.c \ diff --git a/src/thread-callbacks.c b/src/thread-callbacks.c new file mode 100644 index 0000000000..ede35d7107 --- /dev/null +++ b/src/thread-callbacks.c @@ -0,0 +1,55 @@ +/* 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 "thread-callbacks.h" + +typedef struct ThreadInitCallback_ { + SCThreadInitCallbackFn Callback; + void *user; + struct ThreadInitCallback_ *next; +} ThreadInitCallback; + +static ThreadInitCallback *init_callbacks = NULL; + +bool SCThreadRegisterInitCallback(SCThreadInitCallbackFn fn, void *user) +{ + ThreadInitCallback *cb = SCCalloc(1, sizeof(*cb)); + if (cb == NULL) { + return false; + } + cb->Callback = fn; + cb->user = user; + if (init_callbacks == NULL) { + init_callbacks = cb; + } else { + ThreadInitCallback *current = init_callbacks; + while (current->next != NULL) { + current = current->next; + } + current->next = cb; + } + return true; +} + +void SCThreadRunInitCallbacks(ThreadVars *tv) +{ + ThreadInitCallback *cb = init_callbacks; + while (cb != NULL) { + cb->Callback(tv, cb->user); + cb = cb->next; + } +} diff --git a/src/thread-callbacks.h b/src/thread-callbacks.h new file mode 100644 index 0000000000..5bcd638bf8 --- /dev/null +++ b/src/thread-callbacks.h @@ -0,0 +1,54 @@ +/* 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_THREAD_CALLBACKS_H +#define SURICATA_THREAD_CALLBACKS_H + +#include "suricata-common.h" +#include "threadvars.h" + +/** \brief Function type for thread intialization callbacks. + * + * Once registered by SCThreadRegisterInitCallback, this function will + * be called for every thread being initialized during Suricata + * startup. + * + * \param tv The ThreadVars struct that has just been initialized. + * \param user The user data provided when registering the callback. + */ +typedef void (*SCThreadInitCallbackFn)(ThreadVars *tv, void *user); + +/** \brief Register a thread init callback. + * + * Register a user provided function to be called every time a thread is + * initialized for use. + * + * \param fn Pointer to function to be called + * \param user Additional user data to be passed to callback + * + * \returns true if callback was registered, otherwise false if the + * callback could not be registered due to memory allocation error. + */ +bool SCThreadRegisterInitCallback(SCThreadInitCallbackFn fn, void *user); + +/** \internal + * + * Run all registered flow init callbacks. + */ +void SCThreadRunInitCallbacks(ThreadVars *tv); + +#endif /* SURICATA_THREAD_CALLBACKS_H */ diff --git a/src/tm-threads.c b/src/tm-threads.c index c65995ad35..07f9a9390d 100644 --- a/src/tm-threads.c +++ b/src/tm-threads.c @@ -29,6 +29,7 @@ #include "suricata.h" #include "stream.h" #include "runmodes.h" +#include "thread-callbacks.h" #include "threadvars.h" #include "thread-storage.h" #include "tm-queues.h" @@ -1012,6 +1013,8 @@ ThreadVars *TmThreadCreate(const char *name, const char *inq_name, const char *i if (mucond != 0) TmThreadInitMC(tv); + SCThreadRunInitCallbacks(tv); + return tv; error: -- 2.47.2