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