Coverage Report

Created: 2025-07-23 07:29

/src/suricata7/src/output.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2007-2021 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
/**
19
 * \file
20
 *
21
 * \author OISF, Jason Ish <jason.ish@oisf.net>
22
 * \author Endace Technology Limited, Jason Ish <jason.ish@endace.com>
23
 *
24
 * The root logging output for all non-application logging.
25
 *
26
 * The loggers are made up of a hierarchy of loggers. At the top we
27
 * have the root logger which is the main entry point to
28
 * logging. Under the root there exists parent loggers that are the
29
 * entry point for specific types of loggers such as packet logger,
30
 * transaction loggers, etc. Each parent logger may have 0 or more
31
 * loggers that actual handle the job of producing output to something
32
 * like a file.
33
 */
34
35
#include "suricata-common.h"
36
#include "flow.h"
37
#include "conf.h"
38
#include "tm-threads.h"
39
#include "util-error.h"
40
#include "util-debug.h"
41
#include "output.h"
42
43
#include "alert-fastlog.h"
44
#include "alert-debuglog.h"
45
#include "alert-syslog.h"
46
#include "output-json.h"
47
#include "output-json-alert.h"
48
#include "output-json-anomaly.h"
49
#include "output-json-flow.h"
50
#include "output-json-netflow.h"
51
#include "log-cf-common.h"
52
#include "output-json-drop.h"
53
#include "output-eve-stream.h"
54
#include "log-httplog.h"
55
#include "output-json-http.h"
56
#include "output-json-dns.h"
57
#include "output-json-modbus.h"
58
#include "log-tlslog.h"
59
#include "log-tlsstore.h"
60
#include "output-json-tls.h"
61
#include "output-json-ssh.h"
62
#include "log-pcap.h"
63
#include "output-json-file.h"
64
#include "output-json-smtp.h"
65
#include "output-json-stats.h"
66
#include "log-tcp-data.h"
67
#include "log-stats.h"
68
#include "output-json-nfs.h"
69
#include "output-json-ftp.h"
70
#include "output-json-tftp.h"
71
#include "output-json-smb.h"
72
#include "output-json-ike.h"
73
#include "output-json-krb5.h"
74
#include "output-json-quic.h"
75
#include "output-json-dhcp.h"
76
#include "output-json-snmp.h"
77
#include "output-json-sip.h"
78
#include "output-json-rfb.h"
79
#include "output-json-mqtt.h"
80
#include "output-json-pgsql.h"
81
#include "output-json-template.h"
82
#include "output-json-rdp.h"
83
#include "output-json-http2.h"
84
#include "output-lua.h"
85
#include "output-json-dnp3.h"
86
#include "output-json-metadata.h"
87
#include "output-json-dcerpc.h"
88
#include "output-json-frame.h"
89
#include "output-json-bittorrent-dht.h"
90
#include "output-filestore.h"
91
92
typedef struct RootLogger_ {
93
    OutputLogFunc LogFunc;
94
    ThreadInitFunc ThreadInit;
95
    ThreadDeinitFunc ThreadDeinit;
96
    ThreadExitPrintStatsFunc ThreadExitPrintStats;
97
    OutputGetActiveCountFunc ActiveCntFunc;
98
99
    TAILQ_ENTRY(RootLogger_) entries;
100
} RootLogger;
101
102
/* List of registered root loggers. These are registered at start up and
103
 * are independent of configuration. Later we will build a list of active
104
 * loggers based on configuration. */
105
static TAILQ_HEAD(, RootLogger_) registered_loggers =
106
    TAILQ_HEAD_INITIALIZER(registered_loggers);
107
108
/* List of active root loggers. This means that at least one logger is enabled
109
 * for each root logger type in the config. */
110
static TAILQ_HEAD(, RootLogger_) active_loggers =
111
    TAILQ_HEAD_INITIALIZER(active_loggers);
112
113
typedef struct LoggerThreadStoreNode_ {
114
    void *thread_data;
115
    TAILQ_ENTRY(LoggerThreadStoreNode_) entries;
116
} LoggerThreadStoreNode;
117
118
typedef TAILQ_HEAD(LoggerThreadStore_, LoggerThreadStoreNode_) LoggerThreadStore;
119
120
/**
121
 * The list of all registered (known) output modules.
122
 */
123
OutputModuleList output_modules = TAILQ_HEAD_INITIALIZER(output_modules);
124
125
/**
126
 * Registry of flags to be updated on file rotation notification.
127
 */
128
typedef struct OutputFileRolloverFlag_ {
129
    int *flag;
130
131
    TAILQ_ENTRY(OutputFileRolloverFlag_) entries;
132
} OutputFileRolloverFlag;
133
134
TAILQ_HEAD(, OutputFileRolloverFlag_) output_file_rotation_flags =
135
    TAILQ_HEAD_INITIALIZER(output_file_rotation_flags);
136
137
void OutputRegisterRootLoggers(void);
138
void OutputRegisterLoggers(void);
139
140
/**
141
 * \brief Register an output module.
142
 *
143
 * This function will register an output module so it can be
144
 * configured with the configuration file.
145
 *
146
 * \retval Returns 0 on success, -1 on failure.
147
 */
148
void OutputRegisterModule(const char *name, const char *conf_name,
149
    OutputInitFunc InitFunc)
150
109
{
151
109
    OutputModule *module = SCCalloc(1, sizeof(*module));
152
109
    if (unlikely(module == NULL))
153
0
        goto error;
154
155
109
    module->name = name;
156
109
    module->conf_name = conf_name;
157
109
    module->InitFunc = InitFunc;
158
109
    TAILQ_INSERT_TAIL(&output_modules, module, entries);
159
160
109
    SCLogDebug("Output module \"%s\" registered.", name);
161
162
109
    return;
163
164
0
error:
165
0
    FatalError("Fatal error encountered in OutputRegisterModule. Exiting...");
166
0
}
167
168
/**
169
 * \brief Register a packet output module.
170
 *
171
 * This function will register an output module so it can be
172
 * configured with the configuration file.
173
 *
174
 * \retval Returns 0 on success, -1 on failure.
175
 */
