From: Jason Ish Date: Wed, 10 Apr 2024 16:58:56 +0000 (-0600) Subject: examples: rename lib capture example to custom X-Git-Tag: suricata-8.0.0-beta1~150 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4b715a84cfa44d5f724a236388c0cdfedca9c7e2;p=thirdparty%2Fsuricata.git examples: rename lib capture example to custom To keep the simple example simple, move the lib based capture method example to its own example. Ticket: #7240 --- diff --git a/Makefile.am b/Makefile.am index 48f1629127..348ef59ba0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -14,7 +14,7 @@ EXTRA_DIST = ChangeLog COPYING LICENSE suricata.yaml.in \ examples/plugins SUBDIRS = $(HTP_DIR) rust src plugins qa rules doc etc python ebpf \ $(SURICATA_UPDATE_DIR) -DIST_SUBDIRS = $(SUBDIRS) examples/lib/simple +DIST_SUBDIRS = $(SUBDIRS) examples/lib/simple examples/lib/custom CLEANFILES = stamp-h[0-9]* diff --git a/configure.ac b/configure.ac index 3a69421c0f..2a6c92007f 100644 --- a/configure.ac +++ b/configure.ac @@ -2600,6 +2600,7 @@ AC_CONFIG_FILES(examples/plugins/c-json-filetype/Makefile) AC_CONFIG_FILES(examples/plugins/c-custom-loggers/Makefile) AC_CONFIG_FILES(examples/plugins/ci-capture/Makefile) AC_CONFIG_FILES(examples/lib/simple/Makefile examples/lib/simple/Makefile.example) +AC_CONFIG_FILES(examples/lib/custom/Makefile examples/lib/custom/Makefile.example) AC_CONFIG_FILES(plugins/Makefile) AC_CONFIG_FILES(plugins/pfring/Makefile) AC_CONFIG_FILES(plugins/napatech/Makefile) diff --git a/examples/lib/custom/.gitignore b/examples/lib/custom/.gitignore new file mode 100644 index 0000000000..579841d2a5 --- /dev/null +++ b/examples/lib/custom/.gitignore @@ -0,0 +1,2 @@ +!/Makefile.example.in +Makefile.example diff --git a/examples/lib/custom/Makefile.am b/examples/lib/custom/Makefile.am new file mode 100644 index 0000000000..fc9899dade --- /dev/null +++ b/examples/lib/custom/Makefile.am @@ -0,0 +1,12 @@ +bin_PROGRAMS = custom + +custom_SOURCES = main.c + +AM_CPPFLAGS = -I$(top_srcdir)/src + +custom_LDFLAGS = $(all_libraries) $(SECLDFLAGS) +custom_LDADD = "-Wl,--start-group,$(top_builddir)/src/libsuricata_c.a,../../$(RUST_SURICATA_LIB),--end-group" $(RUST_LDADD) +if HTP_LDADD +custom_LDADD += ../../$(HTP_LDADD) +endif +custom_DEPENDENCIES = $(top_builddir)/src/libsuricata_c.a ../../$(RUST_SURICATA_LIB) diff --git a/examples/lib/custom/Makefile.example.in b/examples/lib/custom/Makefile.example.in new file mode 100644 index 0000000000..d41a9c9f5b --- /dev/null +++ b/examples/lib/custom/Makefile.example.in @@ -0,0 +1,16 @@ +LIBSURICATA_CONFIG ?= @CONFIGURE_PREFIX@/bin/libsuricata-config + +SURICATA_LIBS = `$(LIBSURICATA_CONFIG) --libs --static` +SURICATA_CFLAGS := `$(LIBSURICATA_CONFIG) --cflags` + +# Currently the Suricata logging system requires this to be even for +# plugins. +CPPFLAGS += "-D__SCFILENAME__=\"$(*F)\"" + +all: custom + +custom: main.c + $(CC) -o $@ $^ $(CPPFLAGS) $(CFLAGS) $(SURICATA_CFLAGS) $(SURICATA_LIBS) + +clean: + rm -f custom diff --git a/examples/lib/custom/README.md b/examples/lib/custom/README.md new file mode 100644 index 0000000000..2497ee9c25 --- /dev/null +++ b/examples/lib/custom/README.md @@ -0,0 +1,39 @@ +# Custom Library Example + +This is an example of using the Suriata library with your own packets +and threads. + +## Building In Tree + +The Suricata build system has created a Makefile that should allow you +to build this application in-tree on most supported platforms. To +build simply run: + +``` +make +``` + +## Building Out of Tree + +A Makefile.example has also been generated to use as an example on how +to build against the library in a standalone application. + +First build and install the Suricata library including: + +``` +make install-library +make install-headers +``` + +Then run: + +``` +make -f Makefile.example +``` + +If you installed to a non-standard location, you need to ensure that +`libsuricata-config` is in your path, for example: + +``` +PATH=/opt/suricata/bin:$PATH make -f Makefile.example +``` diff --git a/examples/lib/custom/main.c b/examples/lib/custom/main.c new file mode 100644 index 0000000000..7e6900e5f4 --- /dev/null +++ b/examples/lib/custom/main.c @@ -0,0 +1,125 @@ +/* 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 "suricata.h" +#include "conf.h" +#include "pcap.h" +#include "runmode-lib.h" +#include "source-lib.h" +#include "threadvars.h" + +/* Suricata worker thread in library mode. + The functions should be wrapped in an API layer. */ +static void *SimpleWorker(void *arg) +{ + char *pcap_file = (char *)arg; + + /* Create worker. */ + ThreadVars *tv = RunModeCreateWorker(); + if (!tv) { + pthread_exit(NULL); + } + + /* Start worker. */ + if (RunModeSpawnWorker(tv) != 0) { + pthread_exit(NULL); + } + + /* Replay pcap. */ + pcap_t *fp = pcap_open_offline(pcap_file, NULL); + if (fp == NULL) { + pthread_exit(NULL); + } + + int datalink = pcap_datalink(fp); + struct pcap_pkthdr pkthdr; + const u_char *packet; + while ((packet = pcap_next(fp, &pkthdr)) != NULL) { + if (TmModuleLibHandlePacket(tv, packet, datalink, pkthdr.ts, pkthdr.len, 0, 0, NULL) != 0) { + pthread_exit(NULL); + } + } + pcap_close(fp); + + /* Cleanup. */ + RunModeDestroyWorker(tv); + pthread_exit(NULL); +} + +int main(int argc, char **argv) +{ + SuricataPreInit(argv[0]); + + /* Parse command line options. This is optional, you could + * directly configure Suricata through the Conf API. + The last argument is the PCAP file to replay. */ + SCParseCommandLine(argc - 1, argv); + + /* Set lib runmode. There is currently no way to set it via + the Conf API. */ + SuricataSetLibRunmode(); + + /* Validate/finalize the runmode. */ + if (SCFinalizeRunMode() != TM_ECODE_OK) { + exit(EXIT_FAILURE); + } + + /* Handle internal runmodes. Typically you wouldn't do this as a + * library user, however this example is showing how to replicate + * the Suricata application with the library. */ + switch (SCStartInternalRunMode(argc, argv)) { + case TM_ECODE_DONE: + exit(EXIT_SUCCESS); + case TM_ECODE_FAILED: + exit(EXIT_FAILURE); + } + + /* Load configuration file, could be done earlier but must be done + * before SuricataInit, but even then its still optional as you + * may be programmatically configuration Suricata. */ + if (SCLoadYamlConfig() != TM_ECODE_OK) { + exit(EXIT_FAILURE); + } + + /* Set "offline" runmode to replay a pcap in library mode. */ + if (!ConfSetFromString("runmode=offline", 1)) { + exit(EXIT_FAILURE); + } + + SuricataInit(); + + /* Create and start worker on its own thread, passing the PCAP file + as argument. This needs to be done in between SuricataInit and + SuricataPostInit. */ + pthread_t worker; + if (pthread_create(&worker, NULL, SimpleWorker, argv[argc - 1]) != 0) { + exit(EXIT_FAILURE); + } + + /* Need to introduce a little sleep to allow the worker thread to + initialize before SuricataPostInit invokes TmThreadContinueThreads(). + This should be handle at the API level. */ + usleep(100); + + SuricataPostInit(); + + /* Shutdown engine. */ + SuricataShutdown(); + GlobalsDestroy(); + + return EXIT_SUCCESS; +} diff --git a/examples/lib/simple/Makefile.example.in b/examples/lib/simple/Makefile.example.in index c9da97560e..724beccdb1 100644 --- a/examples/lib/simple/Makefile.example.in +++ b/examples/lib/simple/Makefile.example.in @@ -1,16 +1,12 @@ LIBSURICATA_CONFIG ?= @CONFIGURE_PREFIX@/bin/libsuricata-config -SURICATA_LIBS = `$(LIBSURICATA_CONFIG) --libs --static` +SURICATA_LIBS = `$(LIBSURICATA_CONFIG) --libs` SURICATA_CFLAGS := `$(LIBSURICATA_CONFIG) --cflags` -# Currently the Suricata logging system requires this to be even for -# plugins. -CPPFLAGS += "-D__SCFILENAME__=\"$(*F)\"" - all: simple simple: main.c - $(CC) -o $@ $^ $(CPPFLAGS) $(CFLAGS) $(SURICATA_CFLAGS) $(SURICATA_LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(SURICATA_CFLAGS) $(SURICATA_LIBS) clean: rm -f simple diff --git a/examples/lib/simple/main.c b/examples/lib/simple/main.c index 7e6900e5f4..f9c09fb0f5 100644 --- a/examples/lib/simple/main.c +++ b/examples/lib/simple/main.c @@ -16,62 +16,14 @@ */ #include "suricata.h" -#include "conf.h" -#include "pcap.h" -#include "runmode-lib.h" -#include "source-lib.h" -#include "threadvars.h" - -/* Suricata worker thread in library mode. - The functions should be wrapped in an API layer. */ -static void *SimpleWorker(void *arg) -{ - char *pcap_file = (char *)arg; - - /* Create worker. */ - ThreadVars *tv = RunModeCreateWorker(); - if (!tv) { - pthread_exit(NULL); - } - - /* Start worker. */ - if (RunModeSpawnWorker(tv) != 0) { - pthread_exit(NULL); - } - - /* Replay pcap. */ - pcap_t *fp = pcap_open_offline(pcap_file, NULL); - if (fp == NULL) { - pthread_exit(NULL); - } - - int datalink = pcap_datalink(fp); - struct pcap_pkthdr pkthdr; - const u_char *packet; - while ((packet = pcap_next(fp, &pkthdr)) != NULL) { - if (TmModuleLibHandlePacket(tv, packet, datalink, pkthdr.ts, pkthdr.len, 0, 0, NULL) != 0) { - pthread_exit(NULL); - } - } - pcap_close(fp); - - /* Cleanup. */ - RunModeDestroyWorker(tv); - pthread_exit(NULL); -} int main(int argc, char **argv) { SuricataPreInit(argv[0]); /* Parse command line options. This is optional, you could - * directly configure Suricata through the Conf API. - The last argument is the PCAP file to replay. */ - SCParseCommandLine(argc - 1, argv); - - /* Set lib runmode. There is currently no way to set it via - the Conf API. */ - SuricataSetLibRunmode(); + * directly configure Suricata through the Conf API. */ + SCParseCommandLine(argc, argv); /* Validate/finalize the runmode. */ if (SCFinalizeRunMode() != TM_ECODE_OK) { @@ -95,28 +47,13 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } - /* Set "offline" runmode to replay a pcap in library mode. */ - if (!ConfSetFromString("runmode=offline", 1)) { - exit(EXIT_FAILURE); - } - SuricataInit(); - - /* Create and start worker on its own thread, passing the PCAP file - as argument. This needs to be done in between SuricataInit and - SuricataPostInit. */ - pthread_t worker; - if (pthread_create(&worker, NULL, SimpleWorker, argv[argc - 1]) != 0) { - exit(EXIT_FAILURE); - } - - /* Need to introduce a little sleep to allow the worker thread to - initialize before SuricataPostInit invokes TmThreadContinueThreads(). - This should be handle at the API level. */ - usleep(100); - SuricataPostInit(); + /* Suricata is now running, but we enter a loop to keep it running + * until it shouldn't be running anymore. */ + SuricataMainLoop(); + /* Shutdown engine. */ SuricataShutdown(); GlobalsDestroy();