suricata
app-layer-parser.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2025 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 Victor Julien <victor@inliniac.net>
22 *
23 * Generic App-layer parsing functions.
24 */
25
26#include "suricata-common.h"
27#include "app-layer-parser.h"
28
29#include "flow.h"
30#include "flow-private.h"
31#include "flow-util.h"
32
33#include "app-layer-frames.h"
34#include "app-layer-events.h"
35
36#include "stream-tcp.h"
37
38#include "util-validate.h"
39#include "util-config.h"
40
41#include "app-layer.h"
43
44#include "app-layer-ftp.h"
45#include "app-layer-smtp.h"
46
47#include "app-layer-smb.h"
48#include "app-layer-htp.h"
49#include "app-layer-ssl.h"
50#include "app-layer-ssh.h"
51#include "app-layer-modbus.h"
52#include "app-layer-dnp3.h"
53#include "app-layer-nfs-tcp.h"
54#include "app-layer-nfs-udp.h"
55#include "app-layer-tftp.h"
56#include "app-layer-ike.h"
57#include "app-layer-http2.h"
58#include "app-layer-imap.h"
59
61 void *(*alproto_local_storage)[FLOW_PROTO_MAX];
62};
63
64
65/**
66 * \brief App layer protocol parser context.
67 */
69{
70 /* 0 - to_server, 1 - to_client. */
72
73 bool logger;
74
75 /* Indicates the direction the parser is ready to see the data
76 * the first time for a flow. Values accepted -
77 * STREAM_TOSERVER, STREAM_TOCLIENT */
79
80 uint32_t logger_bits; /**< registered loggers for this proto */
81
82 void *(*StateAlloc)(void *, AppProto);
83 void (*StateFree)(void *);
84 void (*StateTransactionFree)(void *, uint64_t);
85 void *(*LocalStorageAlloc)(void);
86 void (*LocalStorageFree)(void *);
87
88 /** get FileContainer reference from the TX. MUST return a non-NULL reference if the TX
89 * has or may have files in the requested direction at some point. */
90 AppLayerGetFileState (*GetTxFiles)(void *, uint8_t);
91
92 int (*StateGetProgress)(void *alstate, uint8_t direction);
93 uint64_t (*StateGetTxCnt)(void *alstate);
94 void *(*StateGetTx)(void *alstate, uint64_t tx_id);
99 uint8_t event_id, const char **event_name, AppLayerEventType *event_type);
101 const char *event_name, uint8_t *event_id, AppLayerEventType *event_type);
102
103 AppLayerStateData *(*GetStateData)(void *state);
104 AppLayerTxData *(*GetTxData)(void *tx);
105 bool (*ApplyTxConfig)(void *state, void *tx, int mode, AppLayerTxConfig);
106
107 void (*SetStreamDepthFlag)(void *tx, uint8_t flags);
108
111
114
115 /* each app-layer has its own value */
116 uint32_t stream_depth;
117
118 /* Option flags such as supporting gaps or not. */
119 uint32_t option_flags;
120 /* coccinelle: AppLayerParserProtoCtx:option_flags:APP_LAYER_PARSER_OPT_ */
121
123 /* coccinelle: AppLayerParserProtoCtx:internal_flags:APP_LAYER_PARSER_INT_ */
124
125#ifdef UNITTESTS
126 void (*RegisterUnittests)(void);
127#endif
129
134
136 /* coccinelle: AppLayerParserState:flags:APP_LAYER_PARSER_ */
137 uint16_t flags;
138
139 /* Indicates the current transaction that is being inspected.
140 * We have a var per direction. */
141 uint64_t inspect_id[2];
142 /* Indicates the current transaction being logged. Unlike inspect_id,
143 * we don't need a var per direction since we don't log a transaction
144 * unless we have the entire transaction. */
145 uint64_t log_id;
146
147 uint64_t min_id;
148
149 /* Used to store decoder events. */
151
153};
154
156
157static void AppLayerConfig(void)
158{
159 g_applayerparser_error_policy = ExceptionPolicyParse("app-layer.error-policy", true);
160}
161
166
167static void AppLayerParserFramesFreeContainer(FramesContainer *frames)
168{
169 if (frames != NULL) {
170 FramesFree(&frames->toserver);
171 FramesFree(&frames->toclient);
172 SCFree(frames);
173 }
174}
175
177{
178 if (f == NULL || f->alparser == NULL || f->alparser->frames == NULL)
179 return;
180 AppLayerParserFramesFreeContainer(f->alparser->frames);
181 f->alparser->frames = NULL;
182}
183
185{
186 if (f == NULL || f->alparser == NULL)
187 return NULL;
188 return f->alparser->frames;
189}
190
192{
193#ifdef UNITTESTS
194 if (f == NULL || f->alparser == NULL || (f->proto == IPPROTO_TCP && f->protoctx == NULL))
195 return NULL;
196#endif
197 DEBUG_VALIDATE_BUG_ON(f == NULL || f->alparser == NULL);
198 if (f->alparser->frames == NULL) {
199 f->alparser->frames = SCCalloc(1, sizeof(FramesContainer));
200 if (f->alparser->frames == NULL) {
201 return NULL;
202 }
203#ifdef DEBUG
204 f->alparser->frames->toserver.ipproto = f->proto;
205 f->alparser->frames->toserver.alproto = f->alproto;
206 f->alparser->frames->toclient.ipproto = f->proto;
207 f->alparser->frames->toclient.alproto = f->alproto;
208#endif
209 }
210 return f->alparser->frames;
211}
212
213#ifdef UNITTESTS
214void UTHAppLayerParserStateGetIds(void *ptr, uint64_t *i1, uint64_t *i2, uint64_t *log, uint64_t *min)
215{
216 struct AppLayerParserState_ *s = ptr;
217 *i1 = s->inspect_id[0];
218 *i2 = s->inspect_id[1];
219 *log = s->log_id;
220 *min = s->min_id;
221}
222#endif
223
224/* Static global version of the parser context.
225 * Post 2.0 let's look at changing this to move it out to app-layer.c. */
226static AppLayerParserCtx alp_ctx;
227
228int AppLayerParserProtoIsRegistered(uint8_t ipproto, AppProto alproto)
229{
230 uint8_t ipproto_map = FlowGetProtoMapping(ipproto);
231
232 return (alp_ctx.ctxs[alproto][ipproto_map].StateAlloc != NULL) ? 1 : 0;
233}
234
236{
237 SCEnter();
238
239 AppLayerParserState *pstate = (AppLayerParserState *)SCCalloc(1, sizeof(*pstate));
240 if (pstate == NULL)
241 goto end;
242
243 end:
244 SCReturnPtr(pstate, "AppLayerParserState");
245}
246
248{
249 SCEnter();
250
251 if (pstate->decoder_events != NULL)
253 AppLayerParserFramesFreeContainer(pstate->frames);
254 SCFree(pstate);
255
256 SCReturn;
257}
258
260{
261 SCEnter();
262 // initial allocation that will later be grown using realloc,
263 // when new protocols register themselves and make g_alproto_max grow
265 if (unlikely(alp_ctx.ctxs == NULL)) {
266 FatalError("Unable to alloc alp_ctx.ctxs.");
267 }
268 alp_ctx.ctxs_len = g_alproto_max;
269 SCReturnInt(0);
270}
271
273{
274 /* lets set a default value for stream_depth */
275 for (int flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) {
276 for (AppProto alproto = 0; alproto < g_alproto_max; alproto++) {
277 if (!(alp_ctx.ctxs[alproto][flow_proto].internal_flags &
279 alp_ctx.ctxs[alproto][flow_proto].stream_depth = stream_config.reassembly_depth;
280 }
281 }
282 }
283}
284
286{
287 SCEnter();
288
289 SCFree(alp_ctx.ctxs);
290
293
294 SCReturnInt(0);
295}
296
298{
299 SCEnter();
300
301 AppLayerParserThreadCtx *tctx = SCCalloc(1, sizeof(*tctx));
302 if (tctx == NULL)
303 goto end;
304
306 if (unlikely(tctx->alproto_local_storage == NULL)) {
307 SCFree(tctx);
308 tctx = NULL;
309 goto end;
310 }
311 for (uint8_t flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) {
312 for (AppProto alproto = 0; alproto < g_alproto_max; alproto++) {
313 uint8_t ipproto = FlowGetReverseProtoMapping(flow_proto);
314
315 tctx->alproto_local_storage[alproto][flow_proto] =
317 }
318 }
319
320 end:
321 SCReturnPtr(tctx, "void *");
322}
323
325{
326 SCEnter();
327
328 for (uint8_t flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) {
329 for (AppProto alproto = 0; alproto < g_alproto_max; alproto++) {
330 uint8_t ipproto = FlowGetReverseProtoMapping(flow_proto);
331
333 ipproto, alproto, tctx->alproto_local_storage[alproto][flow_proto]);
334 }
335 }
336
338 SCFree(tctx);
339 SCReturn;
340}
341
342/** \brief check if a parser is enabled in the config
343 * Returns enabled always if: were running unittests
344 */
345int SCAppLayerParserConfParserEnabled(const char *ipproto, const char *alproto_name)
346{
347 SCEnter();
348
349 int enabled = 1;
350 char param[100];
351 SCConfNode *node;
352 int r;
353
354 if (RunmodeIsUnittests())
355 goto enabled;
356
357 r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
358 alproto_name, ".enabled");
359 if (r < 0) {
360 FatalError("snprintf failure.");
361 } else if (r > (int)sizeof(param)) {
362 FatalError("buffer not big enough to write param.");
363 }
364
365 node = SCConfGetNode(param);
366 if (node == NULL) {
367 SCLogDebug("Entry for %s not found.", param);
368 r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
369 alproto_name, ".", ipproto, ".enabled");
370 if (r < 0) {
371 FatalError("snprintf failure.");
372 } else if (r > (int)sizeof(param)) {
373 FatalError("buffer not big enough to write param.");
374 }
375
376 node = SCConfGetNode(param);
377 if (node == NULL) {
378 SCLogDebug("Entry for %s not found.", param);
379 goto enabled;
380 }
381 }
382
383 if (SCConfValIsTrue(node->val)) {
384 goto enabled;
385 } else if (SCConfValIsFalse(node->val)) {
386 goto disabled;
387 } else if (strcasecmp(node->val, "detection-only") == 0) {
388 goto disabled;
389 } else {
390 SCLogError("Invalid value found for %s.", param);
391 exit(EXIT_FAILURE);
392 }
393
394 disabled:
395 enabled = 0;
396 enabled:
397 SCReturnInt(enabled);
398}
399
400/***** Parser related registration *****/
401
402int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto,
403 uint8_t direction,
404 AppLayerParserFPtr Parser)
405{
406 SCEnter();
407
408 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)]
409 .Parser[(direction & STREAM_TOSERVER) ? 0 : 1] = Parser;
410
411 SCReturnInt(0);
412}
413
415 uint8_t ipproto, AppProto alproto, uint8_t direction)
416{
417 SCEnter();
418
419 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].first_data_dir |=
420 (direction & (STREAM_TOSERVER | STREAM_TOCLIENT));
421
422 SCReturn;
423}
424
425void AppLayerParserRegisterOptionFlags(uint8_t ipproto, AppProto alproto,
426 uint32_t flags)
427{
428 SCEnter();
429
430 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].option_flags |= flags;
431
432 SCReturn;
433}
434
435void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto,
436 void *(*StateAlloc)(void *, AppProto), void (*StateFree)(void *))
437{
438 SCEnter();
439
440 if (alp_ctx.ctxs_len <= alproto && alproto < g_alproto_max) {
441 // Realloc now as AppLayerParserRegisterStateFuncs is called first
442 void *tmp = SCRealloc(
444 if (unlikely(tmp == NULL)) {
445 FatalError("Unable to realloc alp_ctx.ctxs.");
446 }
447 alp_ctx.ctxs = tmp;
448 memset(&alp_ctx.ctxs[alp_ctx.ctxs_len], 0,
450 (g_alproto_max - alp_ctx.ctxs_len));
451 alp_ctx.ctxs_len = g_alproto_max;
452 }
453
454 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateAlloc = StateAlloc;
455 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateFree = StateFree;
456
457 SCReturn;
458}
459
461 void *(*LocalStorageAlloc)(void),
462 void (*LocalStorageFree)(void *))
463{
464 SCEnter();
465
466 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].LocalStorageAlloc = LocalStorageAlloc;
467 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].LocalStorageFree = LocalStorageFree;
468
469 SCReturn;
470}
471
473 uint8_t ipproto, AppProto alproto, AppLayerGetFileState (*GetTxFiles)(void *, uint8_t))
474{
475 SCEnter();
476
477 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetTxFiles = GetTxFiles;
478
479 SCReturn;
480}
481
482void AppLayerParserRegisterLoggerBits(uint8_t ipproto, AppProto alproto, LoggerId bits)
483{
484 SCEnter();
485
486 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].logger_bits = bits;
487
488 SCReturn;
489}
490
491void SCAppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto)
492{
493 SCEnter();
494
495 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].logger = true;
496
497 SCReturn;
498}
499
501 int (*StateGetProgress)(void *alstate, uint8_t direction))
502{
503 SCEnter();
504
505 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateGetProgress = StateGetProgress;
506
507 SCReturn;
508}
509
510void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto,
511 void (*StateTransactionFree)(void *, uint64_t))
512{
513 SCEnter();
514
515 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateTransactionFree = StateTransactionFree;
516
517 SCReturn;
518}
519
520void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto,
521 uint64_t (*StateGetTxCnt)(void *alstate))
522{
523 SCEnter();
524
525 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateGetTxCnt = StateGetTxCnt;
526
527 SCReturn;
528}
529
530void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto,
531 void *(StateGetTx)(void *alstate, uint64_t tx_id))
532{
533 SCEnter();
534
535 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateGetTx = StateGetTx;
536
537 SCReturn;
538}
539
540void AppLayerParserRegisterGetTxIterator(uint8_t ipproto, AppProto alproto,
542{
543 SCEnter();
544 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateGetTxIterator = Func;
545 SCReturn;
546}
547
549 AppProto alproto, const int ts, const int tc)
550{
551 BUG_ON(ts == 0);
552 BUG_ON(tc == 0);
553 BUG_ON(!AppProtoIsValid(alproto));
554 BUG_ON(alp_ctx.ctxs[alproto][FLOW_PROTO_DEFAULT].complete_ts != 0 &&
555 alp_ctx.ctxs[alproto][FLOW_PROTO_DEFAULT].complete_ts != ts);
556 BUG_ON(alp_ctx.ctxs[alproto][FLOW_PROTO_DEFAULT].complete_tc != 0 &&
557 alp_ctx.ctxs[alproto][FLOW_PROTO_DEFAULT].complete_tc != tc);
558
559 alp_ctx.ctxs[alproto][FLOW_PROTO_DEFAULT].complete_ts = ts;
560 alp_ctx.ctxs[alproto][FLOW_PROTO_DEFAULT].complete_tc = tc;
561}
562
564 int (*StateGetEventInfoById)(
565 uint8_t event_id, const char **event_name, AppLayerEventType *event_type))
566{
567 SCEnter();
568
569 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateGetEventInfoById =
570 StateGetEventInfoById;
571
572 SCReturn;
573}
574
575void AppLayerParserRegisterGetStateFuncs(uint8_t ipproto, AppProto alproto,
576 AppLayerParserGetStateIdByNameFn GetIdByNameFunc,
577 AppLayerParserGetStateNameByIdFn GetNameByIdFunc)
578{
579 SCEnter();
580 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetStateIdByName = GetIdByNameFunc;
581 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetStateNameById = GetNameByIdFunc;
582 SCReturn;
583}
584
585void AppLayerParserRegisterGetFrameFuncs(uint8_t ipproto, AppProto alproto,
586 AppLayerParserGetFrameIdByNameFn GetIdByNameFunc,
587 AppLayerParserGetFrameNameByIdFn GetNameByIdFunc)
588{
589 SCEnter();
590 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetFrameIdByName = GetIdByNameFunc;
591 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetFrameNameById = GetNameByIdFunc;
592 SCReturn;
593}
594
595void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto,
596 int (*StateGetEventInfo)(
597 const char *event_name, uint8_t *event_id, AppLayerEventType *event_type))
598{
599 SCEnter();
600
601 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateGetEventInfo = StateGetEventInfo;
602
603 SCReturn;
604}
605
606void AppLayerParserRegisterTxDataFunc(uint8_t ipproto, AppProto alproto,
607 AppLayerTxData *(*GetTxData)(void *tx))
608{
609 SCEnter();
610
611 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetTxData = GetTxData;
612
613 SCReturn;
614}
615
617 uint8_t ipproto, AppProto alproto, AppLayerStateData *(*GetStateData)(void *state))
618{
619 SCEnter();
620
621 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetStateData = GetStateData;
622
623 SCReturn;
624}
625
627 bool (*ApplyTxConfig)(void *state, void *tx, int mode, AppLayerTxConfig))
628{
629 SCEnter();
630
631 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].ApplyTxConfig = ApplyTxConfig;
632
633 SCReturn;
634}
635
637 void (*SetStreamDepthFlag)(void *tx, uint8_t flags))
638{
639 SCEnter();
640
641 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].SetStreamDepthFlag = SetStreamDepthFlag;
642
643 SCReturn;
644}
645
646/***** Get and transaction functions *****/
647
649{
650 SCEnter();
651 void * r = NULL;
652
653 if (alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].LocalStorageAlloc != NULL) {
654 r = alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].LocalStorageAlloc();
655 }
656
657 SCReturnPtr(r, "void *");
658}
659
661 void *local_data)
662{
663 SCEnter();
664
665 if (alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].LocalStorageFree != NULL) {
666 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].LocalStorageFree(local_data);
667 }
668
669 SCReturn;
670}
671
672/** \brief default tx iterator
673 *
674 * Used if the app layer parser doesn't register its own iterator.
675 * Simply walks the tx_id space until it finds a tx. Uses 'state' to
676 * keep track of where it left off.
677 *
678 * \retval txptr or NULL if no more txs in list
679 */
680static AppLayerGetTxIterTuple AppLayerDefaultGetTxIterator(
681 const uint8_t ipproto, const AppProto alproto,
682 void *alstate, uint64_t min_tx_id, uint64_t max_tx_id,
684{
685 uint64_t ustate = *(uint64_t *)state;
686 uint64_t tx_id = MAX(min_tx_id, ustate);
687 for ( ; tx_id < max_tx_id; tx_id++) {
688 void *tx_ptr = AppLayerParserGetTx(ipproto, alproto, alstate, tx_id);
689 if (tx_ptr != NULL) {
690 ustate = tx_id + 1;
691 *state = *(AppLayerGetTxIterState *)&ustate;
692 AppLayerGetTxIterTuple tuple = {
693 .tx_ptr = tx_ptr,
694 .tx_id = tx_id,
695 .has_next = (tx_id + 1 < max_tx_id),
696 };
697 SCLogDebug("tuple: %p/%"PRIu64"/%s", tuple.tx_ptr, tuple.tx_id,
698 tuple.has_next ? "true" : "false");
699 return tuple;
700 }
701 }
702
703 AppLayerGetTxIterTuple no_tuple = { NULL, 0, false };
704 return no_tuple;
705}
706
708 const AppProto alproto)
709{
711 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateGetTxIterator;
712 return Func ? Func : AppLayerDefaultGetTxIterator;
713}
714
716{
717 SCEnter();
718
719 SCReturnCT((pstate == NULL) ? 0 : pstate->log_id, "uint64_t");
720}
721
723{
724 SCEnter();
725
726 if (pstate != NULL)
727 pstate->log_id = tx_id;
728
729 SCReturn;
730}
731
733{
734 SCEnter();
735
736 if (pstate != NULL)
737 SCReturnCT(pstate->inspect_id[(direction & STREAM_TOSERVER) ? 0 : 1], "uint64_t");
738
740 SCReturnCT(0ULL, "uint64_t");
741}
742
743inline uint8_t AppLayerParserGetTxDetectProgress(AppLayerTxData *txd, const uint8_t dir)
744{
745 uint8_t p = (dir & STREAM_TOSERVER) ? txd->detect_progress_ts : txd->detect_progress_tc;
746 return p;
747}
748
749static inline uint32_t GetTxLogged(AppLayerTxData *txd)
750{
751 return txd->logged.flags;
752}
753
755 void *alstate, const uint8_t flags,
756 bool tag_txs_as_inspected)
757{
758 SCEnter();
759
760 const int direction = (flags & STREAM_TOSERVER) ? 0 : 1;
761 const uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
762 uint64_t idx = AppLayerParserGetTransactionInspectId(pstate, flags);
763 const int state_done_progress = AppLayerParserGetStateProgressCompletionStatus(f->alproto, flags);
764 const uint8_t ipproto = f->proto;
765 const AppProto alproto = f->alproto;
766
767 AppLayerGetTxIteratorFunc IterFunc = AppLayerGetTxIterator(ipproto, alproto);
768 AppLayerGetTxIterState state = { 0 };
769
770 SCLogDebug("called: %s, tag_txs_as_inspected %s",direction==0?"toserver":"toclient",
771 tag_txs_as_inspected?"true":"false");
772
773 /* mark all txs as inspected if the applayer progress is
774 * at the 'end state'. */
775 while (1) {
776 AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, idx, total_txs, &state);
777 if (ires.tx_ptr == NULL)
778 break;
779
780 void *tx = ires.tx_ptr;
781 idx = ires.tx_id;
782
783 int state_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx, flags);
784 if (state_progress < state_done_progress)
785 break;
786
787 AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
788 if (tag_txs_as_inspected) {
789 const uint8_t inspected_flag = (flags & STREAM_TOSERVER) ? APP_LAYER_TX_INSPECTED_TS
791 if (txd->flags & inspected_flag) {
792 txd->flags |= inspected_flag;
793 SCLogDebug("%p/%" PRIu64 " in-order tx is done for direction %s. Flags %02x", tx,
794 idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", txd->flags);
795 }
796 }
797 idx++;
798 if (!ires.has_next)
799 break;
800 }
801 pstate->inspect_id[direction] = idx;
802 SCLogDebug("inspect_id now %"PRIu64, pstate->inspect_id[direction]);
803
804 /* if necessary we flag all txs that are complete as 'inspected'
805 * also move inspect_id forward. */
806 if (tag_txs_as_inspected) {
807 /* continue at idx */
808 while (1) {
809 AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, idx, total_txs, &state);
810 if (ires.tx_ptr == NULL)
811 break;
812
813 void *tx = ires.tx_ptr;
814 /* if we got a higher id than the minimum we requested, we
815 * skipped a bunch of 'null-txs'. Lets see if we can up the
816 * inspect tracker */
817 if (ires.tx_id > idx && pstate->inspect_id[direction] == idx) {
818 pstate->inspect_id[direction] = ires.tx_id;
819 }
820 idx = ires.tx_id;
821
822 const int state_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx, flags);
823 if (state_progress < state_done_progress)
824 break;
825
826 /* txd can be NULL for HTTP sessions where the user data alloc failed */
827 AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
828 const uint8_t inspected_flag = (flags & STREAM_TOSERVER) ? APP_LAYER_TX_INSPECTED_TS
830 if (txd->flags & inspected_flag) {
831 txd->flags |= inspected_flag;
832 SCLogDebug("%p/%" PRIu64 " out of order tx is done for direction %s. Flag %02x", tx,
833 idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", txd->flags);
834
835 SCLogDebug("%p/%" PRIu64 " out of order tx. Update inspect_id? %" PRIu64, tx, idx,
836 pstate->inspect_id[direction]);
837 if (pstate->inspect_id[direction] + 1 == idx)
838 pstate->inspect_id[direction] = idx;
839 }
840 if (!ires.has_next)
841 break;
842 idx++;
843 }
844 }
845
846 SCReturn;
847}
848
850{
851 SCEnter();
852
854 "AppLayerDecoderEvents *");
855}
856
858 void *tx)
859{
860 SCEnter();
861
862 AppLayerDecoderEvents *ptr = NULL;
863
864 /* Access events via the tx_data. */
865 AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
866 if (txd->events != NULL) {
867 ptr = txd->events;
868 }
869
870 SCReturnPtr(ptr, "AppLayerDecoderEvents *");
871}
872
873AppLayerGetFileState AppLayerParserGetTxFiles(const Flow *f, void *tx, const uint8_t direction)
874{
875 SCEnter();
876
877 if (alp_ctx.ctxs[f->alproto][f->protomap].GetTxFiles != NULL) {
878 return alp_ctx.ctxs[f->alproto][f->protomap].GetTxFiles(tx, direction);
879 }
880
881 AppLayerGetFileState files = { .fc = NULL, .cfg = NULL };
882 return files;
883}
884
885static void AppLayerParserFileTxHousekeeping(
886 const Flow *f, void *tx, const uint8_t pkt_dir, const bool trunc)
887{
888 AppLayerGetFileState files = AppLayerParserGetTxFiles(f, tx, pkt_dir);
889 if (files.fc) {
890 FilesPrune(files.fc, files.cfg, trunc);
891 }
892}
893
894#define IS_DISRUPTED(flags) ((flags) & (STREAM_DEPTH | STREAM_GAP))
895
896extern int g_detect_disabled;
897extern bool g_file_logger_enabled;
898extern bool g_filedata_logger_enabled;
899
900/**
901 * \brief remove obsolete (inspected and logged) transactions
902 */
903void AppLayerParserTransactionsCleanup(Flow *f, const uint8_t pkt_dir)
904{
905 SCEnter();
907
908 AppLayerParserProtoCtx *p = &alp_ctx.ctxs[f->alproto][f->protomap];
909 if (unlikely(p->StateTransactionFree == NULL))
910 SCReturn;
911
912 const bool has_tx_detect_flags = !g_detect_disabled;
913 const uint8_t ipproto = f->proto;
914 const AppProto alproto = f->alproto;
915 void * const alstate = f->alstate;
916 AppLayerParserState * const alparser = f->alparser;
917
918 if (alstate == NULL || alparser == NULL)
919 SCReturn;
920
921 const uint64_t min = alparser->min_id;
922 const uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
923 const LoggerId logger_expectation = AppLayerParserProtocolGetLoggerBits(ipproto, alproto);
924 const int tx_end_state_ts = AppLayerParserGetStateProgressCompletionStatus(alproto, STREAM_TOSERVER);
925 const int tx_end_state_tc = AppLayerParserGetStateProgressCompletionStatus(alproto, STREAM_TOCLIENT);
926 const uint8_t ts_disrupt_flags = FlowGetDisruptionFlags(f, STREAM_TOSERVER);
927 const uint8_t tc_disrupt_flags = FlowGetDisruptionFlags(f, STREAM_TOCLIENT);
928
929 int pkt_dir_trunc = -1;
930
931 AppLayerGetTxIteratorFunc IterFunc = AppLayerGetTxIterator(ipproto, alproto);
933 memset(&state, 0, sizeof(state));
934 uint64_t i = min;
935 uint64_t new_min = min;
936 SCLogDebug("start min %"PRIu64, min);
937 bool skipped = false;
938 // const bool support_files = AppLayerParserSupportsFiles(f->proto, f->alproto);
939
940 while (1) {
941 AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, i, total_txs, &state);
942 if (ires.tx_ptr == NULL)
943 break;
944
945 bool tx_skipped = false;
946 void *tx = ires.tx_ptr;
947 i = ires.tx_id; // actual tx id for the tx the IterFunc returned
948
949 SCLogDebug("%p/%"PRIu64" checking", tx, i);
950 AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
951 if (AppLayerParserHasFilesInDir(txd, pkt_dir)) {
952 if (pkt_dir_trunc == -1)
953 pkt_dir_trunc = IS_DISRUPTED(
954 (pkt_dir == STREAM_TOSERVER) ? ts_disrupt_flags : tc_disrupt_flags);
955 AppLayerParserFileTxHousekeeping(f, tx, pkt_dir, (bool)pkt_dir_trunc);
956 }
957 // should be reset by parser next time it updates the tx
958 if (pkt_dir & STREAM_TOSERVER) {
959 txd->updated_ts = false;
960 } else {
961 txd->updated_tc = false;
962 }
963 const int tx_progress_tc =
964 AppLayerParserGetStateProgress(ipproto, alproto, tx, tc_disrupt_flags);
965 if (tx_progress_tc < tx_end_state_tc) {
966 SCLogDebug("%p/%"PRIu64" skipping: tc parser not done", tx, i);
967 skipped = true;
968 goto next;
969 }
970 const int tx_progress_ts =
971 AppLayerParserGetStateProgress(ipproto, alproto, tx, ts_disrupt_flags);
972 if (tx_progress_ts < tx_end_state_ts) {
973 SCLogDebug("%p/%"PRIu64" skipping: ts parser not done", tx, i);
974 skipped = true;
975 goto next;
976 }
977
978 if (has_tx_detect_flags) {
979 if (!IS_DISRUPTED(ts_disrupt_flags) &&
980 (f->sgh_toserver != NULL || (f->flags & FLOW_SGH_TOSERVER) == 0)) {
982 0) {
983 SCLogDebug("%p/%" PRIu64 " skipping: TS inspect not done: ts:%02x", tx, i,
984 txd->flags);
985 tx_skipped = true;
986 }
987 }
988 if (!IS_DISRUPTED(tc_disrupt_flags) &&
989 (f->sgh_toclient != NULL || (f->flags & FLOW_SGH_TOCLIENT) == 0)) {
991 0) {
992 SCLogDebug("%p/%" PRIu64 " skipping: TC inspect not done: ts:%02x", tx, i,
993 txd->flags);
994 tx_skipped = true;
995 }
996 }
997 }
998
999 if (tx_skipped) {
1000 SCLogDebug("%p/%" PRIu64 " tx_skipped", tx, i);
1001 skipped = true;
1002 goto next;
1003 }
1004
1005 if (logger_expectation != 0) {
1006 LoggerId tx_logged = GetTxLogged(txd);
1007 if (tx_logged != logger_expectation) {
1008 SCLogDebug("%p/%"PRIu64" skipping: logging not done: want:%"PRIx32", have:%"PRIx32,
1009 tx, i, logger_expectation, tx_logged);
1010 skipped = true;
1011 goto next;
1012 }
1013 }
1014
1015 /* if file logging is enabled, we keep a tx active while some of the files aren't
1016 * logged yet. */
1017 SCLogDebug("files_opened %u files_logged %u files_stored %u", txd->files_opened,
1018 txd->files_logged, txd->files_stored);
1019
1020 if (txd->files_opened) {
1021 if (g_file_logger_enabled && txd->files_opened != txd->files_logged) {
1022 skipped = true;
1023 goto next;
1024 }
1025 if (g_filedata_logger_enabled && txd->files_opened != txd->files_stored) {
1026 skipped = true;
1027 goto next;
1028 }
1029 }
1030
1031 /* if we are here, the tx can be freed. */
1032 p->StateTransactionFree(alstate, i);
1033 SCLogDebug("%p/%"PRIu64" freed", tx, i);
1034
1035 /* if we didn't skip any tx so far, up the minimum */
1036 SCLogDebug("skipped? %s i %"PRIu64", new_min %"PRIu64, skipped ? "true" : "false", i, new_min);
1037 if (!skipped)
1038 new_min = i + 1;
1039 SCLogDebug("final i %"PRIu64", new_min %"PRIu64, i, new_min);
1040
1041next:
1042 if (!ires.has_next) {
1043 /* this was the last tx. See if we skipped any. If not
1044 * we removed all and can update the minimum to the max
1045 * id. */
1046 SCLogDebug("no next: cur tx i %"PRIu64", total %"PRIu64, i, total_txs);
1047 if (!skipped) {
1048 new_min = total_txs;
1049 SCLogDebug("no next: cur tx i %"PRIu64", total %"PRIu64": "
1050 "new_min updated to %"PRIu64, i, total_txs, new_min);
1051 }
1052 break;
1053 }
1054 i++;
1055 }
1056
1057 /* see if we need to bring all trackers up to date. */
1058 SCLogDebug("update f->alparser->min_id? %"PRIu64" vs %"PRIu64, new_min, alparser->min_id);
1059 if (new_min > alparser->min_id) {
1060 const uint64_t next_id = new_min;
1061 alparser->min_id = next_id;
1062 alparser->inspect_id[0] = MAX(alparser->inspect_id[0], next_id);
1063 alparser->inspect_id[1] = MAX(alparser->inspect_id[1], next_id);
1064 alparser->log_id = MAX(alparser->log_id, next_id);
1065 SCLogDebug("updated f->alparser->min_id %"PRIu64, alparser->min_id);
1066 }
1067 SCReturn;
1068}
1069
1070static inline int StateGetProgressCompletionStatus(const AppProto alproto, const uint8_t flags)
1071{
1072 if (flags & STREAM_TOSERVER) {
1073 return alp_ctx.ctxs[alproto][FLOW_PROTO_DEFAULT].complete_ts;
1074 } else if (flags & STREAM_TOCLIENT) {
1075 return alp_ctx.ctxs[alproto][FLOW_PROTO_DEFAULT].complete_tc;
1076 } else {
1078 return 0;
1079 }
1080}
1081
1082/**
1083 * \brief get the progress value for a tx/protocol
1084 *
1085 * If the stream is disrupted, we return the 'completion' value.
1086 */
1087int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto,
1088 void *alstate, uint8_t flags)
1089{
1090 SCEnter();
1091 int r;
1092 if (unlikely(IS_DISRUPTED(flags))) {
1093 r = StateGetProgressCompletionStatus(alproto, flags);
1094 } else {
1095 uint8_t direction = flags & (STREAM_TOCLIENT | STREAM_TOSERVER);
1096 r = alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateGetProgress(
1097 alstate, direction);
1098 }
1099 SCReturnInt(r);
1100}
1101
1102uint64_t AppLayerParserGetTxCnt(const Flow *f, void *alstate)
1103{
1104 SCEnter();
1105 uint64_t r = alp_ctx.ctxs[f->alproto][f->protomap].StateGetTxCnt(alstate);
1106 SCReturnCT(r, "uint64_t");
1107}
1108
1109void *AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
1110{
1111 SCEnter();
1112 void *r = alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateGetTx(alstate, tx_id);
1113 SCReturnPtr(r, "void *");
1114}
1115
1117 uint8_t direction)
1118{
1119 SCEnter();
1120 int r = StateGetProgressCompletionStatus(alproto, direction);
1121 SCReturnInt(r);
1122}
1123
1124int AppLayerParserGetEventInfo(uint8_t ipproto, AppProto alproto, const char *event_name,
1125 uint8_t *event_id, AppLayerEventType *event_type)
1126{
1127 SCEnter();
1128 const int ipproto_map = FlowGetProtoMapping(ipproto);
1129 int r = (alp_ctx.ctxs[alproto][ipproto_map].StateGetEventInfo == NULL)
1130 ? -1
1131 : alp_ctx.ctxs[alproto][ipproto_map].StateGetEventInfo(
1132 event_name, event_id, event_type);
1133 SCReturnInt(r);
1134}
1135
1136int AppLayerParserGetEventInfoById(uint8_t ipproto, AppProto alproto, uint8_t event_id,
1137 const char **event_name, AppLayerEventType *event_type)
1138{
1139 SCEnter();
1140 const int ipproto_map = FlowGetProtoMapping(ipproto);
1141 *event_name = (const char *)NULL;
1142 int r = (alp_ctx.ctxs[alproto][ipproto_map].StateGetEventInfoById == NULL)
1143 ? -1
1144 : alp_ctx.ctxs[alproto][ipproto_map].StateGetEventInfoById(
1145 event_id, event_name, event_type);
1146 SCReturnInt(r);
1147}
1148
1149uint8_t AppLayerParserGetFirstDataDir(uint8_t ipproto, AppProto alproto)
1150{
1151 SCEnter();
1152 uint8_t r = alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].first_data_dir;
1153 SCReturnCT(r, "uint8_t");
1154}
1155
1157 AppLayerParserState *pstate, uint8_t direction)
1158{
1159 SCEnter();
1160
1161 uint64_t active_id;
1162 uint64_t log_id = pstate->log_id;
1163 uint64_t inspect_id = pstate->inspect_id[(direction & STREAM_TOSERVER) ? 0 : 1];
1164 if (alp_ctx.ctxs[f->alproto][f->protomap].logger) {
1165 active_id = MIN(log_id, inspect_id);
1166 } else {
1167 active_id = inspect_id;
1168 }
1169
1170 SCReturnCT(active_id, "uint64_t");
1171}
1172
1173bool AppLayerParserSupportsFiles(uint8_t ipproto, AppProto alproto)
1174{
1175 // Custom case for only signature-only protocol so far
1176 if (alproto == ALPROTO_HTTP) {
1177 return AppLayerParserSupportsFiles(ipproto, ALPROTO_HTTP1) ||
1179 }
1180 return alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetTxFiles != NULL;
1181}
1182
1183AppLayerTxData *AppLayerParserGetTxData(uint8_t ipproto, AppProto alproto, void *tx)
1184{
1185 SCEnter();
1186 AppLayerTxData *d = alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetTxData(tx);
1187 SCReturnPtr(d, "AppLayerTxData");
1188}
1189
1190AppLayerStateData *AppLayerParserGetStateData(uint8_t ipproto, AppProto alproto, void *state)
1191{
1192 SCEnter();
1193 if (alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetStateData) {
1195 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetStateData(state);
1196 SCReturnPtr(d, "AppLayerStateData");
1197 }
1198 SCReturnPtr(NULL, "AppLayerStateData");
1199}
1200
1201void AppLayerParserApplyTxConfig(uint8_t ipproto, AppProto alproto,
1202 void *state, void *tx, enum ConfigAction mode, AppLayerTxConfig config)
1203{
1204 SCEnter();
1205 const int ipproto_map = FlowGetProtoMapping(ipproto);
1206 if (alp_ctx.ctxs[alproto][ipproto_map].ApplyTxConfig) {
1207 alp_ctx.ctxs[alproto][ipproto_map].ApplyTxConfig(state, tx, mode, config);
1208 }
1209 SCReturn;
1210}
1211
1212/***** General *****/
1213
1214static inline void SetEOFFlags(AppLayerParserState *pstate, const uint8_t flags)
1215{
1216 if ((flags & (STREAM_EOF|STREAM_TOSERVER)) == (STREAM_EOF|STREAM_TOSERVER)) {
1217 SCLogDebug("setting APP_LAYER_PARSER_EOF_TS");
1219 } else if ((flags & (STREAM_EOF|STREAM_TOCLIENT)) == (STREAM_EOF|STREAM_TOCLIENT)) {
1220 SCLogDebug("setting APP_LAYER_PARSER_EOF_TC");
1222 }
1223}
1224
1225/** \internal
1226 * \brief create/close stream frames
1227 * On first invocation of TCP parser in a direction, create a <alproto>.stream frame.
1228 * On STREAM_EOF, set the final length. */
1229static void HandleStreamFrames(Flow *f, StreamSlice stream_slice, const uint8_t *input,
1230 const uint32_t input_len, const uint8_t flags)
1231{
1232 const uint8_t direction = (flags & STREAM_TOSERVER) ? 0 : 1;
1233 AppLayerParserState *pstate = f->alparser;
1234
1235 /* setup the generic stream frame */
1236 if (((direction == 0 && (pstate->flags & APP_LAYER_PARSER_SFRAME_TS) == 0) ||
1237 (direction == 1 && (pstate->flags & APP_LAYER_PARSER_SFRAME_TC) == 0)) &&
1238 input != NULL && f->proto == IPPROTO_TCP) {
1240 if (frame == NULL) {
1241 int64_t frame_len = -1;
1242 if (flags & STREAM_EOF)
1243 frame_len = input_len;
1244
1246 f, &stream_slice, stream_slice.offset, frame_len, direction, FRAME_STREAM_TYPE);
1247 if (frame) {
1248 SCLogDebug("opened: frame %p id %" PRIi64, frame, frame->id);
1249 frame->flags = FRAME_FLAG_ENDS_AT_EOF; // TODO logic is not yet implemented
1251 frame->id != 1); // should always be the first frame that is created
1252 }
1253 if (direction == 0) {
1255 } else {
1257 }
1258 }
1259 } else if (flags & STREAM_EOF) {
1261 SCLogDebug("EOF closing: frame %p", frame);
1262 if (frame) {
1263 /* calculate final frame length */
1264 int64_t slice_o = (int64_t)stream_slice.offset - (int64_t)frame->offset;
1265 int64_t frame_len = slice_o + (int64_t)input_len;
1266 SCLogDebug("%s: EOF frame->offset %" PRIu64 " -> %" PRIi64 ": o %" PRIi64,
1267 AppProtoToString(f->alproto), frame->offset, frame_len, slice_o);
1268 frame->len = frame_len;
1269 }
1270 }
1271}
1272
1273static void Setup(Flow *f, const uint8_t direction, const uint8_t *input, uint32_t input_len,
1274 const uint8_t flags, StreamSlice *as)
1275{
1276 memset(as, 0, sizeof(*as));
1277 as->input = input;
1278 as->input_len = input_len;
1279 as->flags = flags;
1280
1281 if (f->proto == IPPROTO_TCP && f->protoctx != NULL) {
1282 TcpSession *ssn = f->protoctx;
1283 TcpStream *stream = (direction & STREAM_TOSERVER) ? &ssn->client : &ssn->server;
1284 as->offset = STREAM_APP_PROGRESS(stream);
1285 }
1286}
1287
1288/** \retval int -1 in case of unrecoverable error. App-layer tracking stops for this flow.
1289 * \retval int 0 ok: we did not update app_progress
1290 * \retval int 1 ok: we updated app_progress */
1292 uint8_t flags, const uint8_t *input, uint32_t input_len)
1293{
1294 SCEnter();
1295#ifdef DEBUG_VALIDATION
1297#endif
1298 AppLayerParserState *pstate = f->alparser;
1299 AppLayerParserProtoCtx *p = &alp_ctx.ctxs[alproto][f->protomap];
1300 StreamSlice stream_slice;
1301 void *alstate = NULL;
1302 uint64_t p_tx_cnt = 0;
1303 uint32_t consumed = input_len;
1304 const uint8_t direction = (flags & STREAM_TOSERVER) ? 0 : 1;
1305
1306 /* we don't have the parser registered for this protocol */
1307 if (p->StateAlloc == NULL) {
1308 if (f->proto == IPPROTO_TCP) {
1310 }
1311 goto end;
1312 }
1313
1314 if (flags & STREAM_GAP) {
1316 SCLogDebug("app-layer parser does not accept gaps");
1317 if (f->alstate != NULL && !FlowChangeProto(f)) {
1319 }
1321 goto error;
1322 }
1323 }
1324
1325 /* Get the parser state (if any) */
1326 if (pstate == NULL) {
1327 f->alparser = pstate = AppLayerParserStateAlloc();
1328 if (pstate == NULL) {
1330 goto error;
1331 }
1332 }
1333
1334 SetEOFFlags(pstate, flags);
1335
1336 alstate = f->alstate;
1337 if (alstate == NULL || FlowChangeProto(f)) {
1338 f->alstate = alstate = p->StateAlloc(alstate, f->alproto_orig);
1339 if (alstate == NULL) {
1341 goto error;
1342 }
1343 SCLogDebug("alloced new app layer state %p (name %s)",
1344 alstate, AppLayerGetProtoName(f->alproto));
1345
1346 /* set flow flags to state */
1347 if (f->file_flags != 0) {
1349 if (sd != NULL) {
1350 if ((sd->file_flags & f->file_flags) != f->file_flags) {
1351 SCLogDebug("state data: updating file_flags %04x with flow file_flags %04x",
1352 sd->file_flags, f->file_flags);
1353 sd->file_flags |= f->file_flags;
1354 }
1355 }
1356 }
1357 } else {
1358 SCLogDebug("using existing app layer state %p (name %s))",
1359 alstate, AppLayerGetProtoName(f->alproto));
1360 }
1361
1362 p_tx_cnt = AppLayerParserGetTxCnt(f, f->alstate);
1363
1364 /* invoke the recursive parser, but only on data. We may get empty msgs on EOF */
1365 if (input_len > 0 || (flags & STREAM_EOF)) {
1366 Setup(f, flags & (STREAM_TOSERVER | STREAM_TOCLIENT), input, input_len, flags,
1367 &stream_slice);
1368 HandleStreamFrames(f, stream_slice, input, input_len, flags);
1369
1370#ifdef DEBUG
1371 if (((stream_slice.flags & STREAM_TOSERVER) &&
1372 stream_slice.offset >= g_eps_applayer_error_offset_ts)) {
1373 SCLogNotice("putting parser %s into an error state from toserver offset %" PRIu64,
1374 AppProtoToString(alproto), g_eps_applayer_error_offset_ts);
1376 goto error;
1377 }
1378 if (((stream_slice.flags & STREAM_TOCLIENT) &&
1379 stream_slice.offset >= g_eps_applayer_error_offset_tc)) {
1380 SCLogNotice("putting parser %s into an error state from toclient offset %" PRIu64,
1381 AppProtoToString(alproto), g_eps_applayer_error_offset_tc);
1383 goto error;
1384 }
1385#endif
1386 /* invoke the parser */
1387 AppLayerResult res = p->Parser[direction](f, alstate, pstate, stream_slice,
1389 if (res.status < 0) {
1391 goto error;
1392 } else if (res.status > 0) {
1393 DEBUG_VALIDATE_BUG_ON(res.consumed > input_len);
1394 DEBUG_VALIDATE_BUG_ON(res.needed + res.consumed < input_len);
1395 DEBUG_VALIDATE_BUG_ON(res.needed == 0);
1396 /* incomplete is only supported for TCP */
1397 DEBUG_VALIDATE_BUG_ON(f->proto != IPPROTO_TCP);
1398
1399 /* put protocol in error state on improper use of the
1400 * return codes. */
1401 if (res.consumed > input_len || res.needed + res.consumed < input_len) {
1403 goto error;
1404 }
1405
1406 if (f->proto == IPPROTO_TCP && f->protoctx != NULL) {
1407 TcpSession *ssn = f->protoctx;
1408 SCLogDebug("direction %d/%s", direction,
1409 (flags & STREAM_TOSERVER) ? "toserver" : "toclient");
1410 if (direction == 0) {
1411 /* parser told us how much data it needs on top of what it
1412 * consumed. So we need tell stream engine how much we need
1413 * before the next call */
1414 ssn->client.data_required = res.needed;
1415 SCLogDebug("setting data_required %u", ssn->client.data_required);
1416 } else {
1417 /* parser told us how much data it needs on top of what it
1418 * consumed. So we need tell stream engine how much we need
1419 * before the next call */
1420 ssn->server.data_required = res.needed;
1421 SCLogDebug("setting data_required %u", ssn->server.data_required);
1422 }
1423 }
1424 consumed = res.consumed;
1425 }
1426 }
1427
1428 /* set the packets to no inspection and reassembly if required */
1429 if (pstate->flags & APP_LAYER_PARSER_NO_INSPECTION) {
1430 AppLayerParserSetEOF(pstate);
1431
1432 if (f->proto == IPPROTO_TCP) {
1434
1435 /* Set the no reassembly flag for both the stream in this TcpSession */
1436 if (pstate->flags & APP_LAYER_PARSER_NO_REASSEMBLY) {
1437 /* Used only if it's TCP */
1438 TcpSession *ssn = f->protoctx;
1439 if (ssn != NULL) {
1442 }
1443 }
1444 /* Set the bypass flag for both the stream in this TcpSession */
1445 if (pstate->flags & APP_LAYER_PARSER_BYPASS_READY) {
1446 /* Used only if it's TCP */
1447 TcpSession *ssn = f->protoctx;
1448 if (ssn != NULL) {
1450 }
1451 }
1452 } else {
1453 // for TCP, this is set after flushing
1454 FlowSetNoPayloadInspectionFlag(f);
1455 }
1456 }
1457
1458 /* In cases like HeartBleed for TLS we need to inspect AppLayer but not Payload */
1460 FlowSetNoPayloadInspectionFlag(f);
1461 /* Set the no reassembly flag for both the stream in this TcpSession */
1462 if (f->proto == IPPROTO_TCP) {
1463 /* Used only if it's TCP */
1464 TcpSession *ssn = f->protoctx;
1465 if (ssn != NULL) {
1468 }
1469 }
1470 }
1471
1472 /* get the diff in tx cnt for stats keeping */
1473 uint64_t cur_tx_cnt = AppLayerParserGetTxCnt(f, f->alstate);
1474 if (cur_tx_cnt > p_tx_cnt && tv) {
1475 AppLayerIncTxCounter(tv, f, cur_tx_cnt - p_tx_cnt);
1476 }
1477
1478 end:
1479 /* update app progress */
1480 if (consumed != input_len && f->proto == IPPROTO_TCP && f->protoctx != NULL) {
1481 TcpSession *ssn = f->protoctx;
1482 StreamTcpUpdateAppLayerProgress(ssn, direction, consumed);
1483 SCReturnInt(1);
1484 }
1485
1486 SCReturnInt(0);
1487 error:
1488 /* Set the no app layer inspection flag for both
1489 * the stream in this Flow */
1490 if (f->proto == IPPROTO_TCP) {
1492 }
1493 AppLayerParserSetEOF(pstate);
1494 SCReturnInt(-1);
1495}
1496
1498{
1499 SCEnter();
1500
1501 if (pstate == NULL)
1502 goto end;
1503
1504 SCLogDebug("setting APP_LAYER_PARSER_EOF_TC and APP_LAYER_PARSER_EOF_TS");
1506
1507 end:
1508 SCReturn;
1509}
1510
1511/* return true if there are app parser decoder events. These are
1512 * only the ones that are set during protocol detection. */
1514{
1515 SCEnter();
1516
1517 if (pstate == NULL)
1518 return false;
1519
1522 return true;
1523
1524 /* if we have reached here, we don't have events */
1525 return false;
1526}
1527
1528/** \brief simple way to globally test if a alproto is registered
1529 * and fully enabled in the configuration.
1530 */
1532{
1533 for (int i = 0; i < FLOW_PROTO_APPLAYER_MAX; i++) {
1534 if (alp_ctx.ctxs[alproto][i].StateGetProgress != NULL) {
1535 return 1;
1536 }
1537 }
1538 return 0;
1539}
1540
1541int AppLayerParserProtocolHasLogger(uint8_t ipproto, AppProto alproto)
1542{
1543 SCEnter();
1544 int ipproto_map = FlowGetProtoMapping(ipproto);
1545 int r = (!alp_ctx.ctxs[alproto][ipproto_map].logger) ? 0 : 1;
1546 SCReturnInt(r);
1547}
1548
1550{
1551 SCEnter();
1552 const int ipproto_map = FlowGetProtoMapping(ipproto);
1553 LoggerId r = alp_ctx.ctxs[alproto][ipproto_map].logger_bits;
1554 SCReturnUInt(r);
1555}
1556
1558{
1559 SCEnter();
1560
1561 SCLogDebug("f %p tcp %p direction %d", f, f ? f->protoctx : NULL, direction);
1562 if (f != NULL && f->protoctx != NULL)
1564
1565 SCReturn;
1566}
1567
1568void SCAppLayerParserSetStreamDepth(uint8_t ipproto, AppProto alproto, uint32_t stream_depth)
1569{
1570 SCEnter();
1571
1572 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].stream_depth = stream_depth;
1573 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].internal_flags |=
1575
1576 SCReturn;
1577}
1578
1580{
1581 SCReturnInt(alp_ctx.ctxs[f->alproto][f->protomap].stream_depth);
1582}
1583
1584void AppLayerParserSetStreamDepthFlag(uint8_t ipproto, AppProto alproto, void *state, uint64_t tx_id, uint8_t flags)
1585{
1586 SCEnter();
1587 void *tx = NULL;
1588 if (state != NULL) {
1589 if ((tx = AppLayerParserGetTx(ipproto, alproto, state, tx_id)) != NULL) {
1590 if (alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].SetStreamDepthFlag != NULL) {
1591 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].SetStreamDepthFlag(tx, flags);
1592 }
1593 }
1594 }
1595 SCReturn;
1596}
1597
1598/**
1599 * \param id progress value id to get the name for
1600 * \param direction STREAM_TOSERVER/STREAM_TOCLIENT
1601 */
1603 uint8_t ipproto, AppProto alproto, const char *name, const uint8_t direction)
1604{
1605 if (alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetStateIdByName != NULL) {
1606 return alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetStateIdByName(
1607 name, direction);
1608 } else {
1609 return -1;
1610 }
1611}
1612
1613/**
1614 * \param id progress value id to get the name for
1615 * \param direction STREAM_TOSERVER/STREAM_TOCLIENT
1616 */
1618 uint8_t ipproto, AppProto alproto, const int id, const uint8_t direction)
1619{
1620 if (alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetStateNameById != NULL) {
1621 return alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetStateNameById(id, direction);
1622 } else {
1623 return NULL;
1624 }
1625}
1626
1627int AppLayerParserGetFrameIdByName(uint8_t ipproto, AppProto alproto, const char *name)
1628{
1629 if (alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetFrameIdByName != NULL) {
1630 return alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetFrameIdByName(name);
1631 } else {
1632 return -1;
1633 }
1634}
1635
1636const char *AppLayerParserGetFrameNameById(uint8_t ipproto, AppProto alproto, const uint8_t id)
1637{
1638 if (alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetFrameNameById != NULL) {
1639 return alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetFrameNameById(id);
1640 } else {
1641 return NULL;
1642 }
1643}
1644
1645/***** Cleanup *****/
1646
1648 uint8_t protomap, AppProto alproto, void *alstate, AppLayerParserState *pstate)
1649{
1650 SCEnter();
1651
1652 AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[alproto][protomap];
1653
1654 if (ctx->StateFree != NULL && alstate != NULL)
1655 ctx->StateFree(alstate);
1656
1657 /* free the app layer parser api state */
1658 if (pstate != NULL)
1660
1661 SCReturn;
1662}
1663
1664void AppLayerParserStateCleanup(const Flow *f, void *alstate, AppLayerParserState *pstate)
1665{
1666 AppLayerParserStateProtoCleanup(f->protomap, f->alproto, alstate, pstate);
1667}
1668
1669static void ValidateParserProtoDump(AppProto alproto, uint8_t ipproto)
1670{
1671 uint8_t map = FlowGetProtoMapping(ipproto);
1672 const AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[alproto][map];
1673 printf("ERROR: incomplete app-layer registration\n");
1674 printf("AppLayer protocol %s ipproto %u\n", AppProtoToString(alproto), ipproto);
1675 printf("- option flags %"PRIx32"\n", ctx->option_flags);
1676 printf("- first_data_dir %"PRIx8"\n", ctx->first_data_dir);
1677 printf("Mandatory:\n");
1678 printf("- Parser[0] %p Parser[1] %p\n", ctx->Parser[0], ctx->Parser[1]);
1679 printf("- StateAlloc %p StateFree %p\n", ctx->StateAlloc, ctx->StateFree);
1680 printf("- StateGetTx %p StateGetTxCnt %p StateTransactionFree %p\n",
1681 ctx->StateGetTx, ctx->StateGetTxCnt, ctx->StateTransactionFree);
1682 printf("- GetTxData %p\n", ctx->GetTxData);
1683 printf("- GetStateData %p\n", ctx->GetStateData);
1684 printf("- StateGetProgress %p\n", ctx->StateGetProgress);
1685 printf("Optional:\n");
1686 printf("- LocalStorageAlloc %p LocalStorageFree %p\n", ctx->LocalStorageAlloc, ctx->LocalStorageFree);
1687 printf("- StateGetEventInfo %p StateGetEventInfoById %p\n", ctx->StateGetEventInfo,
1688 ctx->StateGetEventInfoById);
1689}
1690
1691#define BOTH_SET(a, b) ((a) != NULL && (b) != NULL)
1692#define BOTH_SET_OR_BOTH_UNSET(a, b) (((a) == NULL && (b) == NULL) || ((a) != NULL && (b) != NULL))
1693#define THREE_SET(a, b, c) ((a) != NULL && (b) != NULL && (c) != NULL)
1694
1695static void ValidateParserProto(AppProto alproto, uint8_t ipproto)
1696{
1697 uint8_t map = FlowGetProtoMapping(ipproto);
1698 const AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[alproto][map];
1699
1700 if (ctx->Parser[0] == NULL && ctx->Parser[1] == NULL)
1701 return;
1702
1703 if (!(BOTH_SET(ctx->Parser[0], ctx->Parser[1]))) {
1704 goto bad;
1705 }
1706 if (!(BOTH_SET(ctx->StateFree, ctx->StateAlloc))) {
1707 goto bad;
1708 }
1709 if (!(THREE_SET(ctx->StateGetTx, ctx->StateGetTxCnt, ctx->StateTransactionFree))) {
1710 goto bad;
1711 }
1712 if (ctx->StateGetProgress == NULL) {
1713 goto bad;
1714 }
1715 /* local storage is optional, but needs both set if used */
1716 if (!(BOTH_SET_OR_BOTH_UNSET(ctx->LocalStorageAlloc, ctx->LocalStorageFree))) {
1717 goto bad;
1718 }
1719 if (ctx->GetTxData == NULL) {
1720 goto bad;
1721 }
1722 if (ctx->GetStateData == NULL) {
1723 goto bad;
1724 }
1725 return;
1726bad:
1727 ValidateParserProtoDump(alproto, ipproto);
1728 exit(EXIT_FAILURE);
1729}
1730#undef BOTH_SET
1731#undef BOTH_SET_OR_BOTH_UNSET
1732#undef THREE_SET
1733
1734static void ValidateParser(AppProto alproto)
1735{
1736 ValidateParserProto(alproto, IPPROTO_TCP);
1737 ValidateParserProto(alproto, IPPROTO_UDP);
1738}
1739
1740static void ValidateParsers(void)
1741{
1742 AppProto p = 0;
1743 for (; p < g_alproto_max; p++) {
1744 ValidateParser(p);
1745 }
1746}
1747
1748#define ARRAY_CAP_STEP 16
1749static void (**PreRegisteredCallbacks)(void) = NULL;
1750static size_t preregistered_callbacks_nb = 0;
1751static size_t preregistered_callbacks_cap = 0;
1752
1753int AppLayerParserPreRegister(void (*Register)(void))
1754{
1755 if (preregistered_callbacks_nb == preregistered_callbacks_cap) {
1756 void *tmp = SCRealloc(PreRegisteredCallbacks,
1757 sizeof(void *) * (preregistered_callbacks_cap + ARRAY_CAP_STEP));
1758 if (tmp == NULL) {
1759 return 1;
1760 }
1761 preregistered_callbacks_cap += ARRAY_CAP_STEP;
1762 PreRegisteredCallbacks = tmp;
1763 }
1764 PreRegisteredCallbacks[preregistered_callbacks_nb] = Register;
1765 preregistered_callbacks_nb++;
1766 return 0;
1767}
1768
1770{
1771 SCEnter();
1772
1773 AppLayerConfig();
1774
1777 SCRegisterDcerpcParser();
1778 SCRegisterDcerpcUdpParser();
1783 SCRegisterDnsUdpParser();
1784 SCRegisterDnsTcpParser();
1785 SCRegisterBittorrentDhtUdpParser();
1787 SCEnipRegisterParsers();
1791 SCRegisterNtpParser();
1794 SCRegisterKrb5Parser();
1795 SCRegisterDhcpParser();
1796 SCRegisterSnmpParser();
1797 SCRegisterSipParser();
1798 SCRegisterQuicParser();
1799 SCRegisterWebSocketParser();
1800 SCRegisterLdapTcpParser();
1801 SCRegisterLdapUdpParser();
1802 SCRegisterMdnsParser();
1803 SCRegisterTemplateParser();
1804 SCRfbRegisterParser();
1805 SCMqttRegisterParser();
1806 SCRegisterPgsqlParser();
1807 SCRegisterPop3Parser();
1808 SCRegisterRdpParser();
1810 SCRegisterTelnetParser();
1812
1813 for (size_t i = 0; i < preregistered_callbacks_nb; i++) {
1814 PreRegisteredCallbacks[i]();
1815 }
1816
1817 ValidateParsers();
1818}
1819
1820/* coccinelle: SCAppLayerParserStateSetFlag():2,2:APP_LAYER_PARSER_ */
1822{
1823 SCEnter();
1824 pstate->flags |= flag;
1825 SCReturn;
1826}
1827
1828/* coccinelle: SCAppLayerParserStateIssetFlag():2,2:APP_LAYER_PARSER_ */
1830{
1831 SCEnter();
1832 SCReturnUInt(pstate->flags & flag);
1833}
1834
1835/***** Unittests *****/
1836
1837#ifdef UNITTESTS
1838#include "util-unittest-helper.h"
1839
1841 void (*RegisterUnittests)(void))
1842{
1843 SCEnter();
1844 alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].RegisterUnittests = RegisterUnittests;
1845 SCReturn;
1846}
1847
1849{
1850 SCEnter();
1851
1852 int ip;
1853 AppProto alproto;
1855
1856 for (ip = 0; ip < FLOW_PROTO_DEFAULT; ip++) {
1857 for (alproto = 0; alproto < g_alproto_max; alproto++) {
1858 ctx = &alp_ctx.ctxs[alproto][ip];
1859 if (ctx->RegisterUnittests == NULL)
1860 continue;
1861 ctx->RegisterUnittests();
1862 }
1863 }
1864
1865 SCReturn;
1866}
1867
1868#endif
void RegisterDNP3Parsers(void)
Register the DNP3 application protocol parser.
void AppLayerDecoderEventsFreeEvents(AppLayerDecoderEvents **events)
Frame * AppLayerFrameNewByAbsoluteOffset(Flow *f, const StreamSlice *stream_slice, const uint64_t frame_start, const int64_t len, int dir, uint8_t frame_type)
create new frame using the absolute offset from the start of the stream
Frame * AppLayerFrameGetLastOpenByType(Flow *f, const int dir, const uint8_t frame_type)
void FramesFree(Frames *frames)
#define FRAME_STREAM_TYPE
#define FRAME_FLAG_ENDS_AT_EOF
void RegisterFTPParsers(void)
void FTPParserCleanup(void)
Free memory allocated for global FTP parser state.
struct HtpBodyChunk_ * next
void RegisterHTTP2Parsers(void)
void RegisterIKEParsers(void)
void RegisterIMAPParsers(void)
void RegisterModbusParsers(void)
Function to register the Modbus protocol parser.
void RegisterNFSTCPParsers(void)
void RegisterNFSUDPParsers(void)
int AppLayerParserGetEventInfo(uint8_t ipproto, AppProto alproto, const char *event_name, uint8_t *event_id, AppLayerEventType *event_type)
int AppLayerParserProtocolHasLogger(uint8_t ipproto, AppProto alproto)
uint64_t AppLayerParserGetTransactionActive(const Flow *f, AppLayerParserState *pstate, uint8_t direction)
int AppLayerParserGetFrameIdByName(uint8_t ipproto, AppProto alproto, const char *name)
#define ARRAY_CAP_STEP
int AppLayerParserIsEnabled(AppProto alproto)
simple way to globally test if a alproto is registered and fully enabled in the configuration.
AppLayerTxData * AppLayerParserGetTxData(uint8_t ipproto, AppProto alproto, void *tx)
enum ExceptionPolicy g_applayerparser_error_policy
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))
uint16_t SCAppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint16_t flag)
AppLayerGetFileState AppLayerParserGetTxFiles(const Flow *f, void *tx, const uint8_t direction)
int AppLayerParserGetStateProgressCompletionStatus(AppProto alproto, uint8_t direction)
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
int AppLayerParserGetStateIdByName(uint8_t ipproto, AppProto alproto, const char *name, const uint8_t direction)
void AppLayerParserStateFree(AppLayerParserState *pstate)
void AppLayerParserRegisterTxDataFunc(uint8_t ipproto, AppProto alproto, AppLayerTxData *(*GetTxData)(void *tx))
uint8_t AppLayerParserGetTxDetectProgress(AppLayerTxData *txd, const uint8_t dir)
FramesContainer * AppLayerFramesSetupContainer(Flow *f)
AppLayerStateData * AppLayerParserGetStateData(uint8_t ipproto, AppProto alproto, void *state)
void AppLayerParserTriggerRawStreamInspection(Flow *f, int direction)
void AppLayerParserSetStreamDepthFlag(uint8_t ipproto, AppProto alproto, void *state, uint64_t tx_id, uint8_t flags)
void AppLayerParserRegisterOptionFlags(uint8_t ipproto, AppProto alproto, uint32_t flags)
void AppLayerParserTransactionsCleanup(Flow *f, const uint8_t pkt_dir)
remove obsolete (inspected and logged) transactions
#define THREE_SET(a, b, c)
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
bool g_filedata_logger_enabled
const char * AppLayerParserGetFrameNameById(uint8_t ipproto, AppProto alproto, const uint8_t id)
FramesContainer * AppLayerFramesGetContainer(Flow *f)
uint32_t AppLayerParserGetStreamDepth(const Flow *f)
void AppLayerParserDestroyProtocolParserLocalStorage(uint8_t ipproto, AppProto alproto, void *local_data)
uint64_t AppLayerParserGetTxCnt(const Flow *f, void *alstate)
void AppLayerParserRegisterStateProgressCompletionStatus(AppProto alproto, const int ts, const int tc)
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
void AppLayerParserRegisterSetStreamDepthFlag(uint8_t ipproto, AppProto alproto, void(*SetStreamDepthFlag)(void *tx, uint8_t flags))
bool AppLayerParserSupportsFiles(uint8_t ipproto, AppProto alproto)
AppLayerGetTxIteratorFunc AppLayerGetTxIterator(const uint8_t ipproto, const AppProto alproto)
void SCAppLayerParserStateSetFlag(AppLayerParserState *pstate, uint16_t flag)
uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction)
void AppLayerParserRegisterApplyTxConfigFunc(uint8_t ipproto, AppProto alproto, bool(*ApplyTxConfig)(void *state, void *tx, int mode, AppLayerTxConfig))
int AppLayerParserPreRegister(void(*Register)(void))
void AppLayerParserRegisterLoggerBits(uint8_t ipproto, AppProto alproto, LoggerId bits)
void AppLayerParserRegisterGetTxFilesFunc(uint8_t ipproto, AppProto alproto, AppLayerGetFileState(*GetTxFiles)(void *, uint8_t))
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
void AppLayerParserSetTransactionLogId(AppLayerParserState *pstate, uint64_t tx_id)
bool AppLayerParserHasDecoderEvents(AppLayerParserState *pstate)
void AppLayerFramesFreeContainer(Flow *f)
struct AppLayerParserProtoCtx_ AppLayerParserProtoCtx
App layer protocol parser context.
int AppLayerParserProtoIsRegistered(uint8_t ipproto, AppProto alproto)
uint8_t AppLayerParserGetFirstDataDir(uint8_t ipproto, AppProto alproto)
void AppLayerParserRegisterStateDataFunc(uint8_t ipproto, AppProto alproto, AppLayerStateData *(*GetStateData)(void *state))
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
void AppLayerParserPostStreamSetup(void)
void AppLayerParserRegisterGetTxIterator(uint8_t ipproto, AppProto alproto, AppLayerGetTxIteratorFunc Func)
void AppLayerParserRegisterLocalStorageFunc(uint8_t ipproto, AppProto alproto, void *(*LocalStorageAlloc)(void), void(*LocalStorageFree)(void *))
int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto, uint8_t direction, AppLayerParserFPtr Parser)
Register app layer parser for the protocol.
const char * AppLayerParserGetStateNameById(uint8_t ipproto, AppProto alproto, const int id, const uint8_t direction)
void AppLayerParserStateCleanup(const Flow *f, void *alstate, AppLayerParserState *pstate)
AppLayerDecoderEvents * AppLayerParserGetDecoderEvents(AppLayerParserState *pstate)
int AppLayerParserDeSetup(void)
void UTHAppLayerParserStateGetIds(void *ptr, uint64_t *i1, uint64_t *i2, uint64_t *log, uint64_t *min)
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
void * AppLayerParserGetProtocolParserLocalStorage(uint8_t ipproto, AppProto alproto)
AppLayerParserState * AppLayerParserStateAlloc(void)
int AppLayerParserGetEventInfoById(uint8_t ipproto, AppProto alproto, uint8_t event_id, const char **event_name, AppLayerEventType *event_type)
struct AppLayerParserCtx_ AppLayerParserCtx
void AppLayerParserSetEOF(AppLayerParserState *pstate)
void SCAppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto)
void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfo)(const char *event_name, uint8_t *event_id, AppLayerEventType *event_type))
int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto, void *alstate, uint8_t flags)
get the progress value for a tx/protocol
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto, int(*StateGetProgress)(void *alstate, uint8_t direction))
void SCAppLayerParserRegisterParserAcceptableDataDirection(uint8_t ipproto, AppProto alproto, uint8_t direction)
int SCAppLayerParserConfParserEnabled(const char *ipproto, const char *alproto_name)
check if a parser is enabled in the config Returns enabled always if: were running unittests
void AppLayerParserSetTransactionInspectId(const Flow *f, AppLayerParserState *pstate, void *alstate, const uint8_t flags, bool tag_txs_as_inspected)
void AppLayerParserRegisterUnittests(void)
void SCAppLayerParserSetStreamDepth(uint8_t ipproto, AppProto alproto, uint32_t stream_depth)
void AppLayerParserStateProtoCleanup(uint8_t protomap, AppProto alproto, void *alstate, AppLayerParserState *pstate)
bool g_file_logger_enabled
Definition output-file.c:39
void AppLayerParserRegisterProtocolParsers(void)
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void *, AppProto), void(*StateFree)(void *))
void AppLayerParserRegisterGetEventInfoById(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfoById)(uint8_t event_id, const char **event_name, AppLayerEventType *event_type))
void AppLayerParserRegisterGetStateFuncs(uint8_t ipproto, AppProto alproto, AppLayerParserGetStateIdByNameFn GetIdByNameFunc, AppLayerParserGetStateNameByIdFn GetNameByIdFunc)
void AppLayerParserApplyTxConfig(uint8_t ipproto, AppProto alproto, void *state, void *tx, enum ConfigAction mode, AppLayerTxConfig config)
int AppLayerParserSetup(void)
#define IS_DISRUPTED(flags)
void AppLayerParserRegisterGetFrameFuncs(uint8_t ipproto, AppProto alproto, AppLayerParserGetFrameIdByNameFn GetIdByNameFunc, AppLayerParserGetFrameNameByIdFn GetNameByIdFunc)
AppLayerDecoderEvents * AppLayerParserGetEventsByTx(uint8_t ipproto, AppProto alproto, void *tx)
LoggerId AppLayerParserProtocolGetLoggerBits(uint8_t ipproto, AppProto alproto)
#define BOTH_SET(a, b)
enum ExceptionPolicy AppLayerErrorGetExceptionPolicy(void)
int g_detect_disabled
Definition suricata.c:186
uint64_t AppLayerParserGetTransactionLogId(AppLayerParserState *pstate)
#define BOTH_SET_OR_BOTH_UNSET(a, b)
int(* AppLayerParserGetStateIdByNameFn)(const char *name, const uint8_t direction)
#define APP_LAYER_PARSER_INT_STREAM_DEPTH_SET
struct AppLayerGetFileState AppLayerGetFileState
#define APP_LAYER_TX_INSPECTED_TC
struct AppLayerGetTxIterTuple AppLayerGetTxIterTuple
#define APP_LAYER_PARSER_NO_REASSEMBLY
#define APP_LAYER_PARSER_NO_INSPECTION_PAYLOAD
#define APP_LAYER_PARSER_SFRAME_TS
#define APP_LAYER_PARSER_NO_INSPECTION
const char *(* AppLayerParserGetStateNameByIdFn)(const int id, const uint8_t direction)
AppLayerResult(* AppLayerParserFPtr)(Flow *f, void *protocol_state, AppLayerParserState *pstate, StreamSlice stream_slice, void *local_storage)
Prototype for parsing functions.
#define APP_LAYER_PARSER_BYPASS_READY
struct AppLayerTxData AppLayerTxData
const char *(* AppLayerParserGetFrameNameByIdFn)(const uint8_t id)
#define APP_LAYER_TX_SKIP_INSPECT_TC
int(* AppLayerParserGetFrameIdByNameFn)(const char *frame_name)
#define AppLayerParserHasFilesInDir(txd, direction)
check if tx (possibly) has files in this tx for the direction
#define APP_LAYER_TX_SKIP_INSPECT_TS
#define APP_LAYER_PARSER_EOF_TC
#define APP_LAYER_TX_INSPECTED_TS
#define APP_LAYER_PARSER_SFRAME_TC
AppLayerGetTxIterTuple(* AppLayerGetTxIteratorFunc)(const uint8_t ipproto, const AppProto alproto, void *alstate, uint64_t min_tx_id, uint64_t max_tx_id, AppLayerGetTxIterState *state)
tx iterator prototype
struct AppLayerTxConfig AppLayerTxConfig
struct AppLayerResult AppLayerResult
#define APP_LAYER_PARSER_EOF_TS
#define APP_LAYER_PARSER_OPT_ACCEPT_GAPS
struct StreamSlice StreamSlice
struct AppLayerStateData AppLayerStateData
enum AppLayerEventType AppLayerEventType
AppProto g_alproto_max
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its string equivalent.
uint16_t AppProto
@ ALPROTO_HTTP2
@ ALPROTO_HTTP
@ ALPROTO_HTTP1
void RegisterSMBParsers(void)
void SMTPParserCleanup(void)
Free memory allocated for global SMTP parser state.
void RegisterSMTPParsers(void)
Register the SMTP Protocol parser.
void RegisterSSHParsers(void)
Function to register the SSH protocol parsers and other functions.
void RegisterSSLParsers(void)
Function to register the SSL protocol parser and other functions.
void RegisterTFTPParsers(void)
void AppLayerIncInternalErrorCounter(ThreadVars *tv, Flow *f)
Definition app-layer.c:187
void AppLayerIncAllocErrorCounter(ThreadVars *tv, Flow *f)
Definition app-layer.c:171
const char * AppLayerGetProtoName(AppProto alproto)
Given the internal protocol id, returns a string representation of the protocol.
Definition app-layer.c:1009
void AppLayerIncGapErrorCounter(ThreadVars *tv, Flow *f)
Definition app-layer.c:163
void AppLayerIncParserErrorCounter(ThreadVars *tv, Flow *f)
Definition app-layer.c:179
void AppLayerIncTxCounter(ThreadVars *tv, Flow *f, uint64_t step)
Definition app-layer.c:155
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
Definition conf.c:181
int SCConfValIsTrue(const char *val)
Check if a value is true.
Definition conf.c:551
int SCConfValIsFalse(const char *val)
Check if a value is false.
Definition conf.c:576
uint8_t flags
Definition decode-gre.h:0
TcpStreamCnf stream_config
Definition stream-tcp.c:219
@ FLOW_PROTO_DEFAULT
@ FLOW_PROTO_MAX
#define FLOW_PROTO_APPLAYER_MAX
uint8_t FlowGetReverseProtoMapping(uint8_t rproto)
Definition flow-util.c:113
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
Definition flow-util.c:99
uint8_t FlowGetDisruptionFlags(const Flow *f, uint8_t flags)
get 'disruption' flags: GAP/DEPTH/PASS
Definition flow.c:1141
int FlowChangeProto(Flow *f)
Check if change proto flag is set for flow.
Definition flow.c:196
#define FLOW_SGH_TOCLIENT
Definition flow.h:75
#define FLOW_NOPAYLOAD_INSPECTION
Definition flow.h:67
#define FLOW_SGH_TOSERVER
Definition flow.h:73
AppLayerParserThreadCtx * alp_tctx
ThreadVars * tv
void RegisterHTPParsers(void)
Register the HTTP protocol and state handling functions to APP layer of the engine.
struct Thresholds ctx
uint64_t ts
#define STREAM_APP_PROGRESS(stream)
void StreamTcpReassembleTriggerRawInspection(TcpSession *ssn, int direction)
Trigger RAW stream inspection.
void StreamTcpDisableAppLayer(Flow *f)
void StreamTcpSetSessionBypassFlag(TcpSession *)
enable bypass
void StreamTcpSetSessionNoReassemblyFlag(TcpSession *, char)
disable reassembly
void StreamTcpSetDisableRawReassemblyFlag(TcpSession *, char)
Set the No reassembly flag for the given direction in given TCP session.
void StreamTcpUpdateAppLayerProgress(TcpSession *ssn, char direction, const uint32_t progress)
update reassembly progress
Data structure to store app layer decoder events.
AppLayerParserProtoCtx(* ctxs)[FLOW_PROTO_MAX]
App layer protocol parser context.
AppLayerParserGetFrameIdByNameFn GetFrameIdByName
int(* StateGetEventInfo)(const char *event_name, uint8_t *event_id, AppLayerEventType *event_type)
AppLayerGetFileState(* GetTxFiles)(void *, uint8_t)
void(* SetStreamDepthFlag)(void *tx, uint8_t flags)
AppLayerParserGetFrameNameByIdFn GetFrameNameById
void *(* StateGetTx)(void *alstate, uint64_t tx_id)
int(* StateGetProgress)(void *alstate, uint8_t direction)
void(* LocalStorageFree)(void *)
AppLayerStateData *(* GetStateData)(void *state)
AppLayerGetTxIteratorFunc StateGetTxIterator
void *(* StateAlloc)(void *, AppProto)
int(* StateGetEventInfoById)(uint8_t event_id, const char **event_name, AppLayerEventType *event_type)
AppLayerTxData *(* GetTxData)(void *tx)
AppLayerParserGetStateNameByIdFn GetStateNameById
AppLayerParserGetStateIdByNameFn GetStateIdByName
void *(* LocalStorageAlloc)(void)
bool(* ApplyTxConfig)(void *state, void *tx, int mode, AppLayerTxConfig)
AppLayerParserFPtr Parser[2]
uint64_t(* StateGetTxCnt)(void *alstate)
void(* StateTransactionFree)(void *, uint64_t)
FramesContainer * frames
AppLayerDecoderEvents * decoder_events
void *(* alproto_local_storage)[FLOW_PROTO_MAX]
Flow data structure.
Definition flow.h:356
const struct SigGroupHead_ * sgh_toclient
Definition flow.h:483
uint8_t proto
Definition flow.h:378
uint32_t flags
Definition flow.h:421
uint16_t file_flags
Definition flow.h:423
AppProto alproto
application level protocol
Definition flow.h:450
void * alstate
Definition flow.h:479
const struct SigGroupHead_ * sgh_toserver
Definition flow.h:486
AppProto alproto_orig
Definition flow.h:456
void * protoctx
Definition flow.h:441
AppLayerParserState * alparser
Definition flow.h:478
uint8_t protomap
Definition flow.h:445
int64_t id
int64_t len
uint64_t offset
uint8_t flags
char * val
Definition conf.h:39
uint32_t reassembly_depth
Definition stream-tcp.h:75
uint32_t data_required
Per thread variable structure.
Definition threadvars.h:58
#define BUG_ON(x)
#define MIN(x, y)
#define MAX(x, y)
int RunmodeIsUnittests(void)
Definition suricata.c:270
const char * name
ConfigAction
Definition util-config.h:27
#define SCEnter(...)
Definition util-debug.h:277
#define FatalError(...)
Definition util-debug.h:510
#define SCReturnUInt(x)
Definition util-debug.h:283
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturnInt(x)
Definition util-debug.h:281
#define SCReturnCT(x, type)
Definition util-debug.h:291
#define SCLogNotice(...)
Macro used to log NOTICE messages.
Definition util-debug.h:243
#define SCReturnPtr(x, type)
Definition util-debug.h:293
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#define SCReturn
Definition util-debug.h:279
enum ExceptionPolicy ExceptionPolicyParse(const char *option, bool support_flow)
void FilesPrune(FileContainer *fc, const StreamingBufferConfig *sbcfg, const bool trunc)
Definition util-file.c:1187
#define SCFree(p)
Definition util-mem.h:61
#define SCRealloc(ptr, sz)
Definition util-mem.h:50
#define SCCalloc(nm, sz)
Definition util-mem.h:53
#define unlikely(expr)
#define DEBUG_VALIDATE_BUG_ON(exp)
#define DEBUG_ASSERT_FLOW_LOCKED(f)