suricata
main.c
Go to the documentation of this file.
1 /* Copyright (C) 2024 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 #include "suricata.h"
19 #include "detect.h"
20 #include "detect-engine.h"
21 #include "runmodes.h"
22 #include "conf.h"
23 #include "pcap.h"
24 #include "runmode-lib.h"
25 #include "tm-threads.h"
26 #include "threadvars.h"
27 #include "action-globals.h"
28 #include "packet.h"
29 #include "util-device.h"
30 
31 static int worker_id = 1;
32 
33 /* ThreadVars created during runmode setup, before thread sealing. */
34 static ThreadVars *g_worker_tv = NULL;
35 
36 /**
37  * Struct to pass arguments into a worker thread.
38  */
39 struct WorkerArgs {
42 };
43 
44 /**
45  * Release packet callback.
46  *
47  * If there is any cleanup that needs to be done when Suricata is done
48  * with a packet, this is the place to do it.
49  *
50  * Important: If using a custom release function, you must also
51  * release or free the packet.
52  *
53  * Optionally this is where you would handle IPS like functionality
54  * such as forwarding the packet, or triggering some other mechanism
55  * to forward the packet.
56  */
57 static void ReleasePacket(Packet *p)
58 {
60  SCLogNotice("Dropping packet!");
61  }
62 
63  /* As we overode the default release function, we must release or
64  * free the packet. */
66 }
67 
68 /**
69  * Suricata worker thread in library mode.
70  * The functions should be wrapped in an API layer.
71  */
72 static void *SimpleWorker(void *arg)
73 {
74  struct WorkerArgs *args = arg;
75  ThreadVars *tv = args->tv;
76 
77  /* Start worker. */
78  if (SCRunModeLibSpawnWorker(tv) != 0) {
79  pthread_exit(NULL);
80  }
81 
82  /* Replay pcap. */
83  pcap_t *fp = pcap_open_offline(args->pcap_filename, NULL);
84  if (fp == NULL) {
85  pthread_exit(NULL);
86  }
87 
88  LiveDevice *device = LiveGetDevice("lib0");
89  assert(device != NULL);
90 
91  int datalink = pcap_datalink(fp);
92  int count = 0;
93  struct pcap_pkthdr pkthdr;
94  const u_char *packet;
95  while ((packet = pcap_next(fp, &pkthdr)) != NULL) {
96 
97  /* Have we been asked to stop? */
99  goto done;
100  }
101 
103  if (unlikely(p == NULL)) {
104  /* Memory allocation error. */
105  goto done;
106  }
107 
108  /* If we are processing a PCAP and it is the first packet we need to set the timestamp. */
109  SCTime_t timestamp = SCTIME_FROM_TIMEVAL(&pkthdr.ts);
110  if (count == 0) {
112  }
113 
114  /* Setup the packet, these will become functions to avoid
115  * internal Packet access. */
117  SCPacketSetTime(p, SCTIME_FROM_TIMEVAL(&pkthdr.ts));
118  SCPacketSetDatalink(p, datalink);
119  SCPacketSetLiveDevice(p, device);
120  SCPacketSetReleasePacket(p, ReleasePacket);
121 
122  if (PacketSetData(p, packet, pkthdr.len) == -1) {
124  goto done;
125  }
126 
127  if (TmThreadsSlotProcessPkt(tv, tv->tm_slots, p) != TM_ECODE_OK) {
129  goto done;
130  }
131 
132  LiveDevicePktsIncr(device);
133  count++;
134  }
135 
136 done:
137  pcap_close(fp);
138 
139  /* Stop the engine. */
140  EngineStop();
141 
142  /* Cleanup.
143  *
144  * Note that there is some thread synchronization between this
145  * function and SuricataShutdown such that they must be run
146  * concurrently at this time before either will exit. */
148 
149  SCLogNotice("Worker thread exiting");
150  pthread_exit(NULL);
151 }
152 
153 static uint8_t RateFilterCallback(const Packet *p, const uint32_t sid, const uint32_t gid,
154  const uint32_t rev, uint8_t original_action, uint8_t new_action, void *arg)
155 {
156  /* Don't change the action. */
157  return new_action;
158 }
159 
160 /**
161  * Application runmode setup that creates ThreadVars before thread
162  * sealing. This follows the pattern used by other runmodes (e.g.,
163  * pcap-file) where threads are registered during the runmode
164  * callback.
165  */
166 static int AppRunModeSetup(void)
167 {
168  /* This example uses pcap files, so set time mode to offline. */
170 
171  g_worker_tv = SCRunModeLibCreateThreadVars(worker_id++);
172  if (!g_worker_tv) {
173  SCLogError("Failed to create ThreadVars");
174  return -1;
175  }
176 
177  return 0;
178 }
179 
180 int main(int argc, char **argv)
181 {
182  SuricataPreInit(argv[0]);
183 
184  /* Parse command line options. This is optional, you could
185  * directly configure Suricata through the Conf API. */
186  SCParseCommandLine(argc, argv);
187 
188  /* Find our list of pcap files, after the "--". */
189  while (argc) {
190  bool end = strncmp(argv[0], "--", 2) == 0;
191  argv++;
192  argc--;
193  if (end) {
194  break;
195  }
196  }
197  if (argc == 0) {
198  fprintf(stderr, "ERROR: No PCAP files provided\n");
199  return 1;
200  }
201 
202  /* Set the runmode to library mode. Perhaps in the future this
203  * should be done in some library bootstrap function. */
205 
206  /* Validate/finalize the runmode. */
207  if (SCFinalizeRunMode() != TM_ECODE_OK) {
208  exit(EXIT_FAILURE);
209  }
210 
211  /* Handle internal runmodes. Typically you wouldn't do this as a
212  * library user, however this example is showing how to replicate
213  * the Suricata application with the library. */
214  switch (SCStartInternalRunMode(argc, argv)) {
215  case TM_ECODE_DONE:
216  exit(EXIT_SUCCESS);
217  case TM_ECODE_FAILED:
218  exit(EXIT_FAILURE);
219  }
220 
221  /* Load configuration file, could be done earlier but must be done
222  * before SuricataInit, but even then its still optional as you
223  * may be programmatically configuration Suricata. */
224  if (SCLoadYamlConfig() != TM_ECODE_OK) {
225  exit(EXIT_FAILURE);
226  }
227 
228  /* Enable default signal handlers including SIGHUP for log file rotation,
229  * and SIGUSR2 for reloading rules. This should be done with care by a
230  * library user as the application may already have signal handlers
231  * loaded. */
233 
234  /* Register our own library run mode. At this time, the ThreadVars
235  * for each capture thread need to be created in the provided
236  * callback to meet thread synchronization requirements. */
238  RUNMODE_LIB, "custom", "Custom application run mode", AppRunModeSetup, NULL);
239 
240  if (!SCConfSetFromString("runmode=custom", 1)) {
241  exit(EXIT_FAILURE);
242  }
243 
244  /* Force logging to the current directory. */
245  SCConfSetFromString("default-log-dir=.", 1);
246 
247  if (LiveRegisterDevice("lib0") < 0) {
248  fprintf(stderr, "LiveRegisterDevice failed");
249  exit(1);
250  }
251 
252  /* SuricataInit will call our AppRunModeSetup, when it returns our
253  * ThreadVars will be ready. */
254  SuricataInit();
255 
256  SCDetectEngineRegisterRateFilterCallback(RateFilterCallback, NULL);
257 
258  /* Spawn our worker threads. */
259  pthread_t worker;
260  struct WorkerArgs args = {
261  .tv = g_worker_tv,
262  .pcap_filename = argv[argc - 1],
263  };
264  if (pthread_create(&worker, NULL, SimpleWorker, &args) != 0) {
265  exit(EXIT_FAILURE);
266  }
267 
269 
270  /* Run the main loop, this just waits for the worker thread to
271  * call EngineStop signalling Suricata that it is done reading the
272  * pcap. */
274 
275  /* Shutdown engine. */
276  SCLogNotice("Shutting down");
277 
278  /* Note that there is some thread synchronization between this
279  * function and SCTmThreadsSlotPacketLoopFinish that require them
280  * to be run concurrently at this time. */
282 
283  GlobalsDestroy();
284 
285  return EXIT_SUCCESS;
286 }
PacketCheckAction
bool PacketCheckAction(const Packet *p, const uint8_t a)
Definition: packet.c:50
SCTmThreadsSlotPacketLoopFinish
bool SCTmThreadsSlotPacketLoopFinish(ThreadVars *tv)
Definition: tm-threads.c:275
tm-threads.h
SuricataMainLoop
void SuricataMainLoop(void)
Definition: suricata.c:2971
WorkerArgs::tv
ThreadVars * tv
Definition: main.c:40
detect-engine.h
LiveRegisterDevice
int LiveRegisterDevice(const char *dev)
Add a pcap device for monitoring and create structure.
Definition: util-device.c:132
SCEnableDefaultSignalHandlers
void SCEnableDefaultSignalHandlers(void)
Enable default signal handlers.
Definition: suricata.c:299
PacketFreeOrRelease
void PacketFreeOrRelease(Packet *p)
Return a packet to where it was allocated.
Definition: decode.c:282
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
SCPacketSetLiveDevice
void SCPacketSetLiveDevice(Packet *p, LiveDevice *device)
Set a packets live device.
Definition: packet.c:186
SuricataInit
void SuricataInit(void)
Definition: suricata.c:3059
TM_ECODE_DONE
@ TM_ECODE_DONE
Definition: tm-threads-common.h:83
action-globals.h
SuricataPostInit
void SuricataPostInit(void)
Definition: suricata.c:3163
LiveDevice_
Definition: util-device-private.h:32
SURICATA_STOP
#define SURICATA_STOP
Definition: suricata.h:94
SCParseCommandLine
TmEcode SCParseCommandLine(int argc, char **argv)
Definition: suricata.c:1389
WorkerArgs
Definition: main.c:39
SuricataShutdown
void SuricataShutdown(void)
Definition: suricata.c:3152
TmqhOutputPacketpool
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
Definition: tmqh-packetpool.c:305
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:82
RUNMODE_LIB
@ RUNMODE_LIB
Definition: runmodes.h:40
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:81
SCPacketSetSource
void SCPacketSetSource(Packet *p, enum PktSrcEnum source)
Set packet source.
Definition: packet.c:201
SCRunmodeSet
void SCRunmodeSet(SCRunMode run_mode)
Set the current run mode.
Definition: suricata.c:294
util-device.h
PKT_SRC_WIRE
@ PKT_SRC_WIRE
Definition: decode.h:52
main
int main(int argc, char **argv)
Definition: main.c:20
ThreadVars_::tm_slots
struct TmSlot_ * tm_slots
Definition: threadvars.h:95
LiveGetDevice
LiveDevice * LiveGetDevice(const char *name)
Get a pointer to the device at idx.
Definition: util-device.c:268
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
SCTIME_FROM_TIMEVAL
#define SCTIME_FROM_TIMEVAL(tv)
Definition: util-time.h:79
SCRunModeLibSpawnWorker
int SCRunModeLibSpawnWorker(void *td)
start the "fake" worker.
Definition: runmode-lib.c:65
SCDetectEngineRegisterRateFilterCallback
void SCDetectEngineRegisterRateFilterCallback(SCDetectRateFilterFunc fn, void *arg)
Register a callback when a rate_filter has been applied to an alert.
Definition: detect-engine.c:5157
Packet_
Definition: decode.h:505
conf.h
RunModeRegisterNewRunMode
void RunModeRegisterNewRunMode(enum SCRunModes runmode, const char *name, const char *description, int(*RunModeFunc)(void), int(*RunModeIsIPSEnabled)(void))
Registers a new runmode.
Definition: runmodes.c:482
SCPacketSetTime
void SCPacketSetTime(Packet *p, SCTime_t ts)
Set the timestamp for a packet.
Definition: packet.c:196
SCTime_t
Definition: util-time.h:40
runmodes.h
SCConfSetFromString
int SCConfSetFromString(const char *input, int final)
Set a configuration parameter from a string.
Definition: conf.c:265
TmThreadsInitThreadsTimestamp
void TmThreadsInitThreadsTimestamp(const SCTime_t ts)
Definition: tm-threads.c:2324
TimeModeSetOffline
void TimeModeSetOffline(void)
Definition: util-time.c:105
packet.h
WorkerArgs::pcap_filename
char * pcap_filename
Definition: main.c:41
ACTION_DROP
#define ACTION_DROP
Definition: action-globals.h:30
SCStartInternalRunMode
int SCStartInternalRunMode(int argc, char **argv)
Definition: suricata.c:2424
SCPacketSetReleasePacket
void SCPacketSetReleasePacket(Packet *p, void(*ReleasePacket)(Packet *p))
Set a packet release function.
Definition: packet.c:181
EngineStop
void EngineStop(void)
make sure threads can stop the engine by calling this function. Purpose: pcap file mode needs to be a...
Definition: suricata.c:480
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:33
threadvars.h
SCLoadYamlConfig
TmEcode SCLoadYamlConfig(void)
Definition: suricata.c:1032
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
SCRunModeLibCreateThreadVars
ThreadVars * SCRunModeLibCreateThreadVars(int worker_id)
Create ThreadVars for use by a user provided thread.
Definition: runmode-lib.c:29
runmode-lib.h
PacketSetData
int PacketSetData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Set data for Packet and set length when zero copy is used.
Definition: decode.c:863
suricata.h
SCPacketSetDatalink
void SCPacketSetDatalink(Packet *p, int datalink)
Set a packets data link type.
Definition: packet.c:191
SCLogNotice
#define SCLogNotice(...)
Macro used to log NOTICE messages.
Definition: util-debug.h:250
SuricataPreInit
void SuricataPreInit(const char *progname)
Definition: suricata.c:3050
PacketGetFromQueueOrAlloc
Packet * PacketGetFromQueueOrAlloc(void)
Get a packet. We try to get a packet from the packetpool first, but if that is empty we alloc a packe...
Definition: decode.c:299
SCFinalizeRunMode
int SCFinalizeRunMode(void)
Definition: suricata.c:2498
GlobalsDestroy
void GlobalsDestroy(void)
Definition: suricata.c:400
suricata_ctl_flags
volatile uint8_t suricata_ctl_flags
Definition: suricata.c:176
LiveDevicePktsIncr
void LiveDevicePktsIncr(LiveDevice *dev)
Definition: util-device.c:637