176
void OutputRegisterPacketModule(LoggerId id, const char *name,
177
    const char *conf_name, OutputInitFunc InitFunc,
178
    PacketLogger PacketLogFunc, PacketLogCondition PacketConditionFunc,
179
    ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit,
180
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
181
284
{
182
284
    if (unlikely(PacketLogFunc == NULL || PacketConditionFunc == NULL)) {
183
0
        goto error;
184
0
    }
185
186
284
    OutputModule *module = SCCalloc(1, sizeof(*module));
187
284
    if (unlikely(module == NULL)) {
188
0
        goto error;
189
0
    }
190
191
284
    module->logger_id = id;
192
284
    module->name = name;
193
284
    module->conf_name = conf_name;
194
284
    module->InitFunc = InitFunc;
195
284
    module->PacketLogFunc = PacketLogFunc;
196
284
    module->PacketConditionFunc = PacketConditionFunc;
197
284
    module->ThreadInit = ThreadInit;
198
284
    module->ThreadDeinit = ThreadDeinit;
199
284
    module->ThreadExitPrintStats = ThreadExitPrintStats;
200
284
    TAILQ_INSERT_TAIL(&output_modules, module, entries);
201
202
284
    SCLogDebug("Packet logger \"%s\" registered.", name);
203
284
    return;
204
0
error:
205
0
    FatalError("Fatal error encountered. Exiting...");
206
0
}
207
208
/**
209
 * \brief Register a packet output sub-module.
210
 *
211
 * This function will register an output module so it can be
212
 * configured with the configuration file.
213
 *
214
 * \retval Returns 0 on success, -1 on failure.
215
 */
216
void OutputRegisterPacketSubModule(LoggerId id, const char *parent_name,
217
    const char *name, const char *conf_name, OutputInitSubFunc InitFunc,
218
    PacketLogger PacketLogFunc, PacketLogCondition PacketConditionFunc,
219
    ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit,
220
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
221
535
{
222
535
    if (unlikely(PacketLogFunc == NULL || PacketConditionFunc == NULL)) {
223
0
        goto error;
224
0
    }
225
226
535
    OutputModule *module = SCCalloc(1, sizeof(*module));
227
535
    if (unlikely(module == NULL)) {
228
0
        goto error;
229
0
    }
230
231
535
    module->logger_id = id;
232
535
    module->name = name;
233
535
    module->conf_name = conf_name;
234
535
    module->parent_name = parent_name;
235
535
    module->InitSubFunc = InitFunc;
236
535
    module->PacketLogFunc = PacketLogFunc;
237
535
    module->PacketConditionFunc = PacketConditionFunc;
238
535
    module->ThreadInit = ThreadInit;
239
535
    module->ThreadDeinit = ThreadDeinit;
240
535
    module->ThreadExitPrintStats = ThreadExitPrintStats;
241
535
    TAILQ_INSERT_TAIL(&output_modules, module, entries);
242
243
535
    SCLogDebug("Packet logger \"%s\" registered.", name);
244
535
    return;
245
0
error:
246
0
    FatalError("Fatal error encountered. Exiting...");
247
0
}
248
249
/**
250
 * \brief Wrapper function for tx output modules.
251
 *
252
 * This function will register an output module so it can be
253
 * configured with the configuration file.
254
 *
255
 * \retval Returns 0 on success, -1 on failure.
256
 */
257
static void OutputRegisterTxModuleWrapper(LoggerId id, const char *name,
258
    const char *conf_name, OutputInitFunc InitFunc, AppProto alproto,
259
    TxLogger TxLogFunc, int tc_log_progress, int ts_log_progress,
260
    TxLoggerCondition TxLogCondition, ThreadInitFunc ThreadInit,
261
    ThreadDeinitFunc ThreadDeinit,
262
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
263
251
{
264
251
    if (unlikely(TxLogFunc == NULL)) {
265
0
        goto error;
266
0
    }
267
268
251
    OutputModule *module = SCCalloc(1, sizeof(*module));
269
251
    if (unlikely(module == NULL)) {
270
0
        goto error;
271
0
    }
272
273
251
    module->logger_id = id;
274
251
    module->name = name;
275
251
    module->conf_name = conf_name;
276
251
    module->InitFunc = InitFunc;
277
251
    module->TxLogFunc = TxLogFunc;
278
251
    module->TxLogCondition = TxLogCondition;
279
251
    module->alproto = alproto;
280
251
    module->tc_log_progress = tc_log_progress;
281
251
    module->ts_log_progress = ts_log_progress;
282
251
    module->ThreadInit = ThreadInit;
283
251
    module->ThreadDeinit = ThreadDeinit;
284
251
    module->ThreadExitPrintStats = ThreadExitPrintStats;
285
251
    TAILQ_INSERT_TAIL(&output_modules, module, entries);
286
287
251
    SCLogDebug("Tx logger \"%s\" registered.", name);
288
251
    return;
289
0
error:
290
0
    FatalError("Fatal error encountered. Exiting...");
291
0
}
292
293
static void OutputRegisterTxSubModuleWrapper(LoggerId id, const char *parent_name,
294
    const char *name, const char *conf_name, OutputInitSubFunc InitFunc,
295
    AppProto alproto, TxLogger TxLogFunc, int tc_log_progress,
296
    int ts_log_progress, TxLoggerCondition TxLogCondition,
297
    ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit,
298
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
299
2.10k
{
300
2.10k
    if (unlikely(TxLogFunc == NULL)) {
301
0
        goto error;
302
0
    }
303
304
2.10k
    OutputModule *module = SCCalloc(1, sizeof(*module));
305
2.10k
    if (unlikely(module == NULL)) {
306
0
        goto error;
307
0
    }
308
309
2.10k
    module->logger_id = id;
310
2.10k
    module->name = name;
311
2.10k
    module->conf_name = conf_name;
312
2.10k
    module->parent_name = parent_name;
313
2.10k
    module->InitSubFunc = InitFunc;
314
2.10k
    module->TxLogFunc = TxLogFunc;
315
2.10k
    module->TxLogCondition = TxLogCondition;
316
2.10k
    module->alproto = alproto;
317
2.10k
    module->tc_log_progress = tc_log_progress;
318
2.10k
    module->ts_log_progress = ts_log_progress;
319
2.10k
    module->ThreadInit = ThreadInit;
320
2.10k
    module->ThreadDeinit = ThreadDeinit;
321
2.10k
    module->ThreadExitPrintStats = ThreadExitPrintStats;
322
2.10k
    TAILQ_INSERT_TAIL(&output_modules, module, entries);
323
324
2.10k
    SCLogDebug("Tx logger for alproto %d \"%s\" registered.", alproto, name);
325
2.10k
    return;
326
0
error:
327
0
    FatalError("Fatal error encountered. Exiting...");
328
0
}
329
330
/**
331
 * \brief Register a tx output module with condition.
332
 *
333
 * This function will register an output module so it can be
334
 * configured with the configuration file.
335
 *
336
 * \retval Returns 0 on success, -1 on failure.
337
 */
338
void OutputRegisterTxModuleWithCondition(LoggerId id, const char *name,
339
    const char *conf_name, OutputInitFunc InitFunc, AppProto alproto,
340
    TxLogger TxLogFunc, TxLoggerCondition TxLogCondition,
341
    ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit,
342
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
343
109
{
344
109
    OutputRegisterTxModuleWrapper(id, name, conf_name, InitFunc, alproto,
345
109
        TxLogFunc, -1, -1, TxLogCondition, ThreadInit, ThreadDeinit,
346
109
        ThreadExitPrintStats);
347
109
}
348
349
void OutputRegisterTxSubModuleWithCondition(LoggerId id,
350
    const char *parent_name, const char *name, const char *conf_name,
351
    OutputInitSubFunc InitFunc, AppProto alproto, TxLogger TxLogFunc,
352
    TxLoggerCondition TxLogCondition, ThreadInitFunc ThreadInit,
353
    ThreadDeinitFunc ThreadDeinit,
354
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
355
71
{
356
71
    OutputRegisterTxSubModuleWrapper(id, parent_name, name, conf_name, InitFunc,
357
71
        alproto, TxLogFunc, -1, -1, TxLogCondition, ThreadInit, ThreadDeinit,
358
71
        ThreadExitPrintStats);
359
71
}
360
361
/**
362
 * \brief Register a tx output module with progress.
363
 *
364
 * This function will register an output module so it can be
365
 * configured with the configuration file.
366
 *
367
 * \retval Returns 0 on success, -1 on failure.
368
 */
369
void OutputRegisterTxModuleWithProgress(LoggerId id, const char *name,
370
    const char *conf_name, OutputInitFunc InitFunc, AppProto alproto,
371
    TxLogger TxLogFunc, int tc_log_progress, int ts_log_progress,
372
    ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit,
373
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
374
71
{
375
71
    OutputRegisterTxModuleWrapper(id, name, conf_name, InitFunc, alproto,
376
71
        TxLogFunc, tc_log_progress, ts_log_progress, NULL, ThreadInit,
377
71
        ThreadDeinit, ThreadExitPrintStats);
378
71
}
379
380
void OutputRegisterTxSubModuleWithProgress(LoggerId id, const char *parent_name,
381
    const char *name, const char *conf_name, OutputInitSubFunc InitFunc,
382
    AppProto alproto, TxLogger TxLogFunc, int tc_log_progress,
383
    int ts_log_progress, ThreadInitFunc ThreadInit,
384
    ThreadDeinitFunc ThreadDeinit,
385
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
386
142
{
387
142
    OutputRegisterTxSubModuleWrapper(id, parent_name, name, conf_name, InitFunc,
388
142
        alproto, TxLogFunc, tc_log_progress, ts_log_progress, NULL, ThreadInit,
389
142
        ThreadDeinit, ThreadExitPrintStats);
390
142
}
391
392
/**
393
 * \brief Register a tx output module.
394
 *
395
 * This function will register an output module so it can be
396
 * configured with the configuration file.
397
 *
398
 * \retval Returns 0 on success, -1 on failure.
399
 */
400
void OutputRegisterTxModule(LoggerId id, const char *name,
401
    const char *conf_name, OutputInitFunc InitFunc, AppProto alproto,
402
    TxLogger TxLogFunc, ThreadInitFunc ThreadInit,
403
    ThreadDeinitFunc ThreadDeinit,
404
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
405
71
{
406
71
    OutputRegisterTxModuleWrapper(id, name, conf_name, InitFunc, alproto,
407
71
        TxLogFunc, -1, -1, NULL, ThreadInit, ThreadDeinit,
408
71
        ThreadExitPrintStats);
409
71
}
410
411
void OutputRegisterTxSubModule(LoggerId id, const char *parent_name,
412
    const char *name, const char *conf_name,
413
    OutputInitSubFunc InitFunc, AppProto alproto, TxLogger TxLogFunc,
414
    ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit,
415
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
416
1.89k
{
417
1.89k
    OutputRegisterTxSubModuleWrapper(id, parent_name, name, conf_name,
418
1.89k
        InitFunc, alproto, TxLogFunc, -1, -1, NULL, ThreadInit, ThreadDeinit,
419
1.89k
        ThreadExitPrintStats);
420
1.89k
}
421
422
/**
423
 * \brief Register a file output module.
424
 *
425
 * This function will register an output module so it can be
426
 * configured with the configuration file.
427
 *
428
 * \retval Returns 0 on success, -1 on failure.
429
 */
430
void OutputRegisterFileModule(LoggerId id, const char *name,
431
    const char *conf_name, OutputInitFunc InitFunc, FileLogger FileLogFunc,
432
    ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit,
433
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
434
0
{
435
0
    if (unlikely(FileLogFunc == NULL)) {
436
0
        goto error;
437
0
    }
438
439
0
    OutputModule *module = SCCalloc(1, sizeof(*module));
440
0
    if (unlikely(module == NULL)) {
441
0
        goto error;
442
0
    }
443
444
0
    module->logger_id = id;
445
0
    module->name = name;
446
0
    module->conf_name = conf_name;
447
0
    module->InitFunc = InitFunc;
448
0
    module->FileLogFunc = FileLogFunc;
449
0
    module->ThreadInit = ThreadInit;
450
0
    module->ThreadDeinit = ThreadDeinit;
451
0
    module->ThreadExitPrintStats = ThreadExitPrintStats;
452
0
    TAILQ_INSERT_TAIL(&output_modules, module, entries);
453
454
0
    SCLogDebug("File logger \"%s\" registered.", name);
455
0
    return;
456
0
error:
457
0
    FatalError("Fatal error encountered. Exiting...");
458
0
}
459
460
/**
461
 * \brief Register a file output sub-module.
462
 *
463
 * This function will register an output module so it can be
464
 * configured with the configuration file.
465
 *
466
 * \retval Returns 0 on success, -1 on failure.
467
 */
468
void OutputRegisterFileSubModule(LoggerId id, const char *parent_name,
469
    const char *name, const char *conf_name, OutputInitSubFunc InitFunc,
470
    FileLogger FileLogFunc, ThreadInitFunc ThreadInit,
471
    ThreadDeinitFunc ThreadDeinit,
472
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
473
71
{
474
71
    if (unlikely(FileLogFunc == NULL)) {
475
0
        goto error;
476
0
    }
477
478
71
    OutputModule *module = SCCalloc(1, sizeof(*module));
479
71
    if (unlikely(module == NULL)) {
480
0
        goto error;
481
0
    }
482
483
71
    module->logger_id = id;
484
71
    module->name = name;
485
71
    module->conf_name = conf_name;
486
71
    module->parent_name = parent_name;
487
71
    module->InitSubFunc = InitFunc;
488
71
    module->FileLogFunc = FileLogFunc;
489
71
    module->ThreadInit = ThreadInit;
490
71
    module->ThreadDeinit = ThreadDeinit;
491
71
    module->ThreadExitPrintStats = ThreadExitPrintStats;
492
71
    TAILQ_INSERT_TAIL(&output_modules, module, entries);
493
494
71
    SCLogDebug("File logger \"%s\" registered.", name);
495
71
    return;
496
0
error:
497
0
    FatalError("Fatal error encountered. Exiting...");
498
0
}
499
500
/**
501
 * \brief Register a file data output module.
502
 *
503
 * This function will register an output module so it can be
504
 * configured with the configuration file.
505
 *
506
 * \retval Returns 0 on success, -1 on failure.
507
 */
508
void OutputRegisterFiledataModule(LoggerId id, const char *name,
509
    const char *conf_name, OutputInitFunc InitFunc,
510
    FiledataLogger FiledataLogFunc, ThreadInitFunc ThreadInit,
511
    ThreadDeinitFunc ThreadDeinit,
512
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
513
71
{
514
71
    if (unlikely(FiledataLogFunc == NULL)) {
515
0
        goto error;
516
0
    }
517
518
71
    OutputModule *module = SCCalloc(1, sizeof(*module));
519
71
    if (unlikely(module == NULL)) {
520
0
        goto error;
521
0
    }
522
523
71
    module->logger_id = id;
524
71
    module->name = name;
525
71
    module->conf_name = conf_name;
526
71
    module->InitFunc = InitFunc;
527
71
    module->FiledataLogFunc = FiledataLogFunc;
528
71
    module->ThreadInit = ThreadInit;
529
71
    module->ThreadDeinit = ThreadDeinit;
530
71
    module->ThreadExitPrintStats = ThreadExitPrintStats;
531
71
    TAILQ_INSERT_TAIL(&output_modules, module, entries);
532
533
71
    SCLogDebug("Filedata logger \"%s\" registered.", name);
534
71
    return;
535
0
error:
536
0
    FatalError("Fatal error encountered. Exiting...");
537
0
}
538
539
/**
540
 * \brief Register a file data output sub-module.
541
 *
542
 * This function will register an output module so it can be
543
 * configured with the configuration file.
544
 *
545
 * \retval Returns 0 on success, -1 on failure.
546
 */
547
void OutputRegisterFiledataSubModule(LoggerId id, const char *parent_name,
548
    const char *name, const char *conf_name, OutputInitSubFunc InitFunc,
549
    FiledataLogger FiledataLogFunc, ThreadInitFunc ThreadInit,
550
    ThreadDeinitFunc ThreadDeinit,
551
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
552
0
{
553
0
    if (unlikely(FiledataLogFunc == NULL)) {
554
0
        goto error;
555
0
    }
556
557
0
    OutputModule *module = SCCalloc(1, sizeof(*module));
558
0
    if (unlikely(module == NULL)) {
559
0
        goto error;
560
0
    }
561
562
0
    module->logger_id = id;
563
0
    module->name = name;
564
0
    module->conf_name = conf_name;
565
0
    module->parent_name = parent_name;
566
0
    module->InitSubFunc = InitFunc;
567
0
    module->FiledataLogFunc = FiledataLogFunc;
568
0
    module->ThreadInit = ThreadInit;
569
0
    module->ThreadDeinit = ThreadDeinit;
570
0
    module->ThreadExitPrintStats = ThreadExitPrintStats;
571
0
    TAILQ_INSERT_TAIL(&output_modules, module, entries);
572
573
0
    SCLogDebug("Filedata logger \"%s\" registered.", name);
574
0
    return;
575
0
error:
576
0
    FatalError("Fatal error encountered. Exiting...");
577
0
}
578
579
/**
580
 * \brief Register a flow output sub-module.
581
 *
582
 * This function will register an output module so it can be
583
 * configured with the configuration file.
584
 *
585
 * \retval Returns 0 on success, -1 on failure.
586
 */
587
void OutputRegisterFlowSubModule(LoggerId id, const char *parent_name,
588
    const char *name, const char *conf_name, OutputInitSubFunc InitFunc,
589
    FlowLogger FlowLogFunc, ThreadInitFunc ThreadInit,
590
    ThreadDeinitFunc ThreadDeinit,
591
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
592
142
{
593
142
    if (unlikely(FlowLogFunc == NULL)) {
594
0
        goto error;
595
0
    }
596
597
142
    OutputModule *module = SCCalloc(1, sizeof(*module));
598
142
    if (unlikely(module == NULL)) {
599
0
        goto error;
600
0
    }
601
602
142
    module->logger_id = id;
603
142
    module->name = name;
604
142
    module->conf_name = conf_name;
605
142
    module->parent_name = parent_name;
606
142
    module->InitSubFunc = InitFunc;
607
142
    module->FlowLogFunc = FlowLogFunc;
608
142
    module->ThreadInit = ThreadInit;
609
142
    module->ThreadDeinit = ThreadDeinit;
610
142
    module->ThreadExitPrintStats = ThreadExitPrintStats;
611
142
    TAILQ_INSERT_TAIL(&output_modules, module, entries);
612
613
142
    SCLogDebug("Flow logger \"%s\" registered.", name);
614
142
    return;
615
0
error:
616
0
    FatalError("Fatal error encountered. Exiting...");
617
0
}
618
619
/**
620
 * \brief Register a streaming data output module.
621
 *
622
 * This function will register an output module so it can be
623
 * configured with the configuration file.
624
 *
625
 * \retval Returns 0 on success, -1 on failure.
626
 */
627
void OutputRegisterStreamingModule(LoggerId id, const char *name,
628
    const char *conf_name, OutputInitFunc InitFunc,
629
    StreamingLogger StreamingLogFunc,
630
    enum OutputStreamingType stream_type, ThreadInitFunc ThreadInit,
631
    ThreadDeinitFunc ThreadDeinit,
632
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
633
142
{
634
142
    if (unlikely(StreamingLogFunc == NULL)) {
635
0
        goto error;
636
0
    }
637
638
142
    OutputModule *module = SCCalloc(1, sizeof(*module));
639
142
    if (unlikely(module == NULL)) {
640
0
        goto error;
641
0
    }
642
643
142
    module->logger_id = id;
644
142
    module->name = name;
645
142
    module->conf_name = conf_name;
646
142
    module->InitFunc = InitFunc;
647
142
    module->StreamingLogFunc = StreamingLogFunc;
648
142
    module->stream_type = stream_type;
649
142
    module->ThreadInit = ThreadInit;
650
142
    module->ThreadDeinit = ThreadDeinit;
651
142
    module->ThreadExitPrintStats = ThreadExitPrintStats;
652
142
    TAILQ_INSERT_TAIL(&output_modules, module, entries);
653
654
142
    SCLogDebug("Streaming logger \"%s\" registered.", name);
655
142
    return;
656
0
error:
657
0
    FatalError("Fatal error encountered. Exiting...");
658
0
}
659
660
/**
661
 * \brief Register a streaming data output sub-module.
662
 *
663
 * This function will register an output module so it can be
664
 * configured with the configuration file.
665
 *
666
 * \retval Returns 0 on success, -1 on failure.
667
 */
668
void OutputRegisterStreamingSubModule(LoggerId id, const char *parent_name,
669
    const char *name, const char *conf_name, OutputInitSubFunc InitFunc,
670
    StreamingLogger StreamingLogFunc, enum OutputStreamingType stream_type,
671
    ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit,
672
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
673
0
{
674
0
    if (unlikely(StreamingLogFunc == NULL)) {
675
0
        goto error;
676
0
    }
677
678
0
    OutputModule *module = SCCalloc(1, sizeof(*module));
679
0
    if (unlikely(module == NULL)) {
680
0
        goto error;
681
0
    }
682
683
0
    module->logger_id = id;
684
0
    module->name = name;
685
0
    module->conf_name = conf_name;
686
0
    module->parent_name = parent_name;
687
0
    module->InitSubFunc = InitFunc;
688
0
    module->StreamingLogFunc = StreamingLogFunc;
689
0
    module->stream_type = stream_type;
690
0
    module->ThreadInit = ThreadInit;
691
0
    module->ThreadDeinit = ThreadDeinit;
692
0
    module->ThreadExitPrintStats = ThreadExitPrintStats;
693
0
    TAILQ_INSERT_TAIL(&output_modules, module, entries);
694
695
0
    SCLogDebug("Streaming logger \"%s\" registered.", name);
696
0
    return;
697
0
error:
698
0
    FatalError("Fatal error encountered. Exiting...");
699
0
}
700
701
/**
702
 * \brief Register a stats data output module.
703
 *
704
 * This function will register an output module so it can be
705
 * configured with the configuration file.
706
 *
707
 * \retval Returns 0 on success, -1 on failure.
708
 */
709
void OutputRegisterStatsModule(LoggerId id, const char *name,
710
    const char *conf_name, OutputInitFunc InitFunc, StatsLogger StatsLogFunc,
711
    ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit,
712
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
713
71
{
714
71
    if (unlikely(StatsLogFunc == NULL)) {
715
0
        goto error;
716
0
    }
717
718
71
    OutputModule *module = SCCalloc(1, sizeof(*module));
719
71
    if (unlikely(module == NULL)) {
720
0
        goto error;
721
0
    }
722
723
71
    module->logger_id = id;
724
71
    module->name = name;
725
71
    module->conf_name = conf_name;
726
71
    module->InitFunc = InitFunc;
727
71
    module->StatsLogFunc = StatsLogFunc;
728
71
    module->ThreadInit = ThreadInit;
729
71
    module->ThreadDeinit = ThreadDeinit;
730
71
    module->ThreadExitPrintStats = ThreadExitPrintStats;
731
71
    TAILQ_INSERT_TAIL(&output_modules, module, entries);
732
733
71
    SCLogDebug("Stats logger \"%s\" registered.", name);
734
71
    return;
735
0
error:
736
0
    FatalError("Fatal error encountered. Exiting...");
737
0
}
738
739
/**
740
 * \brief Register a stats data output sub-module.
741
 *
742
 * This function will register an output module so it can be
743
 * configured with the configuration file.
744
 *
745
 * \retval Returns 0 on success, -1 on failure.
746
 */
747
void OutputRegisterStatsSubModule(LoggerId id, const char *parent_name,
748
    const char *name, const char *conf_name, OutputInitSubFunc InitFunc,
749
    StatsLogger StatsLogFunc, ThreadInitFunc ThreadInit,
750
    ThreadDeinitFunc ThreadDeinit,
751
    ThreadExitPrintStatsFunc ThreadExitPrintStats)
752
71
{
753
71
    if (unlikely(StatsLogFunc == NULL)) {
754
0
        goto error;
755
0
    }
756
757
71
    OutputModule *module = SCCalloc(1, sizeof(*module));
758
71
    if (unlikely(module == NULL)) {
759
0
        goto error;
760
0
    }
761
762
71
    module->logger_id = id;
763
71
    module->name = name;
764
71
    module->conf_name = conf_name;
765
71
    module->parent_name = parent_name;
766
71
    module->InitSubFunc = InitFunc;
767
71
    module->StatsLogFunc = StatsLogFunc;
768
71
    module->ThreadInit = ThreadInit;
769
71
    module->ThreadDeinit = ThreadDeinit;
770
71
    module->ThreadExitPrintStats = ThreadExitPrintStats;
771
71
    TAILQ_INSERT_TAIL(&output_modules, module, entries);
772
773
71
    SCLogDebug("Stats logger \"%s\" registered.", name);
774
71
    return;
775
0
error:
776
0
    FatalError("Fatal error encountered. Exiting...");
777
0
}
778
779
/**
780
 * \brief Get an output module by name.
781
 *
782
 * \retval The OutputModule with the given name or NULL if no output module
783
 * with the given name is registered.
784
 */
785
OutputModule *OutputGetModuleByConfName(const char *conf_name)
786
4
{
787
4
    OutputModule *module;
788
789
54
    TAILQ_FOREACH(module, &output_modules, entries) {
790
54
        if (strcmp(module->conf_name, conf_name) == 0)
791
4
            return module;
792
54
    }
793
794
0
    return NULL;
795
4
}
796
797
/**
798
 * \brief Deregister all modules.  Useful for a memory clean exit.
799
 */
800
void OutputDeregisterAll(void)
801
0
{
802
0
    OutputModule *module;
803
804
0
    while ((module = TAILQ_FIRST(&output_modules))) {
805
0
        TAILQ_REMOVE(&output_modules, module, entries);
806
0
        SCFree(module);
807
0
    }
808
0
}
809
810
static int drop_loggers = 0;
811
812
int OutputDropLoggerEnable(void)
813
0
{
814
0
    if (drop_loggers)
815
0
        return -1;
816
0
    drop_loggers++;
817
0
    return 0;
818
0
}
819
820
void OutputDropLoggerDisable(void)
821
0
{
822
0
    if (drop_loggers)
823
0
        drop_loggers--;
824
0
}
825
826
/**
827
 * \brief Register a flag for file rotation notification.
828
 *
829
 * \param flag A pointer that will be set to 1 when file rotation is
830
 *   requested.
831
 */
832
void OutputRegisterFileRotationFlag(int *flag)
833
96
{
834
96
    OutputFileRolloverFlag *flag_entry = SCCalloc(1, sizeof(*flag_entry));
835
96
    if (unlikely(flag_entry == NULL)) {
836
0
        SCLogError("Failed to allocate memory to register file rotation flag");
837
0
        return;
838
0
    }
839
96
    flag_entry->flag = flag;
840
96
    TAILQ_INSERT_TAIL(&output_file_rotation_flags, flag_entry, entries);
841
96
}
842
843
/**
844
 * \brief Unregister a file rotation flag.
845
 *
846
 * Note that it is safe to call this function with a flag that may not
847
 * have been registered, in which case this function won't do
848
 * anything.
849
 *
850
 * \param flag A pointer that has been previously registered for file
851
 *   rotation notifications.
852
 */
853
void OutputUnregisterFileRotationFlag(int *flag)
854
0
{
855
0
    OutputFileRolloverFlag *entry, *next;
856
0
    for (entry = TAILQ_FIRST(&output_file_rotation_flags); entry != NULL;
857
0
         entry = next) {
858
0
        next = TAILQ_NEXT(entry, entries);
859
0
        if (entry->flag == flag) {
860
0
            TAILQ_REMOVE(&output_file_rotation_flags, entry, entries);
861
0
            SCFree(entry);
862
0
            break;
863
0
        }
864
0
    }
865
0
}
866
867
/**
868
 * \brief Notifies all registered file rotation notification flags.
869
 */
870
0
void OutputNotifyFileRotation(void) {
871
0
    OutputFileRolloverFlag *flag;
872
0
    TAILQ_FOREACH(flag, &output_file_rotation_flags, entries) {
873
0
        *(flag->flag) = 1;
874
0
    }
875
0
}
876
877
TmEcode OutputLoggerLog(ThreadVars *tv, Packet *p, void *thread_data)
878
18.7M
{
879
18.7M
    LoggerThreadStore *thread_store = (LoggerThreadStore *)thread_data;
880
18.7M
    RootLogger *logger = TAILQ_FIRST(&active_loggers);
881
18.7M
    LoggerThreadStoreNode *thread_store_node = TAILQ_FIRST(thread_store);
882
56.2M
    while (logger && thread_store_node) {
883
37.5M
        logger->LogFunc(tv, p, thread_store_node->thread_data);
884
885
37.5M
        logger = TAILQ_NEXT(logger, entries);
886
37.5M
        thread_store_node = TAILQ_NEXT(thread_store_node, entries);
887
37.5M
    }
888
18.7M
    return TM_ECODE_OK;
889
18.7M
}
890
891
TmEcode OutputLoggerThreadInit(ThreadVars *tv, const void *initdata, void **data)
892
4
{
893
4
    LoggerThreadStore *thread_store = SCCalloc(1, sizeof(*thread_store));
894
4
    if (thread_store == NULL) {
895
0
        return TM_ECODE_FAILED;
896
0
    }
897
4
    TAILQ_INIT(thread_store);
898
4
    *data = (void *)thread_store;
899
900
4
    RootLogger *logger;
901
8
    TAILQ_FOREACH(logger, &active_loggers, entries) {
902
903
8
        void *child_thread_data = NULL;
904
8
        if (logger->ThreadInit != NULL) {
905
8
            if (logger->ThreadInit(tv, initdata, &child_thread_data) == TM_ECODE_OK) {
906
8
                LoggerThreadStoreNode *thread_store_node =
907
8
                    SCCalloc(1, sizeof(*thread_store_node));
908
8
                if (thread_store_node == NULL) {
909
                    /* Undo everything, calling de-init will take care
910
                     * of that. */
911
0
                    OutputLoggerThreadDeinit(tv, thread_store);
912
0
                    return TM_ECODE_FAILED;
913
0
                }
914
8
                thread_store_node->thread_data = child_thread_data;
915
8
                TAILQ_INSERT_TAIL(thread_store, thread_store_node, entries);
916
8
            }
917
8
        }
918
8
    }
919
4
    return TM_ECODE_OK;
920
4
}
921
922
TmEcode OutputLoggerThreadDeinit(ThreadVars *tv, void *thread_data)
923
0
{
924
0
    if (thread_data == NULL)
925
0
        return TM_ECODE_FAILED;
926
927
0
    LoggerThreadStore *thread_store = (LoggerThreadStore *)thread_data;
928
0
    RootLogger *logger = TAILQ_FIRST(&active_loggers);
929
0
    LoggerThreadStoreNode *thread_store_node = TAILQ_FIRST(thread_store);
930
0
    while (logger && thread_store_node) {
931
0
        if (logger->ThreadDeinit != NULL) {
932
0
            logger->ThreadDeinit(tv, thread_store_node->thread_data);
933
0
        }
934
0
        logger = TAILQ_NEXT(logger, entries);
935
0
        thread_store_node = TAILQ_NEXT(thread_store_node, entries);
936
0
    }
937
938
    /* Free the thread store. */
939
0
    while ((thread_store_node = TAILQ_FIRST(thread_store)) != NULL) {
940
0
        TAILQ_REMOVE(thread_store, thread_store_node, entries);
941
0
        SCFree(thread_store_node);
942
0
    }
943
0
    SCFree(thread_store);
944
945
0
    return TM_ECODE_OK;
946
0
}
947
948
void OutputLoggerExitPrintStats(ThreadVars *tv, void *thread_data)
949
0
{
950
0
    LoggerThreadStore *thread_store = (LoggerThreadStore *)thread_data;
951
0
    RootLogger *logger = TAILQ_FIRST(&active_loggers);
952
0
    LoggerThreadStoreNode *thread_store_node = TAILQ_FIRST(thread_store);
953
0
    while (logger && thread_store_node) {
954
0
        if (logger->ThreadExitPrintStats != NULL) {
955
0
            logger->ThreadExitPrintStats(tv, thread_store_node->thread_data);
956
0
        }
957
0
        logger = TAILQ_NEXT(logger, entries);
958
0
        thread_store_node = TAILQ_NEXT(thread_store_node, entries);
959
0
    }
960
0
}
961
962
void OutputRegisterRootLogger(ThreadInitFunc ThreadInit,
963
    ThreadDeinitFunc ThreadDeinit,
964
    ThreadExitPrintStatsFunc ThreadExitPrintStats,
965
    OutputLogFunc LogFunc, OutputGetActiveCountFunc ActiveCntFunc)
966
213
{
967
213
    BUG_ON(LogFunc == NULL);
968
969
213
    RootLogger *logger = SCCalloc(1, sizeof(*logger));
970
213
    if (logger == NULL) {
971
0
        FatalError("failed to alloc root logger");
972
0
    }
973
213
    logger->ThreadInit = ThreadInit;
974
213
    logger->ThreadDeinit = ThreadDeinit;
975
213
    logger->ThreadExitPrintStats = ThreadExitPrintStats;
976
213
    logger->LogFunc = LogFunc;
977
213
    logger->ActiveCntFunc = ActiveCntFunc;
978
213
    TAILQ_INSERT_TAIL(&registered_loggers, logger, entries);
979
213
}
980
981
static void OutputRegisterActiveLogger(RootLogger *reg)
982
8
{
983
8
    RootLogger *logger = SCCalloc(1, sizeof(*logger));
984
8
    if (logger == NULL) {
985
0
        FatalError("failed to alloc root logger");
986
0
    }
987
8
    logger->ThreadInit = reg->ThreadInit;
988
8
    logger->ThreadDeinit = reg->ThreadDeinit;
989
8
    logger->ThreadExitPrintStats = reg->ThreadExitPrintStats;
990
8
    logger->LogFunc = reg->LogFunc;
991
8
    logger->ActiveCntFunc = reg->ActiveCntFunc;
992
8
    TAILQ_INSERT_TAIL(&active_loggers, logger, entries);
993
8
}
994
995
void OutputSetupActiveLoggers(void)
996
4
{
997
4
    RootLogger *logger = TAILQ_FIRST(&registered_loggers);
998
16
    while (logger) {
999
12
        uint32_t cnt = logger->ActiveCntFunc();
1000
12
        if (cnt) {
1001
8
            OutputRegisterActiveLogger(logger);
1002
8
        }
1003
1004
12
        logger = TAILQ_NEXT(logger, entries);
1005
12
    }
1006
4
}
1007
1008
void OutputClearActiveLoggers(void)
1009
0
{
1010
0
    RootLogger *logger;
1011
0
    while ((logger = TAILQ_FIRST(&active_loggers)) != NULL) {
1012
0
        TAILQ_REMOVE(&active_loggers, logger, entries);
1013
0
        SCFree(logger);
1014
0
    }
1015
0
}
1016
1017
void TmModuleLoggerRegister(void)
1018
71
{
1019
71
    OutputRegisterRootLoggers();
1020
71
    OutputRegisterLoggers();
1021
71
}
1022
1023
/**
1024
 * \brief Register all root loggers.
1025
 */
1026
void OutputRegisterRootLoggers(void)
1027
33
{
1028
33
    OutputPacketLoggerRegister();
1029
33
    OutputFiledataLoggerRegister();
1030
33
    OutputFileLoggerRegister();
1031
33
    OutputTxLoggerRegister();
1032
33
    OutputStreamingLoggerRegister();
1033
33
}
1034
1035
/**
1036
 * \brief Register all non-root logging modules.
1037
 */
1038
void OutputRegisterLoggers(void)
1039
33
{
1040
    /* custom format log*/
1041
33
    LogCustomFormatRegister();
1042
1043
33
    LuaLogRegister();
1044
    /* fast log */
1045
33
    AlertFastLogRegister();
1046
    /* debug log */
1047
33
    AlertDebugLogRegister();
1048
    /* syslog log */
1049
33
    AlertSyslogRegister();
1050
33
    JsonDropLogRegister();
1051
33
    EveStreamLogRegister();
1052
    /* json log */
1053
33
    OutputJsonRegister();
1054
    /* email logs */
1055
33
    JsonSmtpLogRegister();
1056
    /* http log */
1057
33
    LogHttpLogRegister();
1058
33
    JsonHttpLogRegister();
1059
33
    JsonHttp2LogRegister();
1060
    /* tls log */
1061
33
    LogTlsLogRegister();
1062
33
    JsonTlsLogRegister();
1063
33
    LogTlsStoreRegister();
1064
    /* ssh */
1065
33
    JsonSshLogRegister();
1066
    /* pcap log */
1067
33
    PcapLogRegister();
1068
    /* file log */
1069
33
    JsonFileLogRegister();
1070
33
    OutputFilestoreRegister();
1071
    /* dns */
1072
33
    JsonDnsLogRegister();
1073
    /* modbus */
1074
33
    JsonModbusLogRegister();
1075
    /* tcp streaming data */
1076
33
    LogTcpDataLogRegister();
1077
    /* log stats */
1078
33
    LogStatsLogRegister();
1079
1080
33
    JsonAlertLogRegister();
1081
33
    JsonAnomalyLogRegister();
1082
    /* flow/netflow */
1083
33
    JsonFlowLogRegister();
1084
33
    JsonNetFlowLogRegister();
1085
    /* json stats */
1086
33
    JsonStatsLogRegister();
1087
1088
    /* DNP3. */
1089
33
    JsonDNP3LogRegister();
1090
33
    JsonMetadataLogRegister();
1091
1092
    /* NFS JSON logger. */
1093
33
    JsonNFSLogRegister();
1094
    /* TFTP JSON logger. */
1095
33
    JsonTFTPLogRegister();
1096
    /* FTP JSON logger. */
1097
33
    JsonFTPLogRegister();
1098
    /* SMB JSON logger. */
1099
33
    JsonSMBLogRegister();
1100
    /* IKE JSON logger. */
1101
33
    JsonIKELogRegister();
1102
    /* KRB5 JSON logger. */
1103
33
    JsonKRB5LogRegister();
1104
    /* QUIC JSON logger. */
1105
33
    JsonQuicLogRegister();
1106
    /* DHCP JSON logger. */
1107
33
    JsonDHCPLogRegister();
1108
    /* SNMP JSON logger. */
1109
33
    JsonSNMPLogRegister();
1110
    /* SIP JSON logger. */
1111
33
    JsonSIPLogRegister();
1112
    /* RFB JSON logger. */
1113
33
    JsonRFBLogRegister();
1114
    /* MQTT JSON logger. */
1115
33
    JsonMQTTLogRegister();
1116
    /* Pgsql JSON logger. */
1117
33
    JsonPgsqlLogRegister();
1118
    /* Template JSON logger. */
1119
33
    JsonTemplateLogRegister();
1120
    /* RDP JSON logger. */
1121
33
    JsonRdpLogRegister();
1122
    /* DCERPC JSON logger. */
1123
33
    JsonDCERPCLogRegister();
1124
    /* app layer frames */
1125
33
    JsonFrameLogRegister();
1126
    /* BitTorrent DHT JSON logger */
1127
33
    JsonBitTorrentDHTLogRegister();
1128
33
}