]> git.ipfire.org Git - people/ms/suricata.git/blame - src/app-layer-parser.c
app-layer: include decoder events in app-layer tx data
[people/ms/suricata.git] / src / app-layer-parser.c
CommitLineData
674b8dc0 1/* Copyright (C) 2007-2020 Open Information Security Foundation
ce019275
WM
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 */
8e10844f 25
ecf86f9c 26#include "suricata-common.h"
8e10844f 27#include "debug.h"
c1e485cc 28#include "util-unittest.h"
8e10844f
VJ
29#include "decode.h"
30#include "threads.h"
31
32#include "util-print.h"
33#include "util-pool.h"
34
cc76aa4b 35#include "flow-util.h"
429c6388 36#include "flow-private.h"
cc76aa4b 37
0e4235cc 38#include "detect-engine-state.h"
d9686fae 39#include "detect-engine-port.h"
0e4235cc 40
6a53ab9c 41#include "stream-tcp.h"
8e10844f
VJ
42#include "stream-tcp-private.h"
43#include "stream.h"
a16e7b74 44#include "stream-tcp-reassemble.h"
8e10844f 45
e1022ee5 46#include "app-layer.h"
8e10844f
VJ
47#include "app-layer-protos.h"
48#include "app-layer-parser.h"
c2cb155e 49#include "app-layer-smb.h"
000ce98c
AS
50#include "app-layer-htp.h"
51#include "app-layer-ftp.h"
52#include "app-layer-ssl.h"
53#include "app-layer-ssh.h"
576ec7da 54#include "app-layer-smtp.h"
5a040995 55#include "app-layer-modbus.h"
a3ffebd8 56#include "app-layer-enip.h"
bbaa79b8 57#include "app-layer-dnp3.h"
0d79181d
VJ
58#include "app-layer-nfs-tcp.h"
59#include "app-layer-nfs-udp.h"
efe11dc3 60#include "app-layer-ntp.h"
b9cf49e9 61#include "app-layer-tftp.h"
ecdf9f6b 62#include "app-layer-ike.h"
77f0c11c 63#include "app-layer-krb5.h"
2df840a8 64#include "app-layer-snmp.h"
2e975a04 65#include "app-layer-sip.h"
1c8943de 66#include "app-layer-rfb.h"
c3136007 67#include "app-layer-mqtt.h"
c1b92126 68#include "app-layer-template.h"
96dc20ab 69#include "app-layer-template-rust.h"
caef8b5b 70#include "app-layer-rdp.h"
1422b18a 71#include "app-layer-http2.h"
8e10844f 72
ddde572f 73#include "conf.h"
705471e4 74#include "util-spm.h"
9f78d47c 75
91bc83e5 76#include "util-debug.h"
eea5ab4a 77#include "decode-events.h"
262a7300 78#include "util-unittest-helper.h"
5ba41c78 79#include "util-validate.h"
91bc83e5 80
429c6388 81#include "runmodes.h"
cae8e06c 82
68887458
JI
83#include "rust.h"
84
446e68ad 85struct AppLayerParserThreadCtx_ {
429c6388 86 void *alproto_local_storage[FLOW_PROTO_MAX][ALPROTO_MAX];
446e68ad 87};
cae8e06c 88
b74c7330 89
429c6388
AS
90/**
91 * \brief App layer protocol parser context.
92 */
c23742a0 93typedef struct AppLayerParserProtoCtx_
429c6388
AS
94{
95 /* 0 - to_server, 1 - to_client. */
7c8bdfd3 96 AppLayerParserFPtr Parser[2];
66530c61 97 bool logger;
01724f04 98 uint32_t logger_bits; /**< registered loggers for this proto */
429c6388 99
547d6c2d 100 void *(*StateAlloc)(void *, AppProto);
429c6388
AS
101 void (*StateFree)(void *);
102 void (*StateTransactionFree)(void *, uint64_t);
103 void *(*LocalStorageAlloc)(void);
104 void (*LocalStorageFree)(void *);
105
106 void (*Truncate)(void *, uint8_t);
107 FileContainer *(*StateGetFiles)(void *, uint8_t);
429c6388
AS
108
109 int (*StateGetProgress)(void *alstate, uint8_t direction);
110 uint64_t (*StateGetTxCnt)(void *alstate);
111 void *(*StateGetTx)(void *alstate, uint64_t tx_id);
e96d9c11 112 AppLayerGetTxIteratorFunc StateGetTxIterator;
efc9a7a3
VJ
113 int complete_ts;
114 int complete_tc;
50e23ba9
JL
115 int (*StateGetEventInfoById)(int event_id, const char **event_name,
116 AppLayerEventType *event_type);
429c6388
AS
117 int (*StateGetEventInfo)(const char *event_name,
118 int *event_id, AppLayerEventType *event_type);
119
411f428a 120 AppLayerTxData *(*GetTxData)(void *tx);
5665fc83 121 bool (*ApplyTxConfig)(void *state, void *tx, int mode, AppLayerTxConfig);
daeb8fd3 122
ed5a439b
GL
123 void (*SetStreamDepthFlag)(void *tx, uint8_t flags);
124
b160c49e
GL
125 /* each app-layer has its own value */
126 uint32_t stream_depth;
127
429c6388
AS
128 /* Indicates the direction the parser is ready to see the data
129 * the first time for a flow. Values accepted -
130 * STREAM_TOSERVER, STREAM_TOCLIENT */
131 uint8_t first_data_dir;
e1022ee5 132
c862bbdc 133 /* Option flags such as supporting gaps or not. */
c8fb9bcb 134 uint32_t option_flags;
1df38c3b 135 /* coccinelle: AppLayerParserProtoCtx:option_flags:APP_LAYER_PARSER_OPT_ */
c8fb9bcb
VJ
136
137 uint32_t internal_flags;
1df38c3b 138 /* coccinelle: AppLayerParserProtoCtx:internal_flags:APP_LAYER_PARSER_INT_ */
c862bbdc 139
429c6388
AS
140#ifdef UNITTESTS
141 void (*RegisterUnittests)(void);
142#endif
c23742a0 143} AppLayerParserProtoCtx;
429c6388
AS
144
145typedef struct AppLayerParserCtx_ {
c23742a0 146 AppLayerParserProtoCtx ctxs[FLOW_PROTO_MAX][ALPROTO_MAX];
429c6388
AS
147} AppLayerParserCtx;
148
446e68ad 149struct AppLayerParserState_ {
26eb49d7 150 /* coccinelle: AppLayerParserState:flags:APP_LAYER_PARSER_ */
429c6388
AS
151 uint8_t flags;
152
153 /* Indicates the current transaction that is being inspected.
154 * We have a var per direction. */
155 uint64_t inspect_id[2];
156 /* Indicates the current transaction being logged. Unlike inspect_id,
157 * we don't need a var per direction since we don't log a transaction
158 * unless we have the entire transaction. */
159 uint64_t log_id;
429c6388 160
5b56d324
VJ
161 uint64_t min_id;
162
429c6388
AS
163 /* Used to store decoder events. */
164 AppLayerDecoderEvents *decoder_events;
446e68ad 165};
e1022ee5 166
37203c98
VJ
167#ifdef UNITTESTS
168void UTHAppLayerParserStateGetIds(void *ptr, uint64_t *i1, uint64_t *i2, uint64_t *log, uint64_t *min)
169{
170 struct AppLayerParserState_ *s = ptr;
171 *i1 = s->inspect_id[0];
172 *i2 = s->inspect_id[1];
173 *log = s->log_id;
174 *min = s->min_id;
175}
176#endif
177
429c6388
AS
178/* Static global version of the parser context.
179 * Post 2.0 let's look at changing this to move it out to app-layer.c. */
180static AppLayerParserCtx alp_ctx;
5a9a23f9 181
5908dd08
GL
182int AppLayerParserProtoIsRegistered(uint8_t ipproto, AppProto alproto)
183{
184 uint8_t ipproto_map = FlowGetProtoMapping(ipproto);
185
186 return (alp_ctx.ctxs[ipproto_map][alproto].StateAlloc != NULL) ? 1 : 0;
187}
188
9634e60e 189AppLayerParserState *AppLayerParserStateAlloc(void)
429c6388
AS
190{
191 SCEnter();
9dc04d9f 192
cd0627cd 193 AppLayerParserState *pstate = (AppLayerParserState *)SCMalloc(sizeof(*pstate));
429c6388
AS
194 if (pstate == NULL)
195 goto end;
196 memset(pstate, 0, sizeof(*pstate));
9dc04d9f 197
429c6388 198 end:
9634e60e 199 SCReturnPtr(pstate, "AppLayerParserState");
9dc04d9f
VJ
200}
201
9634e60e 202void AppLayerParserStateFree(AppLayerParserState *pstate)
429c6388
AS
203{
204 SCEnter();
205
9634e60e 206 if (pstate->decoder_events != NULL)
347c0df9 207 AppLayerDecoderEventsFreeEvents(&pstate->decoder_events);
429c6388 208 SCFree(pstate);
9dc04d9f 209
429c6388 210 SCReturn;
9dc04d9f
VJ
211}
212
429c6388 213int AppLayerParserSetup(void)
c1e485cc 214{
429c6388 215 SCEnter();
429c6388 216 memset(&alp_ctx, 0, sizeof(alp_ctx));
6d562f3b
VJ
217 SCReturnInt(0);
218}
219
220void AppLayerParserPostStreamSetup(void)
221{
222 AppProto alproto = 0;
223 int flow_proto = 0;
224
b160c49e
GL
225 /* lets set a default value for stream_depth */
226 for (flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) {
227 for (alproto = 0; alproto < ALPROTO_MAX; alproto++) {
c8fb9bcb
VJ
228 if (!(alp_ctx.ctxs[flow_proto][alproto].internal_flags &
229 APP_LAYER_PARSER_INT_STREAM_DEPTH_SET)) {
397f5f5f
GL
230 alp_ctx.ctxs[flow_proto][alproto].stream_depth =
231 stream_config.reassembly_depth;
232 }
b160c49e
GL
233 }
234 }
5a9a23f9 235}
5a9a23f9 236
429c6388 237int AppLayerParserDeSetup(void)
d4d18e31 238{
429c6388 239 SCEnter();
d4d18e31 240
bc68ef46 241 FTPParserCleanup();
7a0dbc6f
JV
242 SMTPParserCleanup();
243
429c6388 244 SCReturnInt(0);
d4d18e31
AS
245}
246
9634e60e 247AppLayerParserThreadCtx *AppLayerParserThreadCtxAlloc(void)
d4d18e31 248{
429c6388 249 SCEnter();
d4d18e31 250
55255889
VJ
251 AppProto alproto = 0;
252 int flow_proto = 0;
72a16459 253 AppLayerParserThreadCtx *tctx;
d4d18e31 254
429c6388
AS
255 tctx = SCMalloc(sizeof(*tctx));
256 if (tctx == NULL)
257 goto end;
258 memset(tctx, 0, sizeof(*tctx));
259
55255889
VJ
260 for (flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) {
261 for (alproto = 0; alproto < ALPROTO_MAX; alproto++) {
262 uint8_t ipproto = FlowGetReverseProtoMapping(flow_proto);
263
264 tctx->alproto_local_storage[flow_proto][alproto] =
265 AppLayerParserGetProtocolParserLocalStorage(ipproto, alproto);
429c6388
AS
266 }
267 }
268
269 end:
270 SCReturnPtr(tctx, "void *");
d4d18e31
AS
271}
272
9634e60e 273void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
c1e485cc 274{
429c6388 275 SCEnter();
9f78d47c 276
55255889
VJ
277 AppProto alproto = 0;
278 int flow_proto = 0;
279
280 for (flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) {
281 for (alproto = 0; alproto < ALPROTO_MAX; alproto++) {
282 uint8_t ipproto = FlowGetReverseProtoMapping(flow_proto);
429c6388 283
55255889
VJ
284 AppLayerParserDestroyProtocolParserLocalStorage(ipproto, alproto,
285 tctx->alproto_local_storage[flow_proto][alproto]);
429c6388 286 }
9f78d47c 287 }
cae8e06c 288
0bac43a1 289 SCFree(tctx);
429c6388 290 SCReturn;
9f78d47c
VJ
291}
292
4683b0e6 293/** \brief check if a parser is enabled in the config
293eebd9 294 * Returns enabled always if: were running unittests
4683b0e6 295 */
429c6388
AS
296int AppLayerParserConfParserEnabled(const char *ipproto,
297 const char *alproto_name)
c1e485cc 298{
429c6388
AS
299 SCEnter();
300
301 int enabled = 1;
302 char param[100];
303 ConfNode *node;
304 int r;
cae8e06c 305
429c6388
AS
306 if (RunmodeIsUnittests())
307 goto enabled;
308
309 r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
310 alproto_name, ".enabled");
311 if (r < 0) {
6f7d8e50 312 FatalError(SC_ERR_FATAL, "snprintf failure.");
429c6388 313 } else if (r > (int)sizeof(param)) {
6f7d8e50 314 FatalError(SC_ERR_FATAL, "buffer not big enough to write param.");
4914d8d9 315 }
5a9a23f9 316
429c6388
AS
317 node = ConfGetNode(param);
318 if (node == NULL) {
319 SCLogDebug("Entry for %s not found.", param);
320 r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
321 alproto_name, ".", ipproto, ".enabled");
322 if (r < 0) {
6f7d8e50 323 FatalError(SC_ERR_FATAL, "snprintf failure.");
429c6388 324 } else if (r > (int)sizeof(param)) {
6f7d8e50 325 FatalError(SC_ERR_FATAL, "buffer not big enough to write param.");
429c6388
AS
326 }
327
328 node = ConfGetNode(param);
329 if (node == NULL) {
330 SCLogDebug("Entry for %s not found.", param);
331 goto enabled;
332 }
9f78d47c 333 }
9f78d47c 334
16e4c92b 335 if (ConfValIsTrue(node->val)) {
429c6388 336 goto enabled;
16e4c92b 337 } else if (ConfValIsFalse(node->val)) {
429c6388
AS
338 goto disabled;
339 } else if (strcasecmp(node->val, "detection-only") == 0) {
ff8dae3b 340 goto disabled;
9f78d47c 341 } else {
429c6388
AS
342 SCLogError(SC_ERR_FATAL, "Invalid value found for %s.", param);
343 exit(EXIT_FAILURE);
9f78d47c 344 }
429c6388
AS
345
346 disabled:
347 enabled = 0;
348 enabled:
349 SCReturnInt(enabled);
9f78d47c
VJ
350}
351
429c6388
AS
352/***** Parser related registration *****/
353
5cdeadb3 354int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto,
429c6388 355 uint8_t direction,
7c8bdfd3 356 AppLayerParserFPtr Parser)
c1e485cc 357{
574bcea0
VJ
358 SCEnter();
359
429c6388
AS
360 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
361 Parser[(direction & STREAM_TOSERVER) ? 0 : 1] = Parser;
9f78d47c 362
574bcea0 363 SCReturnInt(0);
9f78d47c
VJ
364}
365
5cdeadb3 366void AppLayerParserRegisterParserAcceptableDataDirection(uint8_t ipproto, AppProto alproto,
429c6388 367 uint8_t direction)
c13ad8c2 368{
429c6388
AS
369 SCEnter();
370
371 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].first_data_dir |=
372 (direction & (STREAM_TOSERVER | STREAM_TOCLIENT));
373
374 SCReturn;
c13ad8c2
AS
375}
376
c862bbdc 377void AppLayerParserRegisterOptionFlags(uint8_t ipproto, AppProto alproto,
c8fb9bcb 378 uint32_t flags)
c862bbdc
JI
379{
380 SCEnter();
381
c8fb9bcb 382 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].option_flags |= flags;
c862bbdc
JI
383
384 SCReturn;
385}
386
ac3cf6ff
VJ
387uint32_t AppLayerParserGetOptionFlags(uint8_t protomap, AppProto alproto)
388{
389 SCEnter();
390 SCReturnUInt(alp_ctx.ctxs[protomap][alproto].option_flags);
391}
392
5cdeadb3 393void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto,
547d6c2d 394 void *(*StateAlloc)(void *, AppProto), void (*StateFree)(void *))
c1e485cc 395{
574bcea0
VJ
396 SCEnter();
397
429c6388
AS
398 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateAlloc =
399 StateAlloc;
400 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateFree =
401 StateFree;
086ba5f4 402
429c6388
AS
403 SCReturn;
404}
086ba5f4 405
5cdeadb3 406void AppLayerParserRegisterLocalStorageFunc(uint8_t ipproto, AppProto alproto,
429c6388
AS
407 void *(*LocalStorageAlloc)(void),
408 void (*LocalStorageFree)(void *))
409{
410 SCEnter();
574bcea0 411
429c6388
AS
412 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].LocalStorageAlloc =
413 LocalStorageAlloc;
414 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].LocalStorageFree =
415 LocalStorageFree;
086ba5f4 416
429c6388
AS
417 SCReturn;
418}
086ba5f4 419
5cdeadb3 420void AppLayerParserRegisterGetFilesFunc(uint8_t ipproto, AppProto alproto,
429c6388
AS
421 FileContainer *(*StateGetFiles)(void *, uint8_t))
422{
423 SCEnter();
086ba5f4 424
429c6388
AS
425 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetFiles =
426 StateGetFiles;
086ba5f4 427
429c6388
AS
428 SCReturn;
429}
086ba5f4 430
01724f04
VJ
431void AppLayerParserRegisterLoggerBits(uint8_t ipproto, AppProto alproto, LoggerId bits)
432{
433 SCEnter();
434
435 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].logger_bits = bits;
436
437 SCReturn;
438}
439
5cdeadb3 440void AppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto)
429c6388
AS
441{
442 SCEnter();
9f78d47c 443
66530c61 444 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].logger = true;
9f78d47c 445
429c6388
AS
446 SCReturn;
447}
9f78d47c 448
5cdeadb3 449void AppLayerParserRegisterTruncateFunc(uint8_t ipproto, AppProto alproto,
429c6388
AS
450 void (*Truncate)(void *, uint8_t))
451{
452 SCEnter();
574bcea0 453
429c6388 454 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].Truncate = Truncate;
574bcea0 455
429c6388
AS
456 SCReturn;
457}
9f78d47c 458
5cdeadb3 459void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto,
429c6388
AS
460 int (*StateGetProgress)(void *alstate, uint8_t direction))
461{
462 SCEnter();
9f78d47c 463
429c6388
AS
464 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
465 StateGetProgress = StateGetProgress;
9f78d47c 466
429c6388 467 SCReturn;
9f78d47c
VJ
468}
469
5cdeadb3 470void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto,
429c6388 471 void (*StateTransactionFree)(void *, uint64_t))
c1e485cc 472{
574bcea0 473 SCEnter();
9f78d47c 474
429c6388
AS
475 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
476 StateTransactionFree = StateTransactionFree;
9f78d47c 477
429c6388
AS
478 SCReturn;
479}
9f78d47c 480
5cdeadb3 481void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto,
429c6388
AS
482 uint64_t (*StateGetTxCnt)(void *alstate))
483{
484 SCEnter();
9f78d47c 485
429c6388
AS
486 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
487 StateGetTxCnt = StateGetTxCnt;
9f78d47c 488
429c6388
AS
489 SCReturn;
490}
9f78d47c 491
5cdeadb3 492void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto,
429c6388
AS
493 void *(StateGetTx)(void *alstate, uint64_t tx_id))
494{
495 SCEnter();
9f78d47c 496
429c6388
AS
497 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
498 StateGetTx = StateGetTx;
9f78d47c 499
429c6388 500 SCReturn;
9f78d47c
VJ
501}
502
e96d9c11
VJ
503void AppLayerParserRegisterGetTxIterator(uint8_t ipproto, AppProto alproto,
504 AppLayerGetTxIteratorFunc Func)
505{
506 SCEnter();
507 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetTxIterator = Func;
508 SCReturn;
509}
510
efc9a7a3
VJ
511void AppLayerParserRegisterStateProgressCompletionStatus(
512 AppProto alproto, const int ts, const int tc)
c1e485cc 513{
efc9a7a3
VJ
514 BUG_ON(ts == 0);
515 BUG_ON(tc == 0);
516 BUG_ON(!AppProtoIsValid(alproto));
517 BUG_ON(alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].complete_ts != 0 &&
518 alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].complete_ts != ts);
519 BUG_ON(alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].complete_tc != 0 &&
520 alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].complete_tc != tc);
f1f7df07 521
efc9a7a3
VJ
522 alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].complete_ts = ts;
523 alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].complete_tc = tc;
429c6388 524}
f1f7df07 525
50e23ba9
JL
526void AppLayerParserRegisterGetEventInfoById(uint8_t ipproto, AppProto alproto,
527 int (*StateGetEventInfoById)(int event_id, const char **event_name,
528 AppLayerEventType *event_type))
529{
530 SCEnter();
531
532 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
533 StateGetEventInfoById = StateGetEventInfoById;
534
535 SCReturn;
536}
4a39d7a1 537
5cdeadb3 538void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto,
429c6388
AS
539 int (*StateGetEventInfo)(const char *event_name, int *event_id,
540 AppLayerEventType *event_type))
541{
542 SCEnter();
f1f7df07 543
429c6388
AS
544 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
545 StateGetEventInfo = StateGetEventInfo;
d9686fae 546
429c6388
AS
547 SCReturn;
548}
d9686fae 549
411f428a
VJ
550void AppLayerParserRegisterTxDataFunc(uint8_t ipproto, AppProto alproto,
551 AppLayerTxData *(*GetTxData)(void *tx))
552{
553 SCEnter();
554
555 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxData = GetTxData;
556
557 SCReturn;
558}
559
5665fc83
VJ
560void AppLayerParserRegisterApplyTxConfigFunc(uint8_t ipproto, AppProto alproto,
561 bool (*ApplyTxConfig)(void *state, void *tx, int mode, AppLayerTxConfig))
562{
563 SCEnter();
564
565 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].ApplyTxConfig = ApplyTxConfig;
566
567 SCReturn;
568}
569
ed5a439b
GL
570void AppLayerParserRegisterSetStreamDepthFlag(uint8_t ipproto, AppProto alproto,
571 void (*SetStreamDepthFlag)(void *tx, uint8_t flags))
572{
573 SCEnter();
574
575 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetStreamDepthFlag = SetStreamDepthFlag;
576
577 SCReturn;
578}
579
429c6388 580/***** Get and transaction functions *****/
d9686fae 581
5cdeadb3 582void *AppLayerParserGetProtocolParserLocalStorage(uint8_t ipproto, AppProto alproto)
429c6388
AS
583{
584 SCEnter();
dc1599e0 585 void * r = NULL;
429c6388
AS
586
587 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
588 LocalStorageAlloc != NULL)
589 {
dc1599e0 590 r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
591 LocalStorageAlloc();
d9686fae
AS
592 }
593
dc1599e0 594 SCReturnPtr(r, "void *");
f1f7df07
VJ
595}
596
5cdeadb3 597void AppLayerParserDestroyProtocolParserLocalStorage(uint8_t ipproto, AppProto alproto,
429c6388 598 void *local_data)
68425453 599{
429c6388 600 SCEnter();
68425453 601
429c6388
AS
602 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
603 LocalStorageFree != NULL)
604 {
605 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
606 LocalStorageFree(local_data);
68425453
EL
607 }
608
429c6388 609 SCReturn;
68425453
EL
610}
611
e96d9c11
VJ
612/** \brief default tx iterator
613 *
614 * Used if the app layer parser doesn't register its own iterator.
615 * Simply walks the tx_id space until it finds a tx. Uses 'state' to
616 * keep track of where it left off.
617 *
618 * \retval txptr or NULL if no more txs in list
619 */
620static AppLayerGetTxIterTuple AppLayerDefaultGetTxIterator(
621 const uint8_t ipproto, const AppProto alproto,
622 void *alstate, uint64_t min_tx_id, uint64_t max_tx_id,
623 AppLayerGetTxIterState *state)
624{
625 uint64_t ustate = *(uint64_t *)state;
626 uint64_t tx_id = MAX(min_tx_id, ustate);
627 for ( ; tx_id < max_tx_id; tx_id++) {
628 void *tx_ptr = AppLayerParserGetTx(ipproto, alproto, alstate, tx_id);
629 if (tx_ptr != NULL) {
630 ustate = tx_id + 1;
631 *state = *(AppLayerGetTxIterState *)&ustate;
632 AppLayerGetTxIterTuple tuple = {
633 .tx_ptr = tx_ptr,
634 .tx_id = tx_id,
635 .has_next = (tx_id + 1 < max_tx_id),
636 };
da2c4d73 637 SCLogDebug("tuple: %p/%"PRIu64"/%s", tuple.tx_ptr, tuple.tx_id,
e96d9c11
VJ
638 tuple.has_next ? "true" : "false");
639 return tuple;
640 }
641 }
642
643 AppLayerGetTxIterTuple no_tuple = { NULL, 0, false };
644 return no_tuple;
645}
646
647AppLayerGetTxIteratorFunc AppLayerGetTxIterator(const uint8_t ipproto,
648 const AppProto alproto)
649{
650 AppLayerGetTxIteratorFunc Func =
651 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetTxIterator;
652 return Func ? Func : AppLayerDefaultGetTxIterator;
653}
654
9634e60e 655uint64_t AppLayerParserGetTransactionLogId(AppLayerParserState *pstate)
c1e485cc 656{
429c6388 657 SCEnter();
8e10844f 658
0564a8da 659 SCReturnCT((pstate == NULL) ? 0 : pstate->log_id, "uint64_t");
429c6388 660}
8e10844f 661
e9fccfa6 662void AppLayerParserSetTransactionLogId(AppLayerParserState *pstate, uint64_t tx_id)
429c6388
AS
663{
664 SCEnter();
5fc30051 665
0564a8da 666 if (pstate != NULL)
e9fccfa6 667 pstate->log_id = tx_id;
5a9a23f9 668
429c6388 669 SCReturn;
8e10844f
VJ
670}
671
9634e60e 672uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction)
c1e485cc 673{
429c6388 674 SCEnter();
8e10844f 675
0564a8da
VJ
676 if (pstate == NULL)
677 SCReturnCT(0ULL, "uint64_t");
678
9634e60e 679 SCReturnCT(pstate->inspect_id[direction & STREAM_TOSERVER ? 0 : 1], "uint64_t");
429c6388 680}
5fc30051 681
a2f249cc 682static inline uint64_t GetTxDetectFlags(AppLayerTxData *txd, const uint8_t dir)
e15995e2 683{
a2f249cc
VJ
684 uint64_t detect_flags =
685 (dir & STREAM_TOSERVER) ? txd->detect_flags_ts : txd->detect_flags_tc;
e15995e2
VJ
686 return detect_flags;
687}
688
a2f249cc 689static inline void SetTxDetectFlags(AppLayerTxData *txd, const uint8_t dir, const uint64_t detect_flags)
e15995e2 690{
a2f249cc
VJ
691 if (dir & STREAM_TOSERVER) {
692 txd->detect_flags_ts = detect_flags;
693 } else {
694 txd->detect_flags_tc = detect_flags;
e15995e2
VJ
695 }
696}
697
a2f249cc 698static inline uint32_t GetTxLogged(AppLayerTxData *txd)
e15995e2 699{
a2f249cc 700 return txd->logged.flags;
e15995e2
VJ
701}
702
5c01b409 703void AppLayerParserSetTransactionInspectId(const Flow *f, AppLayerParserState *pstate,
af51e0f5
VJ
704 void *alstate, const uint8_t flags,
705 bool tag_txs_as_inspected)
429c6388
AS
706{
707 SCEnter();
59780ca7 708
3fc87595 709 const int direction = (flags & STREAM_TOSERVER) ? 0 : 1;
5c01b409 710 const uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
6946e0be 711 uint64_t idx = AppLayerParserGetTransactionInspectId(pstate, flags);
5c01b409 712 const int state_done_progress = AppLayerParserGetStateProgressCompletionStatus(f->alproto, flags);
af51e0f5
VJ
713 const uint8_t ipproto = f->proto;
714 const AppProto alproto = f->alproto;
8e10844f 715
e96d9c11
VJ
716 AppLayerGetTxIteratorFunc IterFunc = AppLayerGetTxIterator(ipproto, alproto);
717 AppLayerGetTxIterState state;
718 memset(&state, 0, sizeof(state));
719
7a96d18f
VJ
720 SCLogDebug("called: %s, tag_txs_as_inspected %s",direction==0?"toserver":"toclient",
721 tag_txs_as_inspected?"true":"false");
722
723 /* mark all txs as inspected if the applayer progress is
724 * at the 'end state'. */
e96d9c11
VJ
725 while (1) {
726 AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, idx, total_txs, &state);
727 if (ires.tx_ptr == NULL)
728 break;
729
730 void *tx = ires.tx_ptr;
731 idx = ires.tx_id;
732
af51e0f5 733 int state_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx, flags);
e96d9c11
VJ
734 if (state_progress < state_done_progress)
735 break;
736
a2f249cc
VJ
737 AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
738 if (txd && tag_txs_as_inspected) {
739 uint64_t detect_flags = GetTxDetectFlags(txd, flags);
e96d9c11
VJ
740 if ((detect_flags & APP_LAYER_TX_INSPECTED_FLAG) == 0) {
741 detect_flags |= APP_LAYER_TX_INSPECTED_FLAG;
a2f249cc 742 SetTxDetectFlags(txd, flags, detect_flags);
e96d9c11
VJ
743 SCLogDebug("%p/%"PRIu64" in-order tx is done for direction %s. Flag %016"PRIx64,
744 tx, idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags);
af51e0f5 745 }
e96d9c11 746 }
618ad0d9 747 idx++;
e96d9c11 748 if (!ires.has_next)
429c6388 749 break;
8e10844f 750 }
6946e0be 751 pstate->inspect_id[direction] = idx;
7a96d18f 752 SCLogDebug("inspect_id now %"PRIu64, pstate->inspect_id[direction]);
8e10844f 753
7a96d18f
VJ
754 /* if necessary we flag all txs that are complete as 'inspected'
755 * also move inspect_id forward. */
af51e0f5 756 if (tag_txs_as_inspected) {
e96d9c11
VJ
757 /* continue at idx */
758 while (1) {
759 AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, idx, total_txs, &state);
760 if (ires.tx_ptr == NULL)
761 break;
762
763 void *tx = ires.tx_ptr;
764 /* if we got a higher id than the minimum we requested, we
765 * skipped a bunch of 'null-txs'. Lets see if we can up the
766 * inspect tracker */
767 if (ires.tx_id > idx && pstate->inspect_id[direction] == idx) {
768 pstate->inspect_id[direction] = ires.tx_id;
af51e0f5 769 }
e96d9c11
VJ
770 idx = ires.tx_id;
771
772 const int state_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx, flags);
773 if (state_progress < state_done_progress)
774 break;
775
a2f249cc
VJ
776 /* txd can be NULL for HTTP sessions where the user data alloc failed */
777 AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
778 if (likely(txd)) {
779 uint64_t detect_flags = GetTxDetectFlags(txd, flags);
780 if ((detect_flags & APP_LAYER_TX_INSPECTED_FLAG) == 0) {
781 detect_flags |= APP_LAYER_TX_INSPECTED_FLAG;
782 SetTxDetectFlags(txd, flags, detect_flags);
783 SCLogDebug("%p/%"PRIu64" out of order tx is done for direction %s. Flag %016"PRIx64,
784 tx, idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags);
785
786 SCLogDebug("%p/%"PRIu64" out of order tx. Update inspect_id? %"PRIu64,
787 tx, idx, pstate->inspect_id[direction]);
788 if (pstate->inspect_id[direction]+1 == idx)
789 pstate->inspect_id[direction] = idx;
790 }
791 } else {
7a96d18f
VJ
792 if (pstate->inspect_id[direction]+1 == idx)
793 pstate->inspect_id[direction] = idx;
794 }
e96d9c11
VJ
795 if (!ires.has_next)
796 break;
0e402311 797 idx++;
af51e0f5
VJ
798 }
799 }
800
429c6388 801 SCReturn;
9faa4b74 802}
9faa4b74 803
9634e60e 804AppLayerDecoderEvents *AppLayerParserGetDecoderEvents(AppLayerParserState *pstate)
c1e485cc 805{
429c6388 806 SCEnter();
9f78d47c 807
9634e60e 808 SCReturnPtr(pstate->decoder_events,
429c6388 809 "AppLayerDecoderEvents *");
70b32f73
VJ
810}
811
9634e60e 812void AppLayerParserSetDecoderEvents(AppLayerParserState *pstate, AppLayerDecoderEvents *devents)
9a6aef45 813{
9634e60e 814 pstate->decoder_events = devents;
9a6aef45
AS
815}
816
5cdeadb3 817AppLayerDecoderEvents *AppLayerParserGetEventsByTx(uint8_t ipproto, AppProto alproto,
d568e7fa 818 void *tx)
869109a6 819{
429c6388 820 SCEnter();
869109a6 821
429c6388 822 AppLayerDecoderEvents *ptr = NULL;
869109a6 823
7732efbe
JI
824 /* Access events via the tx_data. */
825 AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
826 if (txd != NULL && txd->events != NULL) {
827 ptr = txd->events;
01a35bb6
AS
828 }
829
429c6388 830 SCReturnPtr(ptr, "AppLayerDecoderEvents *");
6cb00142 831}
70b32f73 832
a4a4d17a 833FileContainer *AppLayerParserGetFiles(const Flow *f, const uint8_t direction)
c1e485cc 834{
91bc83e5 835 SCEnter();
8e10844f 836
429c6388 837 FileContainer *ptr = NULL;
45d86ff5 838
a4a4d17a 839 if (alp_ctx.ctxs[f->protomap][f->alproto].StateGetFiles != NULL)
429c6388 840 {
a4a4d17a
VJ
841 ptr = alp_ctx.ctxs[f->protomap][f->alproto].
842 StateGetFiles(f->alstate, direction);
3b3dce83 843 }
5ba41c78 844
429c6388 845 SCReturnPtr(ptr, "FileContainer *");
70b32f73 846}
70b32f73 847
daffcc6e
VJ
848#define IS_DISRUPTED(flags) ((flags) & (STREAM_DEPTH | STREAM_GAP))
849
2cfa35cc 850extern int g_detect_disabled;
c78f5ac3 851extern bool g_file_logger_enabled;
56d3e28a 852extern bool g_filedata_logger_enabled;
c78f5ac3 853
c06c595c
VJ
854/**
855 * \brief remove obsolete (inspected and logged) transactions
856 */
7a96d18f 857void AppLayerParserTransactionsCleanup(Flow *f)
c06c595c 858{
e62e4bdc 859 SCEnter();
c06c595c
VJ
860 DEBUG_ASSERT_FLOW_LOCKED(f);
861
3fc87595
VJ
862 AppLayerParserProtoCtx *p = &alp_ctx.ctxs[f->protomap][f->alproto];
863 if (unlikely(p->StateTransactionFree == NULL))
e62e4bdc 864 SCReturn;
c06c595c 865
1098e3b7 866 const bool has_tx_detect_flags = !g_detect_disabled;
7a96d18f
VJ
867 const uint8_t ipproto = f->proto;
868 const AppProto alproto = f->alproto;
869 void * const alstate = f->alstate;
870 AppLayerParserState * const alparser = f->alparser;
871
872 if (alstate == NULL || alparser == NULL)
e62e4bdc 873 SCReturn;
7a96d18f
VJ
874
875 const uint64_t min = alparser->min_id;
876 const uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
877 const LoggerId logger_expectation = AppLayerParserProtocolGetLoggerBits(ipproto, alproto);
878 const int tx_end_state_ts = AppLayerParserGetStateProgressCompletionStatus(alproto, STREAM_TOSERVER);
879 const int tx_end_state_tc = AppLayerParserGetStateProgressCompletionStatus(alproto, STREAM_TOCLIENT);
daffcc6e
VJ
880 const uint8_t ts_disrupt_flags = FlowGetDisruptionFlags(f, STREAM_TOSERVER);
881 const uint8_t tc_disrupt_flags = FlowGetDisruptionFlags(f, STREAM_TOCLIENT);
7a96d18f 882
e96d9c11
VJ
883 AppLayerGetTxIteratorFunc IterFunc = AppLayerGetTxIterator(ipproto, alproto);
884 AppLayerGetTxIterState state;
885 memset(&state, 0, sizeof(state));
886 uint64_t i = min;
887 uint64_t new_min = min;
e62e4bdc 888 SCLogDebug("start min %"PRIu64, min);
d34e4106 889 bool skipped = false;
60ebc27c
JI
890 const bool is_unidir =
891 AppLayerParserGetOptionFlags(f->protomap, f->alproto) & APP_LAYER_PARSER_OPT_UNIDIR_TXS;
e96d9c11
VJ
892
893 while (1) {
894 AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, i, total_txs, &state);
895 if (ires.tx_ptr == NULL)
896 break;
897
8baef60d 898 bool tx_skipped = false;
e96d9c11 899 void *tx = ires.tx_ptr;
0e402311 900 i = ires.tx_id; // actual tx id for the tx the IterFunc returned
e96d9c11 901
7a96d18f 902 SCLogDebug("%p/%"PRIu64" checking", tx, i);
5b56d324 903
daffcc6e
VJ
904 const int tx_progress_tc =
905 AppLayerParserGetStateProgress(ipproto, alproto, tx, tc_disrupt_flags);
7a96d18f
VJ
906 if (tx_progress_tc < tx_end_state_tc) {
907 SCLogDebug("%p/%"PRIu64" skipping: tc parser not done", tx, i);
d34e4106 908 skipped = true;
e96d9c11 909 goto next;
7a96d18f 910 }
daffcc6e
VJ
911 const int tx_progress_ts =
912 AppLayerParserGetStateProgress(ipproto, alproto, tx, ts_disrupt_flags);
7a96d18f
VJ
913 if (tx_progress_ts < tx_end_state_ts) {
914 SCLogDebug("%p/%"PRIu64" skipping: ts parser not done", tx, i);
d34e4106 915 skipped = true;
e96d9c11 916 goto next;
7a96d18f 917 }
daffcc6e 918
a2f249cc 919 AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
60ebc27c 920 bool inspected = false;
a2f249cc 921 if (txd && has_tx_detect_flags) {
daffcc6e 922 if (!IS_DISRUPTED(ts_disrupt_flags) && f->sgh_toserver != NULL) {
a2f249cc 923 uint64_t detect_flags_ts = GetTxDetectFlags(txd, STREAM_TOSERVER);
ab471c30
VJ
924 if (!(detect_flags_ts & APP_LAYER_TX_INSPECTED_FLAG)) {
925 SCLogDebug("%p/%"PRIu64" skipping: TS inspect not done: ts:%"PRIx64,
926 tx, i, detect_flags_ts);
afaa18c5 927 tx_skipped = true;
60ebc27c
JI
928 } else {
929 inspected = true;
ab471c30 930 }
7a96d18f 931 }
daffcc6e 932 if (!IS_DISRUPTED(tc_disrupt_flags) && f->sgh_toclient != NULL) {
a2f249cc 933 uint64_t detect_flags_tc = GetTxDetectFlags(txd, STREAM_TOCLIENT);
ab471c30
VJ
934 if (!(detect_flags_tc & APP_LAYER_TX_INSPECTED_FLAG)) {
935 SCLogDebug("%p/%"PRIu64" skipping: TC inspect not done: tc:%"PRIx64,
936 tx, i, detect_flags_tc);
afaa18c5 937 tx_skipped = true;
60ebc27c
JI
938 } else {
939 inspected = true;
ab471c30 940 }
7a96d18f
VJ
941 }
942 }
60ebc27c
JI
943
944 // If not a unidirectional transaction both sides are required to have
945 // been inspected.
8baef60d
VJ
946 if (!is_unidir && tx_skipped) {
947 SCLogDebug("%p/%" PRIu64 " !is_unidir && tx_skipped", tx, i);
afaa18c5 948 skipped = true;
60ebc27c
JI
949 goto next;
950 }
951
952 // If this is a unidirectional transaction require only one side to be
953 // inspected, which the inspected flag tells us. This is also guarded
954 // with skip to limit this check to transactions that actually had the
955 // tx inspected flag checked.
8baef60d
VJ
956 if (is_unidir && tx_skipped && !inspected) {
957 SCLogDebug("%p/%" PRIu64 " is_unidir && tx_skipped && !inspected", tx, i);
afaa18c5 958 skipped = true;
60ebc27c
JI
959 goto next;
960 }
961
2cfa35cc 962 if (txd && logger_expectation != 0) {
a2f249cc 963 LoggerId tx_logged = GetTxLogged(txd);
7a96d18f
VJ
964 if (tx_logged != logger_expectation) {
965 SCLogDebug("%p/%"PRIu64" skipping: logging not done: want:%"PRIx32", have:%"PRIx32,
966 tx, i, logger_expectation, tx_logged);
d34e4106 967 skipped = true;
e96d9c11 968 goto next;
7a96d18f
VJ
969 }
970 }
5b56d324 971
c78f5ac3
VJ
972 /* if file logging is enabled, we keep a tx active while some of the files aren't
973 * logged yet. */
56d3e28a
VJ
974 if (txd && txd->files_opened) {
975 if (g_file_logger_enabled && txd->files_opened != txd->files_logged) {
976 skipped = true;
977 goto next;
978 }
979 if (g_filedata_logger_enabled && txd->files_opened != txd->files_stored) {
c78f5ac3
VJ
980 skipped = true;
981 goto next;
982 }
983 }
984
7a96d18f
VJ
985 /* if we are here, the tx can be freed. */
986 p->StateTransactionFree(alstate, i);
987 SCLogDebug("%p/%"PRIu64" freed", tx, i);
e96d9c11 988
d34e4106 989 /* if we didn't skip any tx so far, up the minimum */
0e402311 990 SCLogDebug("skipped? %s i %"PRIu64", new_min %"PRIu64, skipped ? "true" : "false", i, new_min);
d34e4106 991 if (!skipped)
e96d9c11 992 new_min = i + 1;
0e402311 993 SCLogDebug("final i %"PRIu64", new_min %"PRIu64, i, new_min);
e96d9c11
VJ
994
995next:
0e402311
VJ
996 if (!ires.has_next) {
997 /* this was the last tx. See if we skipped any. If not
998 * we removed all and can update the minimum to the max
999 * id. */
1000 SCLogDebug("no next: cur tx i %"PRIu64", total %"PRIu64, i, total_txs);
1001 if (!skipped) {
1002 new_min = total_txs;
1003 SCLogDebug("no next: cur tx i %"PRIu64", total %"PRIu64": "
1004 "new_min updated to %"PRIu64, i, total_txs, new_min);
1005 }
e96d9c11 1006 break;
0e402311
VJ
1007 }
1008 i++;
e96d9c11
VJ
1009 }
1010
1011 /* see if we need to bring all trackers up to date. */
e62e4bdc 1012 SCLogDebug("update f->alparser->min_id? %"PRIu64" vs %"PRIu64, new_min, alparser->min_id);
e96d9c11
VJ
1013 if (new_min > alparser->min_id) {
1014 const uint64_t next_id = new_min;
1015 alparser->min_id = next_id;
1016 alparser->inspect_id[0] = MAX(alparser->inspect_id[0], next_id);
1017 alparser->inspect_id[1] = MAX(alparser->inspect_id[1], next_id);
1018 alparser->log_id = MAX(alparser->log_id, next_id);
1019 SCLogDebug("updated f->alparser->min_id %"PRIu64, alparser->min_id);
c06c595c 1020 }
e62e4bdc 1021 SCReturn;
c06c595c
VJ
1022}
1023
efc9a7a3
VJ
1024static inline int StateGetProgressCompletionStatus(const AppProto alproto, const uint8_t flags)
1025{
1026 if (flags & STREAM_TOSERVER) {
1027 return alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].complete_ts;
1028 } else if (flags & STREAM_TOCLIENT) {
1029 return alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].complete_tc;
1030 } else {
1031 DEBUG_VALIDATE_BUG_ON(1);
1032 return 0;
1033 }
1034}
1035
ea571add
VJ
1036/**
1037 * \brief get the progress value for a tx/protocol
1038 *
1039 * If the stream is disrupted, we return the 'completion' value.
1040 */
5cdeadb3 1041int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto,
ea571add 1042 void *alstate, uint8_t flags)
d4d18e31 1043{
73efb4c7 1044 SCEnter();
b05bd058 1045 int r;
ea571add 1046 if (unlikely(IS_DISRUPTED(flags))) {
efc9a7a3 1047 r = StateGetProgressCompletionStatus(alproto, flags);
ea571add
VJ
1048 } else {
1049 r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
1050 StateGetProgress(alstate, flags);
1051 }
dc1599e0 1052 SCReturnInt(r);
d4d18e31 1053}
70b32f73 1054
5c01b409 1055uint64_t AppLayerParserGetTxCnt(const Flow *f, void *alstate)
d4d18e31 1056{
16cfae2f 1057 SCEnter();
b05bd058 1058 uint64_t r = alp_ctx.ctxs[f->protomap][f->alproto].StateGetTxCnt(alstate);
dc1599e0 1059 SCReturnCT(r, "uint64_t");
16cfae2f
VJ
1060}
1061
5cdeadb3 1062void *AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
ddde572f 1063{
429c6388 1064 SCEnter();
b05bd058 1065 void *r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetTx(alstate, tx_id);
dc1599e0 1066 SCReturnPtr(r, "void *");
ddde572f
AS
1067}
1068
c4b918b6
MK
1069int AppLayerParserGetStateProgressCompletionStatus(AppProto alproto,
1070 uint8_t direction)
6cb00142 1071{
429c6388 1072 SCEnter();
efc9a7a3 1073 int r = StateGetProgressCompletionStatus(alproto, direction);
dc1599e0 1074 SCReturnInt(r);
6cb00142
AS
1075}
1076
5cdeadb3 1077int AppLayerParserGetEventInfo(uint8_t ipproto, AppProto alproto, const char *event_name,
429c6388 1078 int *event_id, AppLayerEventType *event_type)
6f8cfd99 1079{
429c6388 1080 SCEnter();
b05bd058 1081 const int ipproto_map = FlowGetProtoMapping(ipproto);
1cbd1cdf
VJ
1082 int r = (alp_ctx.ctxs[ipproto_map][alproto].StateGetEventInfo == NULL) ?
1083 -1 : alp_ctx.ctxs[ipproto_map][alproto].StateGetEventInfo(event_name, event_id, event_type);
1084 SCReturnInt(r);
6f8cfd99
AS
1085}
1086
50e23ba9
JL
1087int AppLayerParserGetEventInfoById(uint8_t ipproto, AppProto alproto, int event_id,
1088 const char **event_name, AppLayerEventType *event_type)
1089{
1090 SCEnter();
b05bd058 1091 const int ipproto_map = FlowGetProtoMapping(ipproto);
50e23ba9
JL
1092 *event_name = (const char *)NULL;
1093 int r = (alp_ctx.ctxs[ipproto_map][alproto].StateGetEventInfoById == NULL) ?
1094 -1 : alp_ctx.ctxs[ipproto_map][alproto].StateGetEventInfoById(event_id, event_name, event_type);
1095 SCReturnInt(r);
1096}
1097
f5f14880 1098uint8_t AppLayerParserGetFirstDataDir(uint8_t ipproto, AppProto alproto)
432c3317 1099{
429c6388 1100 SCEnter();
b05bd058 1101 uint8_t r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].first_data_dir;
dc1599e0 1102 SCReturnCT(r, "uint8_t");
432c3317 1103}
7c31a232 1104
3148ff34
VJ
1105uint64_t AppLayerParserGetTransactionActive(const Flow *f,
1106 AppLayerParserState *pstate, uint8_t direction)
d9686fae 1107{
429c6388 1108 SCEnter();
d9686fae 1109
429c6388 1110 uint64_t active_id;
9634e60e
VJ
1111 uint64_t log_id = pstate->log_id;
1112 uint64_t inspect_id = pstate->inspect_id[direction & STREAM_TOSERVER ? 0 : 1];
66530c61 1113 if (alp_ctx.ctxs[f->protomap][f->alproto].logger == true) {
b05bd058 1114 active_id = MIN(log_id, inspect_id);
429c6388
AS
1115 } else {
1116 active_id = inspect_id;
d9686fae 1117 }
d9686fae 1118
429c6388 1119 SCReturnCT(active_id, "uint64_t");
d9686fae
AS
1120}
1121
bcfa484b
VJ
1122int AppLayerParserSupportsFiles(uint8_t ipproto, AppProto alproto)
1123{
93e6401c 1124 // Custom case for only signature-only protocol so far
707f0272
PA
1125 if (alproto == ALPROTO_HTTP) {
1126 return AppLayerParserSupportsFiles(ipproto, ALPROTO_HTTP1) ||
93e6401c
PA
1127 AppLayerParserSupportsFiles(ipproto, ALPROTO_HTTP2);
1128 }
bcfa484b
VJ
1129 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetFiles != NULL)
1130 return TRUE;
1131 return FALSE;
1132}
1133
411f428a
VJ
1134AppLayerTxData *AppLayerParserGetTxData(uint8_t ipproto, AppProto alproto, void *tx)
1135{
1136 SCEnter();
1098e3b7
VJ
1137 AppLayerTxData *d = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxData(tx);
1138 SCReturnPtr(d, "AppLayerTxData");
411f428a
VJ
1139}
1140
5665fc83
VJ
1141void AppLayerParserApplyTxConfig(uint8_t ipproto, AppProto alproto,
1142 void *state, void *tx, enum ConfigAction mode, AppLayerTxConfig config)
1143{
1144 SCEnter();
b05bd058
VJ
1145 const int ipproto_map = FlowGetProtoMapping(ipproto);
1146 if (alp_ctx.ctxs[ipproto_map][alproto].ApplyTxConfig) {
1147 alp_ctx.ctxs[ipproto_map][alproto].ApplyTxConfig(state, tx, mode, config);
5665fc83
VJ
1148 }
1149 SCReturn;
1150}
1151
429c6388
AS
1152/***** General *****/
1153
4f73943d
VJ
1154static inline void SetEOFFlags(AppLayerParserState *pstate, const uint8_t flags)
1155{
1156 if ((flags & (STREAM_EOF|STREAM_TOSERVER)) == (STREAM_EOF|STREAM_TOSERVER)) {
1157 SCLogDebug("setting APP_LAYER_PARSER_EOF_TS");
1158 AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_EOF_TS);
1159 } else if ((flags & (STREAM_EOF|STREAM_TOCLIENT)) == (STREAM_EOF|STREAM_TOCLIENT)) {
1160 SCLogDebug("setting APP_LAYER_PARSER_EOF_TC");
1161 AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_EOF_TC);
1162 }
1163}
1164
674b8dc0 1165/** \retval int -1 in case of unrecoverable error. App-layer tracking stops for this flow.
9b1f0656
VJ
1166 * \retval int 0 ok: we did not update app_progress
1167 * \retval int 1 ok: we updated app_progress */
675fa564 1168int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto,
579cc9f0 1169 uint8_t flags, const uint8_t *input, uint32_t input_len)
d9686fae 1170{
429c6388 1171 SCEnter();
a77b9b36
VJ
1172#ifdef DEBUG_VALIDATION
1173 BUG_ON(f->protomap != FlowGetProtoMapping(f->proto));
1174#endif
6608b9a5 1175 AppLayerParserState *pstate = f->alparser;
a77b9b36 1176 AppLayerParserProtoCtx *p = &alp_ctx.ctxs[f->protomap][alproto];
429c6388 1177 void *alstate = NULL;
a194dfbd 1178 uint64_t p_tx_cnt = 0;
674b8dc0
VJ
1179 uint32_t consumed = input_len;
1180 const int direction = (flags & STREAM_TOSERVER) ? 0 : 1;
d9686fae 1181
429c6388
AS
1182 /* we don't have the parser registered for this protocol */
1183 if (p->StateAlloc == NULL)
1184 goto end;
d9686fae 1185
429c6388 1186 if (flags & STREAM_GAP) {
c8fb9bcb 1187 if (!(p->option_flags & APP_LAYER_PARSER_OPT_ACCEPT_GAPS)) {
c862bbdc 1188 SCLogDebug("app-layer parser does not accept gaps");
518e0e66 1189 if (f->alstate != NULL && !FlowChangeProto(f)) {
c862bbdc
JI
1190 AppLayerParserStreamTruncated(f->proto, alproto, f->alstate,
1191 flags);
1192 }
1193 goto error;
1194 }
d9686fae 1195 }
d9686fae 1196
429c6388 1197 /* Get the parser state (if any) */
429c6388 1198 if (pstate == NULL) {
8527b8e0 1199 f->alparser = pstate = AppLayerParserStateAlloc();
429c6388
AS
1200 if (pstate == NULL)
1201 goto error;
d9686fae
AS
1202 }
1203
4f73943d 1204 SetEOFFlags(pstate, flags);
7c31a232 1205
429c6388 1206 alstate = f->alstate;
21e74179 1207 if (alstate == NULL || FlowChangeProto(f)) {
547d6c2d 1208 f->alstate = alstate = p->StateAlloc(alstate, f->alproto_orig);
429c6388
AS
1209 if (alstate == NULL)
1210 goto error;
1211 SCLogDebug("alloced new app layer state %p (name %s)",
1212 alstate, AppLayerGetProtoName(f->alproto));
1213 } else {
1214 SCLogDebug("using existing app layer state %p (name %s))",
1215 alstate, AppLayerGetProtoName(f->alproto));
6e0d98d9 1216 }
429c6388 1217
952cbb56 1218 p_tx_cnt = AppLayerParserGetTxCnt(f, f->alstate);
a194dfbd 1219
429c6388 1220 /* invoke the recursive parser, but only on data. We may get empty msgs on EOF */
cf9ff6ad 1221 if (input_len > 0 || (flags & STREAM_EOF)) {
429c6388 1222 /* invoke the parser */
674b8dc0 1223 AppLayerResult res = p->Parser[direction](f, alstate, pstate,
429c6388 1224 input, input_len,
7bc3c3ac 1225 alp_tctx->alproto_local_storage[f->protomap][alproto],
3bcf948a 1226 flags);
fbdc7765 1227 if (res.status < 0) {
59327e0f 1228 goto error;
674b8dc0 1229 } else if (res.status > 0) {
fbdc7765
VJ
1230 DEBUG_VALIDATE_BUG_ON(res.consumed > input_len);
1231 DEBUG_VALIDATE_BUG_ON(res.needed + res.consumed < input_len);
1232 DEBUG_VALIDATE_BUG_ON(res.needed == 0);
1233 /* incomplete is only supported for TCP */
1234 DEBUG_VALIDATE_BUG_ON(f->proto != IPPROTO_TCP);
1235
1236 /* put protocol in error state on improper use of the
1237 * return codes. */
1238 if (res.consumed > input_len || res.needed + res.consumed < input_len) {
1239 goto error;
1240 }
1241
674b8dc0
VJ
1242 if (f->proto == IPPROTO_TCP && f->protoctx != NULL) {
1243 TcpSession *ssn = f->protoctx;
1244 SCLogDebug("direction %d/%s", direction,
1245 (flags & STREAM_TOSERVER) ? "toserver" : "toclient");
674b8dc0
VJ
1246 if (direction == 0) {
1247 /* parser told us how much data it needs on top of what it
1248 * consumed. So we need tell stream engine how much we need
1249 * before the next call */
1250 ssn->client.data_required = res.needed;
1251 SCLogDebug("setting data_required %u", ssn->client.data_required);
1252 } else {
1253 /* parser told us how much data it needs on top of what it
1254 * consumed. So we need tell stream engine how much we need
1255 * before the next call */
1256 ssn->server.data_required = res.needed;
1257 SCLogDebug("setting data_required %u", ssn->server.data_required);
1258 }
674b8dc0 1259 }
674b8dc0 1260 consumed = res.consumed;
59327e0f 1261 }
6e0d98d9 1262 }
429c6388
AS
1263
1264 /* set the packets to no inspection and reassembly if required */
1265 if (pstate->flags & APP_LAYER_PARSER_NO_INSPECTION) {
1266 AppLayerParserSetEOF(pstate);
1267 FlowSetNoPayloadInspectionFlag(f);
429c6388 1268
c1558f5a
VJ
1269 if (f->proto == IPPROTO_TCP) {
1270 StreamTcpDisableAppLayer(f);
1271
1272 /* Set the no reassembly flag for both the stream in this TcpSession */
1273 if (pstate->flags & APP_LAYER_PARSER_NO_REASSEMBLY) {
1274 /* Used only if it's TCP */
1275 TcpSession *ssn = f->protoctx;
1276 if (ssn != NULL) {
54b2ec0e
VJ
1277 StreamTcpSetSessionNoReassemblyFlag(ssn, 0);
1278 StreamTcpSetSessionNoReassemblyFlag(ssn, 1);
c1558f5a 1279 }
429c6388 1280 }
26eb49d7
EL
1281 /* Set the bypass flag for both the stream in this TcpSession */
1282 if (pstate->flags & APP_LAYER_PARSER_BYPASS_READY) {
1283 /* Used only if it's TCP */
1284 TcpSession *ssn = f->protoctx;
1285 if (ssn != NULL) {
1286 StreamTcpSetSessionBypassFlag(ssn);
1287 }
1288 }
429c6388 1289 }
7f8fb0f0
AS
1290 }
1291
26169ad8 1292 /* In cases like HeartBleed for TLS we need to inspect AppLayer but not Payload */
3543150f 1293 if (!(f->flags & FLOW_NOPAYLOAD_INSPECTION) && pstate->flags & APP_LAYER_PARSER_NO_INSPECTION_PAYLOAD) {
26169ad8 1294 FlowSetNoPayloadInspectionFlag(f);
3543150f
VJ
1295 /* Set the no reassembly flag for both the stream in this TcpSession */
1296 if (f->proto == IPPROTO_TCP) {
1297 /* Used only if it's TCP */
1298 TcpSession *ssn = f->protoctx;
1299 if (ssn != NULL) {
1300 StreamTcpSetDisableRawReassemblyFlag(ssn, 0);
1301 StreamTcpSetDisableRawReassemblyFlag(ssn, 1);
3543150f
VJ
1302 }
1303 }
26169ad8
WM
1304 }
1305
952cbb56
VJ
1306 /* get the diff in tx cnt for stats keeping */
1307 uint64_t cur_tx_cnt = AppLayerParserGetTxCnt(f, f->alstate);
1308 if (cur_tx_cnt > p_tx_cnt && tv) {
1309 AppLayerIncTxCounter(tv, f, cur_tx_cnt - p_tx_cnt);
a194dfbd 1310 }
429c6388
AS
1311
1312 /* stream truncated, inform app layer */
1313 if (flags & STREAM_DEPTH)
1314 AppLayerParserStreamTruncated(f->proto, alproto, alstate, flags);
1315
1316 end:
674b8dc0 1317 /* update app progress */
9b1f0656 1318 if (consumed != input_len && f->proto == IPPROTO_TCP && f->protoctx != NULL) {
674b8dc0
VJ
1319 TcpSession *ssn = f->protoctx;
1320 StreamTcpUpdateAppLayerProgress(ssn, direction, consumed);
9b1f0656 1321 SCReturnInt(1);
674b8dc0
VJ
1322 }
1323
429c6388 1324 SCReturnInt(0);
6e0d98d9 1325 error:
a77b9b36
VJ
1326 /* Set the no app layer inspection flag for both
1327 * the stream in this Flow */
c1558f5a
VJ
1328 if (f->proto == IPPROTO_TCP) {
1329 StreamTcpDisableAppLayer(f);
1330 }
a77b9b36 1331 AppLayerParserSetEOF(pstate);
429c6388 1332 SCReturnInt(-1);
7c31a232
AS
1333}
1334
9634e60e 1335void AppLayerParserSetEOF(AppLayerParserState *pstate)
7c31a232 1336{
429c6388 1337 SCEnter();
7c31a232 1338
429c6388
AS
1339 if (pstate == NULL)
1340 goto end;
1341
ecd7862c
VJ
1342 SCLogDebug("setting APP_LAYER_PARSER_EOF_TC and APP_LAYER_PARSER_EOF_TS");
1343 AppLayerParserStateSetFlag(pstate, (APP_LAYER_PARSER_EOF_TS|APP_LAYER_PARSER_EOF_TC));
429c6388
AS
1344
1345 end:
1346 SCReturn;
432c3317
AS
1347}
1348
af51e0f5
VJ
1349/* return true if there are app parser decoder events. These are
1350 * only the ones that are set during protocol detection. */
1351bool AppLayerParserHasDecoderEvents(AppLayerParserState *pstate)
432c3317 1352{
429c6388 1353 SCEnter();
432c3317 1354
af51e0f5
VJ
1355 if (pstate == NULL)
1356 return false;
7c31a232 1357
af51e0f5 1358 const AppLayerDecoderEvents *decoder_events = AppLayerParserGetDecoderEvents(pstate);
429c6388 1359 if (decoder_events && decoder_events->cnt)
af51e0f5 1360 return true;
429c6388
AS
1361
1362 /* if we have reached here, we don't have events */
948dee9a 1363 return false;
d9686fae
AS
1364}
1365
d369e54f 1366/** \brief simple way to globally test if a alproto is registered
01913f6a
VJ
1367 * and fully enabled in the configuration.
1368 */
d369e54f 1369int AppLayerParserIsEnabled(AppProto alproto)
01913f6a 1370{
efc9a7a3
VJ
1371 for (int i = 0; i < FLOW_PROTO_APPLAYER_MAX; i++) {
1372 if (alp_ctx.ctxs[i][alproto].StateGetProgress != NULL) {
1373 return 1;
1374 }
1375 }
1376 return 0;
01913f6a
VJ
1377}
1378
078ff0c0
VJ
1379int AppLayerParserProtocolHasLogger(uint8_t ipproto, AppProto alproto)
1380{
1381 SCEnter();
1382 int ipproto_map = FlowGetProtoMapping(ipproto);
66530c61 1383 int r = (alp_ctx.ctxs[ipproto_map][alproto].logger == false) ? 0 : 1;
078ff0c0
VJ
1384 SCReturnInt(r);
1385}
1386
bca0cd71
VJ
1387LoggerId AppLayerParserProtocolGetLoggerBits(uint8_t ipproto, AppProto alproto)
1388{
1389 SCEnter();
1390 const int ipproto_map = FlowGetProtoMapping(ipproto);
1391 LoggerId r = alp_ctx.ctxs[ipproto_map][alproto].logger_bits;
1392 SCReturnUInt(r);
1393}
1394
2d223b69 1395void AppLayerParserTriggerRawStreamReassembly(Flow *f, int direction)
432c3317 1396{
429c6388 1397 SCEnter();
432c3317 1398
2d223b69 1399 SCLogDebug("f %p tcp %p direction %d", f, f ? f->protoctx : NULL, direction);
429c6388 1400 if (f != NULL && f->protoctx != NULL)
2d223b69 1401 StreamTcpReassembleTriggerRawReassembly(f->protoctx, direction);
d9686fae 1402
429c6388 1403 SCReturn;
7c31a232
AS
1404}
1405
b160c49e
GL
1406void AppLayerParserSetStreamDepth(uint8_t ipproto, AppProto alproto, uint32_t stream_depth)
1407{
1408 SCEnter();
1409
1410 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].stream_depth = stream_depth;
c8fb9bcb
VJ
1411 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].internal_flags |=
1412 APP_LAYER_PARSER_INT_STREAM_DEPTH_SET;
b160c49e
GL
1413
1414 SCReturn;
1415}
1416
3148ff34 1417uint32_t AppLayerParserGetStreamDepth(const Flow *f)
b160c49e 1418{
3148ff34 1419 SCReturnInt(alp_ctx.ctxs[f->protomap][f->alproto].stream_depth);
b160c49e
GL
1420}
1421
ed5a439b
GL
1422void AppLayerParserSetStreamDepthFlag(uint8_t ipproto, AppProto alproto, void *state, uint64_t tx_id, uint8_t flags)
1423{
1424 SCEnter();
1425 void *tx = NULL;
1426 if (state != NULL) {
1427 if ((tx = AppLayerParserGetTx(ipproto, alproto, state, tx_id)) != NULL) {
1428 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetStreamDepthFlag != NULL) {
1429 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetStreamDepthFlag(tx, flags);
1430 }
1431 }
1432 }
1433 SCReturn;
1434}
1435
429c6388
AS
1436/***** Cleanup *****/
1437
21e74179
PA
1438void AppLayerParserStateProtoCleanup(
1439 uint8_t protomap, AppProto alproto, void *alstate, AppLayerParserState *pstate)
7c31a232 1440{
429c6388 1441 SCEnter();
7c31a232 1442
21e74179 1443 AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[protomap][alproto];
7c31a232 1444
429c6388
AS
1445 if (ctx->StateFree != NULL && alstate != NULL)
1446 ctx->StateFree(alstate);
7c31a232 1447
429c6388
AS
1448 /* free the app layer parser api state */
1449 if (pstate != NULL)
8527b8e0 1450 AppLayerParserStateFree(pstate);
432c3317 1451
429c6388
AS
1452 SCReturn;
1453}
432c3317 1454
21e74179
PA
1455void AppLayerParserStateCleanup(const Flow *f, void *alstate, AppLayerParserState *pstate)
1456{
1457 AppLayerParserStateProtoCleanup(f->protomap, f->alproto, alstate, pstate);
1458}
1459
ed172985
VJ
1460static void ValidateParserProtoDump(AppProto alproto, uint8_t ipproto)
1461{
1462 uint8_t map = FlowGetProtoMapping(ipproto);
1463 const AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[map][alproto];
ed172985
VJ
1464 printf("ERROR: incomplete app-layer registration\n");
1465 printf("AppLayer protocol %s ipproto %u\n", AppProtoToString(alproto), ipproto);
c8fb9bcb 1466 printf("- option flags %"PRIx32"\n", ctx->option_flags);
ed172985
VJ
1467 printf("- first_data_dir %"PRIx8"\n", ctx->first_data_dir);
1468 printf("Mandatory:\n");
1469 printf("- Parser[0] %p Parser[1] %p\n", ctx->Parser[0], ctx->Parser[1]);
1470 printf("- StateAlloc %p StateFree %p\n", ctx->StateAlloc, ctx->StateFree);
1471 printf("- StateGetTx %p StateGetTxCnt %p StateTransactionFree %p\n",
1472 ctx->StateGetTx, ctx->StateGetTxCnt, ctx->StateTransactionFree);
f8865720 1473 printf("- GetTxData %p\n", ctx->GetTxData);
efc9a7a3 1474 printf("- StateGetProgress %p\n", ctx->StateGetProgress);
ed172985
VJ
1475 printf("Optional:\n");
1476 printf("- LocalStorageAlloc %p LocalStorageFree %p\n", ctx->LocalStorageAlloc, ctx->LocalStorageFree);
7732efbe 1477 printf("- StateGetEventInfo %p StateGetEventInfoById %p\n", ctx->StateGetEventInfo,
a5d9d37c 1478 ctx->StateGetEventInfoById);
ed172985
VJ
1479}
1480
1481#define BOTH_SET(a, b) ((a) != NULL && (b) != NULL)
1482#define BOTH_SET_OR_BOTH_UNSET(a, b) (((a) == NULL && (b) == NULL) || ((a) != NULL && (b) != NULL))
1483#define THREE_SET_OR_THREE_UNSET(a, b, c) (((a) == NULL && (b) == NULL && (c) == NULL) || ((a) != NULL && (b) != NULL && (c) != NULL))
952cbb56 1484#define THREE_SET(a, b, c) ((a) != NULL && (b) != NULL && (c) != NULL)
ed172985
VJ
1485
1486static void ValidateParserProto(AppProto alproto, uint8_t ipproto)
1487{
1488 uint8_t map = FlowGetProtoMapping(ipproto);
1489 const AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[map][alproto];
ed172985
VJ
1490
1491 if (ctx->Parser[0] == NULL && ctx->Parser[1] == NULL)
1492 return;
1493
1494 if (!(BOTH_SET(ctx->Parser[0], ctx->Parser[1]))) {
1495 goto bad;
1496 }
1497 if (!(BOTH_SET(ctx->StateFree, ctx->StateAlloc))) {
1498 goto bad;
1499 }
952cbb56 1500 if (!(THREE_SET(ctx->StateGetTx, ctx->StateGetTxCnt, ctx->StateTransactionFree))) {
ed172985
VJ
1501 goto bad;
1502 }
efc9a7a3 1503 if (ctx->StateGetProgress == NULL) {
ed172985
VJ
1504 goto bad;
1505 }
1506 /* local storage is optional, but needs both set if used */
1507 if (!(BOTH_SET_OR_BOTH_UNSET(ctx->LocalStorageAlloc, ctx->LocalStorageFree))) {
1508 goto bad;
1509 }
f8865720
VJ
1510 if (ctx->GetTxData == NULL) {
1511 goto bad;
1512 }
ed172985
VJ
1513 return;
1514bad:
1515 ValidateParserProtoDump(alproto, ipproto);
1516 exit(EXIT_FAILURE);
1517}
1518#undef BOTH_SET
1519#undef BOTH_SET_OR_BOTH_UNSET
1520#undef THREE_SET_OR_THREE_UNSET
952cbb56 1521#undef THREE_SET
ed172985
VJ
1522
1523static void ValidateParser(AppProto alproto)
1524{
1525 ValidateParserProto(alproto, IPPROTO_TCP);
1526 ValidateParserProto(alproto, IPPROTO_UDP);
1527}
1528
1529static void ValidateParsers(void)
1530{
1531 AppProto p = 0;
1532 for ( ; p < ALPROTO_MAX; p++) {
1533 ValidateParser(p);
1534 }
1535}
432c3317 1536
429c6388
AS
1537void AppLayerParserRegisterProtocolParsers(void)
1538{
1539 SCEnter();
d9686fae 1540
429c6388
AS
1541 RegisterHTPParsers();
1542 RegisterSSLParsers();
bac69af7 1543 rs_dcerpc_register_parser();
581cb622 1544 rs_dcerpc_udp_register_parser();
c2cb155e 1545 RegisterSMBParsers();
429c6388 1546 RegisterFTPParsers();
429c6388 1547 RegisterSSHParsers();
429c6388 1548 RegisterSMTPParsers();
a0e3e2d7
JI
1549 rs_dns_udp_register_parser();
1550 rs_dns_tcp_register_parser();
5a040995 1551 RegisterModbusParsers();
a3ffebd8 1552 RegisterENIPUDPParsers();
1553 RegisterENIPTCPParsers();
bbaa79b8 1554 RegisterDNP3Parsers();
0d79181d
VJ
1555 RegisterNFSTCPParsers();
1556 RegisterNFSUDPParsers();
efe11dc3 1557 RegisterNTPParsers();
b9cf49e9 1558 RegisterTFTPParsers();
ecdf9f6b 1559 RegisterIKEParsers();
77f0c11c 1560 RegisterKRB5Parsers();
68887458 1561 rs_dhcp_register_parser();
2df840a8 1562 RegisterSNMPParsers();
2e975a04 1563 RegisterSIPParsers();
96dc20ab 1564 RegisterTemplateRustParsers();
1c8943de 1565 RegisterRFBParsers();
c3136007 1566 RegisterMQTTParsers();
c1b92126 1567 RegisterTemplateParsers();
caef8b5b 1568 RegisterRdpParsers();
1422b18a 1569 RegisterHTTP2Parsers();
432c3317 1570
429c6388
AS
1571 /** IMAP */
1572 AppLayerProtoDetectRegisterProtocol(ALPROTO_IMAP, "imap");
1573 if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", "imap")) {
1574 if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_IMAP,
1575 "1|20|capability", 12, 0, STREAM_TOSERVER) < 0)
1576 {
924982e7 1577 SCLogInfo("imap proto registration failure");
429c6388 1578 exit(EXIT_FAILURE);
d9686fae 1579 }
429c6388
AS
1580 } else {
1581 SCLogInfo("Protocol detection and parser disabled for %s protocol.",
1582 "imap");
d9686fae 1583 }
429c6388 1584
ed172985 1585 ValidateParsers();
432c3317
AS
1586 return;
1587}
1588
0d7159b5 1589
3ded7f11 1590/* coccinelle: AppLayerParserStateSetFlag():2,2:APP_LAYER_PARSER_ */
9634e60e 1591void AppLayerParserStateSetFlag(AppLayerParserState *pstate, uint8_t flag)
429c6388
AS
1592{
1593 SCEnter();
9634e60e 1594 pstate->flags |= flag;
429c6388 1595 SCReturn;
0d7159b5
AS
1596}
1597
3ded7f11 1598/* coccinelle: AppLayerParserStateIssetFlag():2,2:APP_LAYER_PARSER_ */
9634e60e 1599int AppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint8_t flag)
0d7159b5 1600{
429c6388 1601 SCEnter();
9634e60e 1602 SCReturnInt(pstate->flags & flag);
0d7159b5
AS
1603}
1604
429c6388 1605
5cdeadb3 1606void AppLayerParserStreamTruncated(uint8_t ipproto, AppProto alproto, void *alstate,
429c6388 1607 uint8_t direction)
d9686fae 1608{
429c6388 1609 SCEnter();
432c3317 1610
429c6388
AS
1611 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].Truncate != NULL)
1612 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].Truncate(alstate, direction);
1613
1614 SCReturn;
7c31a232
AS
1615}
1616
429c6388 1617#ifdef DEBUG
9634e60e 1618void AppLayerParserStatePrintDetails(AppLayerParserState *pstate)
7c31a232 1619{
429c6388 1620 SCEnter();
980934d6 1621
429c6388
AS
1622 if (pstate == NULL)
1623 SCReturn;
7c31a232 1624
9634e60e 1625 AppLayerParserState *p = pstate;
429c6388
AS
1626 SCLogDebug("AppLayerParser parser state information for parser state p(%p). "
1627 "p->inspect_id[0](%"PRIu64"), "
1628 "p->inspect_id[1](%"PRIu64"), "
1629 "p->log_id(%"PRIu64"), "
429c6388
AS
1630 "p->decoder_events(%p).",
1631 pstate, p->inspect_id[0], p->inspect_id[1], p->log_id,
e24eb0f2 1632 p->decoder_events);
7c31a232 1633
429c6388 1634 SCReturn;
7c31a232 1635}
429c6388
AS
1636#endif
1637
429c6388 1638/***** Unittests *****/
7c31a232 1639
c1e485cc
GS
1640#ifdef UNITTESTS
1641
429c6388
AS
1642static AppLayerParserCtx alp_ctx_backup_unittest;
1643
c1e485cc
GS
1644typedef struct TestState_ {
1645 uint8_t test;
429c6388 1646} TestState;
c1e485cc
GS
1647
1648/**
1649 * \brief Test parser function to test the memory deallocation of app layer
1650 * parser of occurence of an error.
1651 */
44d3f264 1652static AppLayerResult TestProtocolParser(Flow *f, void *test_state, AppLayerParserState *pstate,
579cc9f0 1653 const uint8_t *input, uint32_t input_len,
7bc3c3ac 1654 void *local_data, const uint8_t flags)
c1e485cc 1655{
429c6388 1656 SCEnter();
44d3f264 1657 SCReturnStruct(APP_LAYER_ERROR);
c1e485cc
GS
1658}
1659
1660/** \brief Function to allocates the Test protocol state memory
1661 */
547d6c2d 1662static void *TestProtocolStateAlloc(void *orig_state, AppProto proto_orig)
c1e485cc 1663{
429c6388 1664 SCEnter();
25a3a5c6 1665 void *s = SCMalloc(sizeof(TestState));
e176be6f 1666 if (unlikely(s == NULL))
429c6388 1667 goto end;
c1e485cc 1668 memset(s, 0, sizeof(TestState));
429c6388
AS
1669 end:
1670 SCReturnPtr(s, "TestState");
c1e485cc
GS
1671}
1672
1673/** \brief Function to free the Test Protocol state memory
1674 */
1675static void TestProtocolStateFree(void *s)
1676{
25a3a5c6 1677 SCFree(s);
c1e485cc
GS
1678}
1679
a4a4d17a 1680static uint64_t TestGetTxCnt(void *state)
8bc1e120
VJ
1681{
1682 /* single tx */
1683 return 1;
1684}
1685
a4a4d17a
VJ
1686static void TestStateTransactionFree(void *state, uint64_t tx_id)
1687{
1688 /* do nothing */
1689}
1690
1691static void *TestGetTx(void *state, uint64_t tx_id)
1692{
1693 TestState *test_state = (TestState *)state;
1694 return test_state;
1695}
1696
5cdeadb3 1697void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto,
429c6388 1698 void (*RegisterUnittests)(void))
6cb00142 1699{
429c6388
AS
1700 SCEnter();
1701 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
1702 RegisterUnittests = RegisterUnittests;
1703 SCReturn;
6cb00142
AS
1704}
1705
429c6388 1706void AppLayerParserBackupParserTable(void)
6cb00142 1707{
429c6388
AS
1708 SCEnter();
1709 alp_ctx_backup_unittest = alp_ctx;
1710 memset(&alp_ctx, 0, sizeof(alp_ctx));
1711 SCReturn;
1712}
6cb00142 1713
429c6388
AS
1714void AppLayerParserRestoreParserTable(void)
1715{
1716 SCEnter();
1717 alp_ctx = alp_ctx_backup_unittest;
1718 memset(&alp_ctx_backup_unittest, 0, sizeof(alp_ctx_backup_unittest));
1719 SCReturn;
6cb00142
AS
1720}
1721
1722/**
1723 * \test Test the deallocation of app layer parser memory on occurance of
1724 * error in the parsing process.
c1e485cc 1725 */
429c6388 1726static int AppLayerParserTest01(void)
c1e485cc 1727{
429c6388
AS
1728 AppLayerParserBackupParserTable();
1729
262a7300 1730 Flow *f = NULL;
c1e485cc
GS
1731 uint8_t testbuf[] = { 0x11 };
1732 uint32_t testlen = sizeof(testbuf);
1733 TcpSession ssn;
8dbf7a0d 1734 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
c1e485cc 1735
c1e485cc 1736 memset(&ssn, 0, sizeof(ssn));
c1e485cc
GS
1737
1738 /* Register the Test protocol state and parser functions */
429c6388
AS
1739 AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_TEST, STREAM_TOSERVER,
1740 TestProtocolParser);
1741 AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_TEST,
1742 TestProtocolStateAlloc, TestProtocolStateFree);
a4a4d17a
VJ
1743 AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_TEST, TestStateTransactionFree);
1744 AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_TEST, TestGetTx);
1745 AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_TEST, TestGetTxCnt);
c1e485cc 1746
262a7300 1747 f = UTHBuildFlow(AF_INET, "1.2.3.4", "4.3.2.1", 20, 40);
fb311e3d 1748 FAIL_IF_NULL(f);
262a7300 1749 f->protoctx = &ssn;
262a7300
VJ
1750 f->alproto = ALPROTO_TEST;
1751 f->proto = IPPROTO_TCP;
c1e485cc 1752
1eeb9669 1753 StreamTcpInitConfig(true);
6a53ab9c 1754
675fa564
GL
1755 int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_TEST,
1756 STREAM_TOSERVER | STREAM_EOF, testbuf,
1757 testlen);
fb311e3d 1758 FAIL_IF(r != -1);
c1e485cc 1759
fb311e3d 1760 FAIL_IF(!(ssn.flags & STREAMTCP_FLAG_APP_LAYER_DISABLED));
c1e485cc 1761
429c6388 1762 AppLayerParserRestoreParserTable();
1eeb9669 1763 StreamTcpFreeConfig(true);
262a7300 1764 UTHFreeFlow(f);
fb311e3d 1765 PASS;
8cc525c9
PR
1766}
1767
6cb00142
AS
1768/**
1769 * \test Test the deallocation of app layer parser memory on occurance of
1770 * error in the parsing process for UDP.
8cc525c9 1771 */
429c6388 1772static int AppLayerParserTest02(void)
8cc525c9 1773{
429c6388
AS
1774 AppLayerParserBackupParserTable();
1775
262a7300 1776 Flow *f = NULL;
8cc525c9
PR
1777 uint8_t testbuf[] = { 0x11 };
1778 uint32_t testlen = sizeof(testbuf);
8dbf7a0d 1779 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
8cc525c9
PR
1780
1781 /* Register the Test protocol state and parser functions */
429c6388
AS
1782 AppLayerParserRegisterParser(IPPROTO_UDP, ALPROTO_TEST, STREAM_TOSERVER,
1783 TestProtocolParser);
1784 AppLayerParserRegisterStateFuncs(IPPROTO_UDP, ALPROTO_TEST,
1785 TestProtocolStateAlloc, TestProtocolStateFree);
a4a4d17a
VJ
1786 AppLayerParserRegisterTxFreeFunc(IPPROTO_UDP, ALPROTO_TEST, TestStateTransactionFree);
1787 AppLayerParserRegisterGetTx(IPPROTO_UDP, ALPROTO_TEST, TestGetTx);
1788 AppLayerParserRegisterGetTxCnt(IPPROTO_UDP, ALPROTO_TEST, TestGetTxCnt);
8cc525c9 1789
262a7300 1790 f = UTHBuildFlow(AF_INET, "1.2.3.4", "4.3.2.1", 20, 40);
fb311e3d 1791 FAIL_IF_NULL(f);
262a7300
VJ
1792 f->alproto = ALPROTO_TEST;
1793 f->proto = IPPROTO_UDP;
a77b9b36 1794 f->protomap = FlowGetProtoMapping(f->proto);
8cc525c9 1795
1eeb9669 1796 StreamTcpInitConfig(true);
8cc525c9 1797
675fa564
GL
1798 int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_TEST,
1799 STREAM_TOSERVER | STREAM_EOF, testbuf,
1800 testlen);
fb311e3d 1801 FAIL_IF(r != -1);
8cc525c9 1802
429c6388 1803 AppLayerParserRestoreParserTable();
1eeb9669 1804 StreamTcpFreeConfig(true);
262a7300 1805 UTHFreeFlow(f);
fb311e3d 1806 PASS;
c1e485cc
GS
1807}
1808
7c31a232 1809
429c6388 1810void AppLayerParserRegisterUnittests(void)
7c31a232 1811{
429c6388 1812 SCEnter();
9faa4b74 1813
429c6388 1814 int ip;
f5f14880 1815 AppProto alproto;
c23742a0 1816 AppLayerParserProtoCtx *ctx;
9faa4b74 1817
429c6388
AS
1818 for (ip = 0; ip < FLOW_PROTO_DEFAULT; ip++) {
1819 for (alproto = 0; alproto < ALPROTO_MAX; alproto++) {
1820 ctx = &alp_ctx.ctxs[ip][alproto];
1821 if (ctx->RegisterUnittests == NULL)
1822 continue;
1823 ctx->RegisterUnittests();
9faa4b74
VJ
1824 }
1825 }
1826
796dd522
JI
1827 UtRegisterTest("AppLayerParserTest01", AppLayerParserTest01);
1828 UtRegisterTest("AppLayerParserTest02", AppLayerParserTest02);
7c31a232 1829
429c6388 1830 SCReturn;
c1e485cc 1831}
429c6388
AS
1832
1833#endif