]> git.ipfire.org Git - people/ms/suricata.git/blame - src/app-layer-parser.c
app-layer: make tests tx aware
[people/ms/suricata.git] / src / app-layer-parser.c
CommitLineData
5532af46 1/* Copyright (C) 2007-2013 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"
000ce98c
AS
49#include "app-layer-dcerpc.h"
50#include "app-layer-dcerpc-udp.h"
c2cb155e 51#include "app-layer-smb.h"
000ce98c
AS
52#include "app-layer-htp.h"
53#include "app-layer-ftp.h"
54#include "app-layer-ssl.h"
55#include "app-layer-ssh.h"
576ec7da 56#include "app-layer-smtp.h"
8e01cba8
VJ
57#include "app-layer-dns-udp.h"
58#include "app-layer-dns-tcp.h"
5a040995 59#include "app-layer-modbus.h"
a3ffebd8 60#include "app-layer-enip.h"
bbaa79b8 61#include "app-layer-dnp3.h"
0d79181d
VJ
62#include "app-layer-nfs-tcp.h"
63#include "app-layer-nfs-udp.h"
efe11dc3 64#include "app-layer-ntp.h"
b9cf49e9 65#include "app-layer-tftp.h"
c99b9462 66#include "app-layer-ikev2.h"
77f0c11c 67#include "app-layer-krb5.h"
9210d874 68#include "app-layer-dhcp.h"
c1b92126 69#include "app-layer-template.h"
96dc20ab 70#include "app-layer-template-rust.h"
8e10844f 71
ddde572f 72#include "conf.h"
705471e4 73#include "util-spm.h"
9f78d47c 74
91bc83e5 75#include "util-debug.h"
eea5ab4a 76#include "decode-events.h"
262a7300 77#include "util-unittest-helper.h"
5ba41c78 78#include "util-validate.h"
91bc83e5 79
429c6388 80#include "runmodes.h"
cae8e06c 81
446e68ad 82struct AppLayerParserThreadCtx_ {
429c6388 83 void *alproto_local_storage[FLOW_PROTO_MAX][ALPROTO_MAX];
446e68ad 84};
cae8e06c 85
b74c7330 86
429c6388
AS
87/**
88 * \brief App layer protocol parser context.
89 */
c23742a0 90typedef struct AppLayerParserProtoCtx_
429c6388
AS
91{
92 /* 0 - to_server, 1 - to_client. */
7c8bdfd3 93 AppLayerParserFPtr Parser[2];
66530c61 94 bool logger;
01724f04 95 uint32_t logger_bits; /**< registered loggers for this proto */
429c6388
AS
96
97 void *(*StateAlloc)(void);
98 void (*StateFree)(void *);
99 void (*StateTransactionFree)(void *, uint64_t);
100 void *(*LocalStorageAlloc)(void);
101 void (*LocalStorageFree)(void *);
102
103 void (*Truncate)(void *, uint8_t);
104 FileContainer *(*StateGetFiles)(void *, uint8_t);
105 AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t);
429c6388
AS
106
107 int (*StateGetProgress)(void *alstate, uint8_t direction);
108 uint64_t (*StateGetTxCnt)(void *alstate);
109 void *(*StateGetTx)(void *alstate, uint64_t tx_id);
e96d9c11 110 AppLayerGetTxIteratorFunc StateGetTxIterator;
429c6388
AS
111 int (*StateGetProgressCompletionStatus)(uint8_t direction);
112 int (*StateGetEventInfo)(const char *event_name,
113 int *event_id, AppLayerEventType *event_type);
114
bca0cd71
VJ
115 LoggerId (*StateGetTxLogged)(void *alstate, void *tx);
116 void (*StateSetTxLogged)(void *alstate, void *tx, LoggerId logger);
f3599323 117
1cf02560 118 DetectEngineState *(*GetTxDetectState)(void *tx);
7548944b 119 int (*SetTxDetectState)(void *tx, DetectEngineState *);
1cf02560 120
daeb8fd3
VJ
121 uint64_t (*GetTxDetectFlags)(void *tx, uint8_t dir);
122 void (*SetTxDetectFlags)(void *tx, uint8_t dir, uint64_t);
123
b160c49e
GL
124 /* each app-layer has its own value */
125 uint32_t stream_depth;
126
429c6388
AS
127 /* Indicates the direction the parser is ready to see the data
128 * the first time for a flow. Values accepted -
129 * STREAM_TOSERVER, STREAM_TOCLIENT */
130 uint8_t first_data_dir;
e1022ee5 131
c862bbdc 132 /* Option flags such as supporting gaps or not. */
c8fb9bcb 133 uint32_t option_flags;
1df38c3b 134 /* coccinelle: AppLayerParserProtoCtx:option_flags:APP_LAYER_PARSER_OPT_ */
c8fb9bcb
VJ
135
136 uint32_t internal_flags;
1df38c3b 137 /* coccinelle: AppLayerParserProtoCtx:internal_flags:APP_LAYER_PARSER_INT_ */
c862bbdc 138
429c6388
AS
139#ifdef UNITTESTS
140 void (*RegisterUnittests)(void);
141#endif
c23742a0 142} AppLayerParserProtoCtx;
429c6388
AS
143
144typedef struct AppLayerParserCtx_ {
c23742a0 145 AppLayerParserProtoCtx ctxs[FLOW_PROTO_MAX][ALPROTO_MAX];
429c6388
AS
146} AppLayerParserCtx;
147
446e68ad 148struct AppLayerParserState_ {
26eb49d7 149 /* coccinelle: AppLayerParserState:flags:APP_LAYER_PARSER_ */
429c6388
AS
150 uint8_t flags;
151
152 /* Indicates the current transaction that is being inspected.
153 * We have a var per direction. */
154 uint64_t inspect_id[2];
155 /* Indicates the current transaction being logged. Unlike inspect_id,
156 * we don't need a var per direction since we don't log a transaction
157 * unless we have the entire transaction. */
158 uint64_t log_id;
429c6388 159
5b56d324
VJ
160 uint64_t min_id;
161
429c6388
AS
162 /* Used to store decoder events. */
163 AppLayerDecoderEvents *decoder_events;
446e68ad 164};
e1022ee5 165
37203c98
VJ
166#ifdef UNITTESTS
167void UTHAppLayerParserStateGetIds(void *ptr, uint64_t *i1, uint64_t *i2, uint64_t *log, uint64_t *min)
168{
169 struct AppLayerParserState_ *s = ptr;
170 *i1 = s->inspect_id[0];
171 *i2 = s->inspect_id[1];
172 *log = s->log_id;
173 *min = s->min_id;
174}
175#endif
176
429c6388
AS
177/* Static global version of the parser context.
178 * Post 2.0 let's look at changing this to move it out to app-layer.c. */
179static AppLayerParserCtx alp_ctx;
5a9a23f9 180
5908dd08
GL
181int AppLayerParserProtoIsRegistered(uint8_t ipproto, AppProto alproto)
182{
183 uint8_t ipproto_map = FlowGetProtoMapping(ipproto);
184
185 return (alp_ctx.ctxs[ipproto_map][alproto].StateAlloc != NULL) ? 1 : 0;
186}
187
9634e60e 188AppLayerParserState *AppLayerParserStateAlloc(void)
429c6388
AS
189{
190 SCEnter();
9dc04d9f 191
cd0627cd 192 AppLayerParserState *pstate = (AppLayerParserState *)SCMalloc(sizeof(*pstate));
429c6388
AS
193 if (pstate == NULL)
194 goto end;
195 memset(pstate, 0, sizeof(*pstate));
9dc04d9f 196
429c6388 197 end:
9634e60e 198 SCReturnPtr(pstate, "AppLayerParserState");
9dc04d9f
VJ
199}
200
9634e60e 201void AppLayerParserStateFree(AppLayerParserState *pstate)
429c6388
AS
202{
203 SCEnter();
204
9634e60e 205 if (pstate->decoder_events != NULL)
347c0df9 206 AppLayerDecoderEventsFreeEvents(&pstate->decoder_events);
429c6388 207 SCFree(pstate);
9dc04d9f 208
429c6388 209 SCReturn;
9dc04d9f
VJ
210}
211
429c6388 212int AppLayerParserSetup(void)
c1e485cc 213{
429c6388 214 SCEnter();
429c6388 215 memset(&alp_ctx, 0, sizeof(alp_ctx));
6d562f3b
VJ
216 SCReturnInt(0);
217}
218
219void AppLayerParserPostStreamSetup(void)
220{
221 AppProto alproto = 0;
222 int flow_proto = 0;
223
b160c49e
GL
224 /* lets set a default value for stream_depth */
225 for (flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) {
226 for (alproto = 0; alproto < ALPROTO_MAX; alproto++) {
c8fb9bcb
VJ
227 if (!(alp_ctx.ctxs[flow_proto][alproto].internal_flags &
228 APP_LAYER_PARSER_INT_STREAM_DEPTH_SET)) {
397f5f5f
GL
229 alp_ctx.ctxs[flow_proto][alproto].stream_depth =
230 stream_config.reassembly_depth;
231 }
b160c49e
GL
232 }
233 }
5a9a23f9 234}
5a9a23f9 235
429c6388 236int AppLayerParserDeSetup(void)
d4d18e31 237{
429c6388 238 SCEnter();
d4d18e31 239
7a0dbc6f
JV
240 SMTPParserCleanup();
241
429c6388 242 SCReturnInt(0);
d4d18e31
AS
243}
244
9634e60e 245AppLayerParserThreadCtx *AppLayerParserThreadCtxAlloc(void)
d4d18e31 246{
429c6388 247 SCEnter();
d4d18e31 248
55255889
VJ
249 AppProto alproto = 0;
250 int flow_proto = 0;
72a16459 251 AppLayerParserThreadCtx *tctx;
d4d18e31 252
429c6388
AS
253 tctx = SCMalloc(sizeof(*tctx));
254 if (tctx == NULL)
255 goto end;
256 memset(tctx, 0, sizeof(*tctx));
257
55255889
VJ
258 for (flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) {
259 for (alproto = 0; alproto < ALPROTO_MAX; alproto++) {
260 uint8_t ipproto = FlowGetReverseProtoMapping(flow_proto);
261
262 tctx->alproto_local_storage[flow_proto][alproto] =
263 AppLayerParserGetProtocolParserLocalStorage(ipproto, alproto);
429c6388
AS
264 }
265 }
266
267 end:
268 SCReturnPtr(tctx, "void *");
d4d18e31
AS
269}
270
9634e60e 271void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
c1e485cc 272{
429c6388 273 SCEnter();
9f78d47c 274
55255889
VJ
275 AppProto alproto = 0;
276 int flow_proto = 0;
277
278 for (flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) {
279 for (alproto = 0; alproto < ALPROTO_MAX; alproto++) {
280 uint8_t ipproto = FlowGetReverseProtoMapping(flow_proto);
429c6388 281
55255889
VJ
282 AppLayerParserDestroyProtocolParserLocalStorage(ipproto, alproto,
283 tctx->alproto_local_storage[flow_proto][alproto]);
429c6388 284 }
9f78d47c 285 }
cae8e06c 286
0bac43a1 287 SCFree(tctx);
429c6388 288 SCReturn;
9f78d47c
VJ
289}
290
4683b0e6
VJ
291/** \brief check if a parser is enabled in the config
292 * Returns enabled always if: were running unittests and
293 * when compiled with --enable-afl
294 */
429c6388
AS
295int AppLayerParserConfParserEnabled(const char *ipproto,
296 const char *alproto_name)
c1e485cc 297{
429c6388
AS
298 SCEnter();
299
300 int enabled = 1;
301 char param[100];
302 ConfNode *node;
303 int r;
cae8e06c 304
4683b0e6
VJ
305#ifdef AFLFUZZ_APPLAYER
306 goto enabled;
307#endif
429c6388
AS
308 if (RunmodeIsUnittests())
309 goto enabled;
310
311 r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
312 alproto_name, ".enabled");
313 if (r < 0) {
314 SCLogError(SC_ERR_FATAL, "snprintf failure.");
315 exit(EXIT_FAILURE);
316 } else if (r > (int)sizeof(param)) {
317 SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
318 exit(EXIT_FAILURE);
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) {
327 SCLogError(SC_ERR_FATAL, "snprintf failure.");
328 exit(EXIT_FAILURE);
329 } else if (r > (int)sizeof(param)) {
330 SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
331 exit(EXIT_FAILURE);
332 }
333
334 node = ConfGetNode(param);
335 if (node == NULL) {
336 SCLogDebug("Entry for %s not found.", param);
337 goto enabled;
338 }
9f78d47c 339 }
9f78d47c 340
16e4c92b 341 if (ConfValIsTrue(node->val)) {
429c6388 342 goto enabled;
16e4c92b 343 } else if (ConfValIsFalse(node->val)) {
429c6388
AS
344 goto disabled;
345 } else if (strcasecmp(node->val, "detection-only") == 0) {
ff8dae3b 346 goto disabled;
9f78d47c 347 } else {
429c6388
AS
348 SCLogError(SC_ERR_FATAL, "Invalid value found for %s.", param);
349 exit(EXIT_FAILURE);
9f78d47c 350 }
429c6388
AS
351
352 disabled:
353 enabled = 0;
354 enabled:
355 SCReturnInt(enabled);
9f78d47c
VJ
356}
357
429c6388
AS
358/***** Parser related registration *****/
359
5cdeadb3 360int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto,
429c6388 361 uint8_t direction,
7c8bdfd3 362 AppLayerParserFPtr Parser)
c1e485cc 363{
574bcea0
VJ
364 SCEnter();
365
429c6388
AS
366 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
367 Parser[(direction & STREAM_TOSERVER) ? 0 : 1] = Parser;
9f78d47c 368
574bcea0 369 SCReturnInt(0);
9f78d47c
VJ
370}
371
5cdeadb3 372void AppLayerParserRegisterParserAcceptableDataDirection(uint8_t ipproto, AppProto alproto,
429c6388 373 uint8_t direction)
c13ad8c2 374{
429c6388
AS
375 SCEnter();
376
377 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].first_data_dir |=
378 (direction & (STREAM_TOSERVER | STREAM_TOCLIENT));
379
380 SCReturn;
c13ad8c2
AS
381}
382
c862bbdc 383void AppLayerParserRegisterOptionFlags(uint8_t ipproto, AppProto alproto,
c8fb9bcb 384 uint32_t flags)
c862bbdc
JI
385{
386 SCEnter();
387
c8fb9bcb 388 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].option_flags |= flags;
c862bbdc
JI
389
390 SCReturn;
391}
392
5cdeadb3 393void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto,
429c6388
AS
394 void *(*StateAlloc)(void),
395 void (*StateFree)(void *))
c1e485cc 396{
574bcea0
VJ
397 SCEnter();
398
429c6388
AS
399 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateAlloc =
400 StateAlloc;
401 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateFree =
402 StateFree;
086ba5f4 403
429c6388
AS
404 SCReturn;
405}
086ba5f4 406
5cdeadb3 407void AppLayerParserRegisterLocalStorageFunc(uint8_t ipproto, AppProto alproto,
429c6388
AS
408 void *(*LocalStorageAlloc)(void),
409 void (*LocalStorageFree)(void *))
410{
411 SCEnter();
574bcea0 412
429c6388
AS
413 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].LocalStorageAlloc =
414 LocalStorageAlloc;
415 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].LocalStorageFree =
416 LocalStorageFree;
086ba5f4 417
429c6388
AS
418 SCReturn;
419}
086ba5f4 420
5cdeadb3 421void AppLayerParserRegisterGetFilesFunc(uint8_t ipproto, AppProto alproto,
429c6388
AS
422 FileContainer *(*StateGetFiles)(void *, uint8_t))
423{
424 SCEnter();
086ba5f4 425
429c6388
AS
426 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetFiles =
427 StateGetFiles;
086ba5f4 428
429c6388
AS
429 SCReturn;
430}
086ba5f4 431
5cdeadb3 432void AppLayerParserRegisterGetEventsFunc(uint8_t ipproto, AppProto alproto,
429c6388
AS
433 AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t))
434{
435 SCEnter();
574bcea0 436
429c6388
AS
437 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetEvents =
438 StateGetEvents;
086ba5f4 439
429c6388 440 SCReturn;
086ba5f4
VJ
441}
442
f3599323 443void AppLayerParserRegisterLoggerFuncs(uint8_t ipproto, AppProto alproto,
bca0cd71
VJ
444 LoggerId (*StateGetTxLogged)(void *, void *),
445 void (*StateSetTxLogged)(void *, void *, LoggerId))
f3599323
MK
446{
447 SCEnter();
448
449 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetTxLogged =
450 StateGetTxLogged;
451
452 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateSetTxLogged =
453 StateSetTxLogged;
454
455 SCReturn;
456}
457
01724f04
VJ
458void AppLayerParserRegisterLoggerBits(uint8_t ipproto, AppProto alproto, LoggerId bits)
459{
460 SCEnter();
461
462 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].logger_bits = bits;
463
464 SCReturn;
465}
466
5cdeadb3 467void AppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto)
429c6388
AS
468{
469 SCEnter();
9f78d47c 470
66530c61 471 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].logger = true;
9f78d47c 472
429c6388
AS
473 SCReturn;
474}
9f78d47c 475
5cdeadb3 476void AppLayerParserRegisterTruncateFunc(uint8_t ipproto, AppProto alproto,
429c6388
AS
477 void (*Truncate)(void *, uint8_t))
478{
479 SCEnter();
574bcea0 480
429c6388 481 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].Truncate = Truncate;
574bcea0 482
429c6388
AS
483 SCReturn;
484}
9f78d47c 485
5cdeadb3 486void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto,
429c6388
AS
487 int (*StateGetProgress)(void *alstate, uint8_t direction))
488{
489 SCEnter();
9f78d47c 490
429c6388
AS
491 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
492 StateGetProgress = StateGetProgress;
9f78d47c 493
429c6388 494 SCReturn;
9f78d47c
VJ
495}
496
5cdeadb3 497void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto,
429c6388 498 void (*StateTransactionFree)(void *, uint64_t))
c1e485cc 499{
574bcea0 500 SCEnter();
9f78d47c 501
429c6388
AS
502 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
503 StateTransactionFree = StateTransactionFree;
9f78d47c 504
429c6388
AS
505 SCReturn;
506}
9f78d47c 507
5cdeadb3 508void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto,
429c6388
AS
509 uint64_t (*StateGetTxCnt)(void *alstate))
510{
511 SCEnter();
9f78d47c 512
429c6388
AS
513 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
514 StateGetTxCnt = StateGetTxCnt;
9f78d47c 515
429c6388
AS
516 SCReturn;
517}
9f78d47c 518
5cdeadb3 519void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto,
429c6388
AS
520 void *(StateGetTx)(void *alstate, uint64_t tx_id))
521{
522 SCEnter();
9f78d47c 523
429c6388
AS
524 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
525 StateGetTx = StateGetTx;
9f78d47c 526
429c6388 527 SCReturn;
9f78d47c
VJ
528}
529
e96d9c11
VJ
530void AppLayerParserRegisterGetTxIterator(uint8_t ipproto, AppProto alproto,
531 AppLayerGetTxIteratorFunc Func)
532{
533 SCEnter();
534 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetTxIterator = Func;
535 SCReturn;
536}
537
c4b918b6 538void AppLayerParserRegisterGetStateProgressCompletionStatus(AppProto alproto,
429c6388 539 int (*StateGetProgressCompletionStatus)(uint8_t direction))
c1e485cc 540{
429c6388 541 SCEnter();
f1f7df07 542
c4b918b6 543 alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].
429c6388 544 StateGetProgressCompletionStatus = StateGetProgressCompletionStatus;
f1f7df07 545
429c6388
AS
546 SCReturn;
547}
f1f7df07 548
5cdeadb3 549void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto,
429c6388
AS
550 int (*StateGetEventInfo)(const char *event_name, int *event_id,
551 AppLayerEventType *event_type))
552{
553 SCEnter();
f1f7df07 554
429c6388
AS
555 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
556 StateGetEventInfo = StateGetEventInfo;
d9686fae 557
429c6388
AS
558 SCReturn;
559}
d9686fae 560
1cf02560
VJ
561void AppLayerParserRegisterDetectStateFuncs(uint8_t ipproto, AppProto alproto,
562 DetectEngineState *(*GetTxDetectState)(void *tx),
7548944b 563 int (*SetTxDetectState)(void *tx, DetectEngineState *))
1cf02560
VJ
564{
565 SCEnter();
566
567 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxDetectState = GetTxDetectState;
568 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetTxDetectState = SetTxDetectState;
569
570 SCReturn;
571}
572
daeb8fd3
VJ
573void AppLayerParserRegisterDetectFlagsFuncs(uint8_t ipproto, AppProto alproto,
574 uint64_t(*GetTxDetectFlags)(void *tx, uint8_t dir),
575 void (*SetTxDetectFlags)(void *tx, uint8_t dir, uint64_t))
576{
577 SCEnter();
578
579 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxDetectFlags = GetTxDetectFlags;
580 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetTxDetectFlags = SetTxDetectFlags;
581
582 SCReturn;
583}
584
a0fad6bb
VJ
585void AppLayerParserRegisterMpmIDsFuncs(uint8_t ipproto, AppProto alproto,
586 uint64_t(*GetTxMpmIDs)(void *tx),
587 int (*SetTxMpmIDs)(void *tx, uint64_t))
588{
589 SCEnter();
5f890296
VJ
590 SCLogWarning(SC_WARN_DEPRECATED, "%u/%s: GetTxMpmIDs/SetTxMpmIDs is no longer used",
591 ipproto, AppProtoToString(alproto));
a0fad6bb
VJ
592 SCReturn;
593}
594
429c6388 595/***** Get and transaction functions *****/
d9686fae 596
5cdeadb3 597void *AppLayerParserGetProtocolParserLocalStorage(uint8_t ipproto, AppProto alproto)
429c6388
AS
598{
599 SCEnter();
dc1599e0 600 void * r = NULL;
429c6388
AS
601
602 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
603 LocalStorageAlloc != NULL)
604 {
dc1599e0 605 r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
606 LocalStorageAlloc();
d9686fae
AS
607 }
608
dc1599e0 609 SCReturnPtr(r, "void *");
f1f7df07
VJ
610}
611
5cdeadb3 612void AppLayerParserDestroyProtocolParserLocalStorage(uint8_t ipproto, AppProto alproto,
429c6388 613 void *local_data)
68425453 614{
429c6388 615 SCEnter();
68425453 616
429c6388
AS
617 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
618 LocalStorageFree != NULL)
619 {
620 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
621 LocalStorageFree(local_data);
68425453
EL
622 }
623
429c6388 624 SCReturn;
68425453
EL
625}
626
e96d9c11
VJ
627/** \brief default tx iterator
628 *
629 * Used if the app layer parser doesn't register its own iterator.
630 * Simply walks the tx_id space until it finds a tx. Uses 'state' to
631 * keep track of where it left off.
632 *
633 * \retval txptr or NULL if no more txs in list
634 */
635static AppLayerGetTxIterTuple AppLayerDefaultGetTxIterator(
636 const uint8_t ipproto, const AppProto alproto,
637 void *alstate, uint64_t min_tx_id, uint64_t max_tx_id,
638 AppLayerGetTxIterState *state)
639{
640 uint64_t ustate = *(uint64_t *)state;
641 uint64_t tx_id = MAX(min_tx_id, ustate);
642 for ( ; tx_id < max_tx_id; tx_id++) {
643 void *tx_ptr = AppLayerParserGetTx(ipproto, alproto, alstate, tx_id);
644 if (tx_ptr != NULL) {
645 ustate = tx_id + 1;
646 *state = *(AppLayerGetTxIterState *)&ustate;
647 AppLayerGetTxIterTuple tuple = {
648 .tx_ptr = tx_ptr,
649 .tx_id = tx_id,
650 .has_next = (tx_id + 1 < max_tx_id),
651 };
652 SCLogDebug("tulpe: %p/%"PRIu64"/%s", tuple.tx_ptr, tuple.tx_id,
653 tuple.has_next ? "true" : "false");
654 return tuple;
655 }
656 }
657
658 AppLayerGetTxIterTuple no_tuple = { NULL, 0, false };
659 return no_tuple;
660}
661
662AppLayerGetTxIteratorFunc AppLayerGetTxIterator(const uint8_t ipproto,
663 const AppProto alproto)
664{
665 AppLayerGetTxIteratorFunc Func =
666 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetTxIterator;
667 return Func ? Func : AppLayerDefaultGetTxIterator;
668}
669
f3599323 670void AppLayerParserSetTxLogged(uint8_t ipproto, AppProto alproto,
bca0cd71 671 void *alstate, void *tx, LoggerId logger)
f3599323
MK
672{
673 SCEnter();
674
675 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
676 StateSetTxLogged != NULL) {
677 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
678 StateSetTxLogged(alstate, tx, logger);
679 }
680
681 SCReturn;
682}
683
bca0cd71
VJ
684LoggerId AppLayerParserGetTxLogged(const Flow *f,
685 void *alstate, void *tx)
f3599323
MK
686{
687 SCEnter();
688
bca0cd71 689 LoggerId r = 0;
4459b887
VJ
690 if (alp_ctx.ctxs[f->protomap][f->alproto].StateGetTxLogged != NULL) {
691 r = alp_ctx.ctxs[f->protomap][f->alproto].
bca0cd71 692 StateGetTxLogged(alstate, tx);
f3599323
MK
693 }
694
bca0cd71 695 SCReturnUInt(r);
f3599323
MK
696}
697
9634e60e 698uint64_t AppLayerParserGetTransactionLogId(AppLayerParserState *pstate)
c1e485cc 699{
429c6388 700 SCEnter();
8e10844f 701
0564a8da 702 SCReturnCT((pstate == NULL) ? 0 : pstate->log_id, "uint64_t");
429c6388 703}
8e10844f 704
e9fccfa6 705void AppLayerParserSetTransactionLogId(AppLayerParserState *pstate, uint64_t tx_id)
429c6388
AS
706{
707 SCEnter();
5fc30051 708
0564a8da 709 if (pstate != NULL)
e9fccfa6 710 pstate->log_id = tx_id;
5a9a23f9 711
429c6388 712 SCReturn;
8e10844f
VJ
713}
714
9634e60e 715uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction)
c1e485cc 716{
429c6388 717 SCEnter();
8e10844f 718
0564a8da
VJ
719 if (pstate == NULL)
720 SCReturnCT(0ULL, "uint64_t");
721
9634e60e 722 SCReturnCT(pstate->inspect_id[direction & STREAM_TOSERVER ? 0 : 1], "uint64_t");
429c6388 723}
5fc30051 724
5c01b409 725void AppLayerParserSetTransactionInspectId(const Flow *f, AppLayerParserState *pstate,
af51e0f5
VJ
726 void *alstate, const uint8_t flags,
727 bool tag_txs_as_inspected)
429c6388
AS
728{
729 SCEnter();
59780ca7 730
3fc87595 731 const int direction = (flags & STREAM_TOSERVER) ? 0 : 1;
5c01b409 732 const uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
6946e0be 733 uint64_t idx = AppLayerParserGetTransactionInspectId(pstate, flags);
5c01b409 734 const int state_done_progress = AppLayerParserGetStateProgressCompletionStatus(f->alproto, flags);
af51e0f5
VJ
735 const uint8_t ipproto = f->proto;
736 const AppProto alproto = f->alproto;
8e10844f 737
e96d9c11
VJ
738 AppLayerGetTxIteratorFunc IterFunc = AppLayerGetTxIterator(ipproto, alproto);
739 AppLayerGetTxIterState state;
740 memset(&state, 0, sizeof(state));
741
7a96d18f
VJ
742 SCLogDebug("called: %s, tag_txs_as_inspected %s",direction==0?"toserver":"toclient",
743 tag_txs_as_inspected?"true":"false");
744
745 /* mark all txs as inspected if the applayer progress is
746 * at the 'end state'. */
e96d9c11
VJ
747 while (1) {
748 AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, idx, total_txs, &state);
749 if (ires.tx_ptr == NULL)
750 break;
751
752 void *tx = ires.tx_ptr;
753 idx = ires.tx_id;
754
af51e0f5 755 int state_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx, flags);
e96d9c11
VJ
756 if (state_progress < state_done_progress)
757 break;
758
759 if (tag_txs_as_inspected) {
760 uint64_t detect_flags = AppLayerParserGetTxDetectFlags(ipproto, alproto, tx, flags);
761 if ((detect_flags & APP_LAYER_TX_INSPECTED_FLAG) == 0) {
762 detect_flags |= APP_LAYER_TX_INSPECTED_FLAG;
763 AppLayerParserSetTxDetectFlags(ipproto, alproto, tx, flags, detect_flags);
764 SCLogDebug("%p/%"PRIu64" in-order tx is done for direction %s. Flag %016"PRIx64,
765 tx, idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags);
af51e0f5 766 }
e96d9c11
VJ
767 }
768 if (!ires.has_next)
429c6388 769 break;
0e402311 770 idx++;
8e10844f 771 }
6946e0be 772 pstate->inspect_id[direction] = idx;
7a96d18f 773 SCLogDebug("inspect_id now %"PRIu64, pstate->inspect_id[direction]);
8e10844f 774
7a96d18f
VJ
775 /* if necessary we flag all txs that are complete as 'inspected'
776 * also move inspect_id forward. */
af51e0f5 777 if (tag_txs_as_inspected) {
e96d9c11
VJ
778 /* continue at idx */
779 while (1) {
780 AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, idx, total_txs, &state);
781 if (ires.tx_ptr == NULL)
782 break;
783
784 void *tx = ires.tx_ptr;
785 /* if we got a higher id than the minimum we requested, we
786 * skipped a bunch of 'null-txs'. Lets see if we can up the
787 * inspect tracker */
788 if (ires.tx_id > idx && pstate->inspect_id[direction] == idx) {
789 pstate->inspect_id[direction] = ires.tx_id;
af51e0f5 790 }
e96d9c11
VJ
791 idx = ires.tx_id;
792
793 const int state_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx, flags);
794 if (state_progress < state_done_progress)
795 break;
796
797 uint64_t detect_flags = AppLayerParserGetTxDetectFlags(ipproto, alproto, tx, flags);
798 if ((detect_flags & APP_LAYER_TX_INSPECTED_FLAG) == 0) {
799 detect_flags |= APP_LAYER_TX_INSPECTED_FLAG;
800 AppLayerParserSetTxDetectFlags(ipproto, alproto, tx, flags, detect_flags);
801 SCLogDebug("%p/%"PRIu64" out of order tx is done for direction %s. Flag %016"PRIx64,
802 tx, idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags);
803
804 SCLogDebug("%p/%"PRIu64" out of order tx. Update inspect_id? %"PRIu64,
805 tx, idx, pstate->inspect_id[direction]);
7a96d18f
VJ
806 if (pstate->inspect_id[direction]+1 == idx)
807 pstate->inspect_id[direction] = idx;
808 }
e96d9c11
VJ
809 if (!ires.has_next)
810 break;
0e402311 811 idx++;
af51e0f5
VJ
812 }
813 }
814
429c6388 815 SCReturn;
9faa4b74 816}
9faa4b74 817
9634e60e 818AppLayerDecoderEvents *AppLayerParserGetDecoderEvents(AppLayerParserState *pstate)
c1e485cc 819{
429c6388 820 SCEnter();
9f78d47c 821
9634e60e 822 SCReturnPtr(pstate->decoder_events,
429c6388 823 "AppLayerDecoderEvents *");
70b32f73
VJ
824}
825
9634e60e 826void AppLayerParserSetDecoderEvents(AppLayerParserState *pstate, AppLayerDecoderEvents *devents)
9a6aef45 827{
9634e60e 828 pstate->decoder_events = devents;
9a6aef45
AS
829}
830
5cdeadb3 831AppLayerDecoderEvents *AppLayerParserGetEventsByTx(uint8_t ipproto, AppProto alproto,
429c6388 832 void *alstate, uint64_t tx_id)
869109a6 833{
429c6388 834 SCEnter();
869109a6 835
429c6388 836 AppLayerDecoderEvents *ptr = NULL;
869109a6 837
429c6388
AS
838 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
839 StateGetEvents != NULL)
840 {
841 ptr = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
842 StateGetEvents(alstate, tx_id);
01a35bb6
AS
843 }
844
429c6388 845 SCReturnPtr(ptr, "AppLayerDecoderEvents *");
6cb00142 846}
70b32f73 847
5cdeadb3 848FileContainer *AppLayerParserGetFiles(uint8_t ipproto, AppProto alproto,
429c6388 849 void *alstate, uint8_t direction)
c1e485cc 850{
91bc83e5 851 SCEnter();
8e10844f 852
429c6388 853 FileContainer *ptr = NULL;
45d86ff5 854
429c6388
AS
855 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
856 StateGetFiles != NULL)
857 {
858 ptr = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
859 StateGetFiles(alstate, direction);
3b3dce83 860 }
5ba41c78 861
429c6388 862 SCReturnPtr(ptr, "FileContainer *");
70b32f73 863}
70b32f73 864
c06c595c
VJ
865/**
866 * \brief remove obsolete (inspected and logged) transactions
867 */
7a96d18f 868void AppLayerParserTransactionsCleanup(Flow *f)
c06c595c 869{
e62e4bdc 870 SCEnter();
c06c595c
VJ
871 DEBUG_ASSERT_FLOW_LOCKED(f);
872
3fc87595
VJ
873 AppLayerParserProtoCtx *p = &alp_ctx.ctxs[f->protomap][f->alproto];
874 if (unlikely(p->StateTransactionFree == NULL))
e62e4bdc 875 SCReturn;
c06c595c 876
7a96d18f
VJ
877 const uint8_t ipproto = f->proto;
878 const AppProto alproto = f->alproto;
879 void * const alstate = f->alstate;
880 AppLayerParserState * const alparser = f->alparser;
881
882 if (alstate == NULL || alparser == NULL)
e62e4bdc 883 SCReturn;
7a96d18f
VJ
884
885 const uint64_t min = alparser->min_id;
886 const uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
887 const LoggerId logger_expectation = AppLayerParserProtocolGetLoggerBits(ipproto, alproto);
888 const int tx_end_state_ts = AppLayerParserGetStateProgressCompletionStatus(alproto, STREAM_TOSERVER);
889 const int tx_end_state_tc = AppLayerParserGetStateProgressCompletionStatus(alproto, STREAM_TOCLIENT);
890
e96d9c11
VJ
891 AppLayerGetTxIteratorFunc IterFunc = AppLayerGetTxIterator(ipproto, alproto);
892 AppLayerGetTxIterState state;
893 memset(&state, 0, sizeof(state));
894 uint64_t i = min;
895 uint64_t new_min = min;
e62e4bdc 896 SCLogDebug("start min %"PRIu64, min);
d34e4106 897 bool skipped = false;
e96d9c11
VJ
898
899 while (1) {
900 AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, i, total_txs, &state);
901 if (ires.tx_ptr == NULL)
902 break;
903
904 void *tx = ires.tx_ptr;
0e402311 905 i = ires.tx_id; // actual tx id for the tx the IterFunc returned
e96d9c11 906
7a96d18f 907 SCLogDebug("%p/%"PRIu64" checking", tx, i);
5b56d324 908
7a96d18f
VJ
909 const int tx_progress_tc = AppLayerParserGetStateProgress(ipproto, alproto, tx, STREAM_TOCLIENT);
910 if (tx_progress_tc < tx_end_state_tc) {
911 SCLogDebug("%p/%"PRIu64" skipping: tc parser not done", tx, i);
d34e4106 912 skipped = true;
e96d9c11 913 goto next;
7a96d18f
VJ
914 }
915 const int tx_progress_ts = AppLayerParserGetStateProgress(ipproto, alproto, tx, STREAM_TOSERVER);
916 if (tx_progress_ts < tx_end_state_ts) {
917 SCLogDebug("%p/%"PRIu64" skipping: ts parser not done", tx, i);
d34e4106 918 skipped = true;
e96d9c11 919 goto next;
7a96d18f
VJ
920 }
921 if (f->sgh_toserver != NULL) {
922 uint64_t detect_flags_ts = AppLayerParserGetTxDetectFlags(ipproto, alproto, tx, STREAM_TOSERVER);
923 if (!(detect_flags_ts & APP_LAYER_TX_INSPECTED_FLAG)) {
924 SCLogDebug("%p/%"PRIu64" skipping: TS inspect not done: ts:%"PRIx64,
925 tx, i, detect_flags_ts);
d34e4106 926 skipped = true;
e96d9c11 927 goto next;
7a96d18f
VJ
928 }
929 }
930 if (f->sgh_toclient != NULL) {
931 uint64_t detect_flags_tc = AppLayerParserGetTxDetectFlags(ipproto, alproto, tx, STREAM_TOCLIENT);
932 if (!(detect_flags_tc & APP_LAYER_TX_INSPECTED_FLAG)) {
933 SCLogDebug("%p/%"PRIu64" skipping: TC inspect not done: tc:%"PRIx64,
934 tx, i, detect_flags_tc);
d34e4106 935 skipped = true;
e96d9c11 936 goto next;
7a96d18f
VJ
937 }
938 }
939 if (logger_expectation != 0) {
940 LoggerId tx_logged = AppLayerParserGetTxLogged(f, alstate, tx);
941 if (tx_logged != logger_expectation) {
942 SCLogDebug("%p/%"PRIu64" skipping: logging not done: want:%"PRIx32", have:%"PRIx32,
943 tx, i, logger_expectation, tx_logged);
d34e4106 944 skipped = true;
e96d9c11 945 goto next;
7a96d18f
VJ
946 }
947 }
5b56d324 948
7a96d18f
VJ
949 /* if we are here, the tx can be freed. */
950 p->StateTransactionFree(alstate, i);
951 SCLogDebug("%p/%"PRIu64" freed", tx, i);
e96d9c11 952
d34e4106 953 /* if we didn't skip any tx so far, up the minimum */
0e402311 954 SCLogDebug("skipped? %s i %"PRIu64", new_min %"PRIu64, skipped ? "true" : "false", i, new_min);
d34e4106 955 if (!skipped)
e96d9c11 956 new_min = i + 1;
0e402311 957 SCLogDebug("final i %"PRIu64", new_min %"PRIu64, i, new_min);
e96d9c11
VJ
958
959next:
0e402311
VJ
960 if (!ires.has_next) {
961 /* this was the last tx. See if we skipped any. If not
962 * we removed all and can update the minimum to the max
963 * id. */
964 SCLogDebug("no next: cur tx i %"PRIu64", total %"PRIu64, i, total_txs);
965 if (!skipped) {
966 new_min = total_txs;
967 SCLogDebug("no next: cur tx i %"PRIu64", total %"PRIu64": "
968 "new_min updated to %"PRIu64, i, total_txs, new_min);
969 }
e96d9c11 970 break;
0e402311
VJ
971 }
972 i++;
e96d9c11
VJ
973 }
974
975 /* see if we need to bring all trackers up to date. */
e62e4bdc 976 SCLogDebug("update f->alparser->min_id? %"PRIu64" vs %"PRIu64, new_min, alparser->min_id);
e96d9c11
VJ
977 if (new_min > alparser->min_id) {
978 const uint64_t next_id = new_min;
979 alparser->min_id = next_id;
980 alparser->inspect_id[0] = MAX(alparser->inspect_id[0], next_id);
981 alparser->inspect_id[1] = MAX(alparser->inspect_id[1], next_id);
982 alparser->log_id = MAX(alparser->log_id, next_id);
983 SCLogDebug("updated f->alparser->min_id %"PRIu64, alparser->min_id);
c06c595c 984 }
e62e4bdc 985 SCReturn;
c06c595c
VJ
986}
987
ea571add
VJ
988#define IS_DISRUPTED(flags) \
989 ((flags) & (STREAM_DEPTH|STREAM_GAP))
990
991/**
992 * \brief get the progress value for a tx/protocol
993 *
994 * If the stream is disrupted, we return the 'completion' value.
995 */
5cdeadb3 996int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto,
ea571add 997 void *alstate, uint8_t flags)
d4d18e31 998{
73efb4c7 999 SCEnter();
dc1599e0 1000 int r = 0;
ea571add 1001 if (unlikely(IS_DISRUPTED(flags))) {
c4b918b6 1002 r = alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].
ea571add
VJ
1003 StateGetProgressCompletionStatus(flags);
1004 } else {
1005 r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
1006 StateGetProgress(alstate, flags);
1007 }
dc1599e0 1008 SCReturnInt(r);
d4d18e31 1009}
70b32f73 1010
5c01b409 1011uint64_t AppLayerParserGetTxCnt(const Flow *f, void *alstate)
d4d18e31 1012{
16cfae2f 1013 SCEnter();
dc1599e0 1014 uint64_t r = 0;
5c01b409 1015 r = alp_ctx.ctxs[f->protomap][f->alproto].
dc1599e0 1016 StateGetTxCnt(alstate);
1017 SCReturnCT(r, "uint64_t");
16cfae2f
VJ
1018}
1019
5cdeadb3 1020void *AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
ddde572f 1021{
429c6388 1022 SCEnter();
dc1599e0 1023 void * r = NULL;
1024 r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
1025 StateGetTx(alstate, tx_id);
1026 SCReturnPtr(r, "void *");
ddde572f
AS
1027}
1028
c4b918b6
MK
1029int AppLayerParserGetStateProgressCompletionStatus(AppProto alproto,
1030 uint8_t direction)
6cb00142 1031{
429c6388 1032 SCEnter();
dc1599e0 1033 int r = 0;
c4b918b6 1034 r = alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].
dc1599e0 1035 StateGetProgressCompletionStatus(direction);
1036 SCReturnInt(r);
6cb00142
AS
1037}
1038
5cdeadb3 1039int AppLayerParserGetEventInfo(uint8_t ipproto, AppProto alproto, const char *event_name,
429c6388 1040 int *event_id, AppLayerEventType *event_type)
6f8cfd99 1041{
429c6388
AS
1042 SCEnter();
1043 int ipproto_map = FlowGetProtoMapping(ipproto);
1cbd1cdf
VJ
1044 int r = (alp_ctx.ctxs[ipproto_map][alproto].StateGetEventInfo == NULL) ?
1045 -1 : alp_ctx.ctxs[ipproto_map][alproto].StateGetEventInfo(event_name, event_id, event_type);
1046 SCReturnInt(r);
6f8cfd99
AS
1047}
1048
f5f14880 1049uint8_t AppLayerParserGetFirstDataDir(uint8_t ipproto, AppProto alproto)
432c3317 1050{
429c6388 1051 SCEnter();
dc1599e0 1052 uint8_t r = 0;
1053 r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
1054 first_data_dir;
1055 SCReturnCT(r, "uint8_t");
432c3317 1056}
7c31a232 1057
3148ff34
VJ
1058uint64_t AppLayerParserGetTransactionActive(const Flow *f,
1059 AppLayerParserState *pstate, uint8_t direction)
d9686fae 1060{
429c6388 1061 SCEnter();
d9686fae 1062
429c6388 1063 uint64_t active_id;
d9686fae 1064
9634e60e
VJ
1065 uint64_t log_id = pstate->log_id;
1066 uint64_t inspect_id = pstate->inspect_id[direction & STREAM_TOSERVER ? 0 : 1];
66530c61 1067 if (alp_ctx.ctxs[f->protomap][f->alproto].logger == true) {
429c6388
AS
1068 active_id = (log_id < inspect_id) ? log_id : inspect_id;
1069 } else {
1070 active_id = inspect_id;
d9686fae 1071 }
d9686fae 1072
429c6388 1073 SCReturnCT(active_id, "uint64_t");
d9686fae
AS
1074}
1075
bcfa484b
VJ
1076int AppLayerParserSupportsFiles(uint8_t ipproto, AppProto alproto)
1077{
1078 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetFiles != NULL)
1079 return TRUE;
1080 return FALSE;
1081}
1082
1cf02560
VJ
1083int AppLayerParserSupportsTxDetectState(uint8_t ipproto, AppProto alproto)
1084{
1085 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxDetectState != NULL)
1086 return TRUE;
1087 return FALSE;
1088}
1089
1090DetectEngineState *AppLayerParserGetTxDetectState(uint8_t ipproto, AppProto alproto, void *tx)
1091{
1092 SCEnter();
1093 DetectEngineState *s;
1094 s = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxDetectState(tx);
1095 SCReturnPtr(s, "DetectEngineState");
1096}
1097
3148ff34 1098int AppLayerParserSetTxDetectState(const Flow *f,
7548944b 1099 void *tx, DetectEngineState *s)
1cf02560
VJ
1100{
1101 int r;
1102 SCEnter();
3148ff34 1103 if ((alp_ctx.ctxs[f->protomap][f->alproto].GetTxDetectState(tx) != NULL))
1cf02560 1104 SCReturnInt(-EBUSY);
7548944b 1105 r = alp_ctx.ctxs[f->protomap][f->alproto].SetTxDetectState(tx, s);
1cf02560
VJ
1106 SCReturnInt(r);
1107}
1108
daeb8fd3
VJ
1109uint64_t AppLayerParserGetTxDetectFlags(uint8_t ipproto, AppProto alproto, void *tx, uint8_t dir)
1110{
1111 SCEnter();
1112 uint64_t flags = 0;
1113 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxDetectFlags != NULL) {
1114 flags = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxDetectFlags(tx, dir);
1115 }
1116 SCReturnUInt(flags);
1117}
1118
1119void AppLayerParserSetTxDetectFlags(uint8_t ipproto, AppProto alproto, void *tx, uint8_t dir, uint64_t flags)
1120{
1121 SCEnter();
1122 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetTxDetectFlags != NULL) {
1123 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetTxDetectFlags(tx, dir, flags);
1124 }
1125 SCReturn;
1126}
1127
429c6388
AS
1128/***** General *****/
1129
675fa564 1130int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto,
429c6388 1131 uint8_t flags, uint8_t *input, uint32_t input_len)
d9686fae 1132{
429c6388 1133 SCEnter();
a77b9b36
VJ
1134#ifdef DEBUG_VALIDATION
1135 BUG_ON(f->protomap != FlowGetProtoMapping(f->proto));
1136#endif
cd0627cd 1137 AppLayerParserState *pstate = NULL;
a77b9b36 1138 AppLayerParserProtoCtx *p = &alp_ctx.ctxs[f->protomap][alproto];
429c6388 1139 void *alstate = NULL;
a194dfbd 1140 uint64_t p_tx_cnt = 0;
d9686fae 1141
429c6388
AS
1142 /* we don't have the parser registered for this protocol */
1143 if (p->StateAlloc == NULL)
1144 goto end;
d9686fae 1145
429c6388 1146 if (flags & STREAM_GAP) {
c8fb9bcb 1147 if (!(p->option_flags & APP_LAYER_PARSER_OPT_ACCEPT_GAPS)) {
c862bbdc
JI
1148 SCLogDebug("app-layer parser does not accept gaps");
1149 if (f->alstate != NULL) {
1150 AppLayerParserStreamTruncated(f->proto, alproto, f->alstate,
1151 flags);
1152 }
1153 goto error;
1154 }
d9686fae 1155 }
d9686fae 1156
429c6388
AS
1157 /* Get the parser state (if any) */
1158 pstate = f->alparser;
1159 if (pstate == NULL) {
8527b8e0 1160 f->alparser = pstate = AppLayerParserStateAlloc();
429c6388
AS
1161 if (pstate == NULL)
1162 goto error;
d9686fae
AS
1163 }
1164
429c6388 1165 if (flags & STREAM_EOF)
8527b8e0 1166 AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_EOF);
7c31a232 1167
429c6388
AS
1168 alstate = f->alstate;
1169 if (alstate == NULL) {
1170 f->alstate = alstate = p->StateAlloc();
1171 if (alstate == NULL)
1172 goto error;
1173 SCLogDebug("alloced new app layer state %p (name %s)",
1174 alstate, AppLayerGetProtoName(f->alproto));
1175 } else {
1176 SCLogDebug("using existing app layer state %p (name %s))",
1177 alstate, AppLayerGetProtoName(f->alproto));
6e0d98d9 1178 }
429c6388 1179
a194dfbd 1180 if (AppLayerParserProtocolIsTxAware(f->proto, alproto)) {
5c01b409 1181 p_tx_cnt = AppLayerParserGetTxCnt(f, f->alstate);
a194dfbd
EL
1182 }
1183
429c6388 1184 /* invoke the recursive parser, but only on data. We may get empty msgs on EOF */
cf9ff6ad 1185 if (input_len > 0 || (flags & STREAM_EOF)) {
429c6388
AS
1186 /* invoke the parser */
1187 if (p->Parser[(flags & STREAM_TOSERVER) ? 0 : 1](f, alstate, pstate,
1188 input, input_len,
7bc3c3ac
VJ
1189 alp_tctx->alproto_local_storage[f->protomap][alproto],
1190 flags) < 0)
59327e0f
VJ
1191 {
1192 goto error;
1193 }
6e0d98d9 1194 }
429c6388
AS
1195
1196 /* set the packets to no inspection and reassembly if required */
1197 if (pstate->flags & APP_LAYER_PARSER_NO_INSPECTION) {
1198 AppLayerParserSetEOF(pstate);
1199 FlowSetNoPayloadInspectionFlag(f);
429c6388 1200
c1558f5a
VJ
1201 if (f->proto == IPPROTO_TCP) {
1202 StreamTcpDisableAppLayer(f);
1203
1204 /* Set the no reassembly flag for both the stream in this TcpSession */
1205 if (pstate->flags & APP_LAYER_PARSER_NO_REASSEMBLY) {
1206 /* Used only if it's TCP */
1207 TcpSession *ssn = f->protoctx;
1208 if (ssn != NULL) {
1209 StreamTcpSetSessionNoReassemblyFlag(ssn,
1210 flags & STREAM_TOCLIENT ? 1 : 0);
1211 StreamTcpSetSessionNoReassemblyFlag(ssn,
1212 flags & STREAM_TOSERVER ? 1 : 0);
1213 }
429c6388 1214 }
26eb49d7
EL
1215 /* Set the bypass flag for both the stream in this TcpSession */
1216 if (pstate->flags & APP_LAYER_PARSER_BYPASS_READY) {
1217 /* Used only if it's TCP */
1218 TcpSession *ssn = f->protoctx;
1219 if (ssn != NULL) {
1220 StreamTcpSetSessionBypassFlag(ssn);
1221 }
1222 }
429c6388 1223 }
7f8fb0f0
AS
1224 }
1225
26169ad8 1226 /* In cases like HeartBleed for TLS we need to inspect AppLayer but not Payload */
3543150f 1227 if (!(f->flags & FLOW_NOPAYLOAD_INSPECTION) && pstate->flags & APP_LAYER_PARSER_NO_INSPECTION_PAYLOAD) {
26169ad8 1228 FlowSetNoPayloadInspectionFlag(f);
3543150f
VJ
1229 /* Set the no reassembly flag for both the stream in this TcpSession */
1230 if (f->proto == IPPROTO_TCP) {
1231 /* Used only if it's TCP */
1232 TcpSession *ssn = f->protoctx;
1233 if (ssn != NULL) {
1234 StreamTcpSetDisableRawReassemblyFlag(ssn, 0);
1235 StreamTcpSetDisableRawReassemblyFlag(ssn, 1);
3543150f
VJ
1236 }
1237 }
26169ad8
WM
1238 }
1239
a194dfbd
EL
1240 if (AppLayerParserProtocolIsTxAware(f->proto, alproto)) {
1241 if (likely(tv)) {
5c01b409 1242 uint64_t cur_tx_cnt = AppLayerParserGetTxCnt(f, f->alstate);
a194dfbd
EL
1243 if (cur_tx_cnt > p_tx_cnt) {
1244 AppLayerIncTxCounter(tv, f, cur_tx_cnt - p_tx_cnt);
1245 }
1246 }
1247 }
429c6388
AS
1248
1249 /* stream truncated, inform app layer */
1250 if (flags & STREAM_DEPTH)
1251 AppLayerParserStreamTruncated(f->proto, alproto, alstate, flags);
1252
1253 end:
1254 SCReturnInt(0);
6e0d98d9 1255 error:
a77b9b36
VJ
1256 /* Set the no app layer inspection flag for both
1257 * the stream in this Flow */
c1558f5a
VJ
1258 if (f->proto == IPPROTO_TCP) {
1259 StreamTcpDisableAppLayer(f);
1260 }
a77b9b36 1261 AppLayerParserSetEOF(pstate);
429c6388 1262 SCReturnInt(-1);
7c31a232
AS
1263}
1264
9634e60e 1265void AppLayerParserSetEOF(AppLayerParserState *pstate)
7c31a232 1266{
429c6388 1267 SCEnter();
7c31a232 1268
429c6388
AS
1269 if (pstate == NULL)
1270 goto end;
1271
8527b8e0 1272 AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_EOF);
429c6388
AS
1273
1274 end:
1275 SCReturn;
432c3317
AS
1276}
1277
af51e0f5
VJ
1278/* return true if there are app parser decoder events. These are
1279 * only the ones that are set during protocol detection. */
1280bool AppLayerParserHasDecoderEvents(AppLayerParserState *pstate)
432c3317 1281{
429c6388 1282 SCEnter();
432c3317 1283
af51e0f5
VJ
1284 if (pstate == NULL)
1285 return false;
7c31a232 1286
af51e0f5 1287 const AppLayerDecoderEvents *decoder_events = AppLayerParserGetDecoderEvents(pstate);
429c6388 1288 if (decoder_events && decoder_events->cnt)
af51e0f5 1289 return true;
429c6388
AS
1290
1291 /* if we have reached here, we don't have events */
948dee9a 1292 return false;
d9686fae
AS
1293}
1294
01913f6a
VJ
1295/** \brief simpler way to globally test if a alproto is registered
1296 * and fully enabled in the configuration.
1297 */
1298int AppLayerParserIsTxAware(AppProto alproto)
1299{
1300 return (alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto]
1301 .StateGetProgressCompletionStatus != NULL);
1302}
1303
b2d420be
VJ
1304int AppLayerParserProtocolIsTxAware(uint8_t ipproto, AppProto alproto)
1305{
1306 SCEnter();
1307 int ipproto_map = FlowGetProtoMapping(ipproto);
1308 int r = (alp_ctx.ctxs[ipproto_map][alproto].StateGetTx == NULL) ? 0 : 1;
1309 SCReturnInt(r);
1310}
1311
5cdeadb3 1312int AppLayerParserProtocolIsTxEventAware(uint8_t ipproto, AppProto alproto)
d9686fae 1313{
429c6388
AS
1314 SCEnter();
1315 int ipproto_map = FlowGetProtoMapping(ipproto);
3967bd55 1316 int r = (alp_ctx.ctxs[ipproto_map][alproto].StateGetEvents == NULL) ? 0 : 1;
1cbd1cdf 1317 SCReturnInt(r);
429c6388 1318}
432c3317 1319
5cdeadb3 1320int AppLayerParserProtocolSupportsTxs(uint8_t ipproto, AppProto alproto)
429c6388
AS
1321{
1322 SCEnter();
1323 int ipproto_map = FlowGetProtoMapping(ipproto);
1cbd1cdf
VJ
1324 int r = (alp_ctx.ctxs[ipproto_map][alproto].StateTransactionFree == NULL) ? 0 : 1;
1325 SCReturnInt(r);
432c3317
AS
1326}
1327
078ff0c0
VJ
1328int AppLayerParserProtocolHasLogger(uint8_t ipproto, AppProto alproto)
1329{
1330 SCEnter();
1331 int ipproto_map = FlowGetProtoMapping(ipproto);
66530c61 1332 int r = (alp_ctx.ctxs[ipproto_map][alproto].logger == false) ? 0 : 1;
078ff0c0
VJ
1333 SCReturnInt(r);
1334}
1335
bca0cd71
VJ
1336LoggerId AppLayerParserProtocolGetLoggerBits(uint8_t ipproto, AppProto alproto)
1337{
1338 SCEnter();
1339 const int ipproto_map = FlowGetProtoMapping(ipproto);
1340 LoggerId r = alp_ctx.ctxs[ipproto_map][alproto].logger_bits;
1341 SCReturnUInt(r);
1342}
1343
2d223b69 1344void AppLayerParserTriggerRawStreamReassembly(Flow *f, int direction)
432c3317 1345{
429c6388 1346 SCEnter();
432c3317 1347
2d223b69 1348 SCLogDebug("f %p tcp %p direction %d", f, f ? f->protoctx : NULL, direction);
429c6388 1349 if (f != NULL && f->protoctx != NULL)
2d223b69 1350 StreamTcpReassembleTriggerRawReassembly(f->protoctx, direction);
d9686fae 1351
429c6388 1352 SCReturn;
7c31a232
AS
1353}
1354
b160c49e
GL
1355void AppLayerParserSetStreamDepth(uint8_t ipproto, AppProto alproto, uint32_t stream_depth)
1356{
1357 SCEnter();
1358
1359 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].stream_depth = stream_depth;
c8fb9bcb
VJ
1360 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].internal_flags |=
1361 APP_LAYER_PARSER_INT_STREAM_DEPTH_SET;
b160c49e
GL
1362
1363 SCReturn;
1364}
1365
3148ff34 1366uint32_t AppLayerParserGetStreamDepth(const Flow *f)
b160c49e 1367{
3148ff34 1368 SCReturnInt(alp_ctx.ctxs[f->protomap][f->alproto].stream_depth);
b160c49e
GL
1369}
1370
429c6388
AS
1371/***** Cleanup *****/
1372
3148ff34 1373void AppLayerParserStateCleanup(const Flow *f, void *alstate,
9634e60e 1374 AppLayerParserState *pstate)
7c31a232 1375{
429c6388 1376 SCEnter();
7c31a232 1377
3148ff34 1378 AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[f->protomap][f->alproto];
7c31a232 1379
429c6388
AS
1380 if (ctx->StateFree != NULL && alstate != NULL)
1381 ctx->StateFree(alstate);
7c31a232 1382
429c6388
AS
1383 /* free the app layer parser api state */
1384 if (pstate != NULL)
8527b8e0 1385 AppLayerParserStateFree(pstate);
432c3317 1386
429c6388
AS
1387 SCReturn;
1388}
432c3317 1389
ed172985
VJ
1390static void ValidateParserProtoDump(AppProto alproto, uint8_t ipproto)
1391{
1392 uint8_t map = FlowGetProtoMapping(ipproto);
1393 const AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[map][alproto];
1394 const AppLayerParserProtoCtx *ctx_def = &alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto];
1395 printf("ERROR: incomplete app-layer registration\n");
1396 printf("AppLayer protocol %s ipproto %u\n", AppProtoToString(alproto), ipproto);
c8fb9bcb 1397 printf("- option flags %"PRIx32"\n", ctx->option_flags);
ed172985
VJ
1398 printf("- first_data_dir %"PRIx8"\n", ctx->first_data_dir);
1399 printf("Mandatory:\n");
1400 printf("- Parser[0] %p Parser[1] %p\n", ctx->Parser[0], ctx->Parser[1]);
1401 printf("- StateAlloc %p StateFree %p\n", ctx->StateAlloc, ctx->StateFree);
1402 printf("- StateGetTx %p StateGetTxCnt %p StateTransactionFree %p\n",
1403 ctx->StateGetTx, ctx->StateGetTxCnt, ctx->StateTransactionFree);
1404 printf("- StateGetProgress %p StateGetProgressCompletionStatus %p\n", ctx->StateGetProgress, ctx_def->StateGetProgressCompletionStatus);
e9305131 1405 printf("- GetTxDetectState %p SetTxDetectState %p\n", ctx->GetTxDetectState, ctx->SetTxDetectState);
ed172985
VJ
1406 printf("Optional:\n");
1407 printf("- LocalStorageAlloc %p LocalStorageFree %p\n", ctx->LocalStorageAlloc, ctx->LocalStorageFree);
1408 printf("- StateGetTxLogged %p StateSetTxLogged %p\n", ctx->StateGetTxLogged, ctx->StateSetTxLogged);
c4115196 1409 printf("- StateGetEvents %p StateGetEventInfo %p\n", ctx->StateGetEvents, ctx->StateGetEventInfo);
ed172985
VJ
1410}
1411
1412#define BOTH_SET(a, b) ((a) != NULL && (b) != NULL)
1413#define BOTH_SET_OR_BOTH_UNSET(a, b) (((a) == NULL && (b) == NULL) || ((a) != NULL && (b) != NULL))
1414#define THREE_SET_OR_THREE_UNSET(a, b, c) (((a) == NULL && (b) == NULL && (c) == NULL) || ((a) != NULL && (b) != NULL && (c) != NULL))
1415
1416static void ValidateParserProto(AppProto alproto, uint8_t ipproto)
1417{
1418 uint8_t map = FlowGetProtoMapping(ipproto);
1419 const AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[map][alproto];
1420 const AppLayerParserProtoCtx *ctx_def = &alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto];
1421
1422 if (ctx->Parser[0] == NULL && ctx->Parser[1] == NULL)
1423 return;
1424
1425 if (!(BOTH_SET(ctx->Parser[0], ctx->Parser[1]))) {
1426 goto bad;
1427 }
1428 if (!(BOTH_SET(ctx->StateFree, ctx->StateAlloc))) {
1429 goto bad;
1430 }
1431 if (!(THREE_SET_OR_THREE_UNSET(ctx->StateGetTx, ctx->StateGetTxCnt, ctx->StateTransactionFree))) {
1432 goto bad;
1433 }
1434 /* special case: StateGetProgressCompletionStatus is used from 'default'. */
1435 if (!(BOTH_SET(ctx->StateGetProgress, ctx_def->StateGetProgressCompletionStatus))) {
1436 goto bad;
1437 }
1438 /* local storage is optional, but needs both set if used */
1439 if (!(BOTH_SET_OR_BOTH_UNSET(ctx->LocalStorageAlloc, ctx->LocalStorageFree))) {
1440 goto bad;
1441 }
1442 if (!(BOTH_SET_OR_BOTH_UNSET(ctx->StateGetTxLogged, ctx->StateSetTxLogged))) {
1443 goto bad;
1444 }
e9305131 1445 if (!(BOTH_SET(ctx->GetTxDetectState, ctx->SetTxDetectState))) {
ed172985
VJ
1446 goto bad;
1447 }
1448/* TODO: not yet mandatory to use StateHasTxDetectState
1449 if (!(THREE_SET_OR_THREE_UNSET(ctx->GetTxDetectState, ctx->SetTxDetectState, ctx->StateHasTxDetectState))) {
1450 goto bad;
1451 }
1452*/
1453
1454 return;
1455bad:
1456 ValidateParserProtoDump(alproto, ipproto);
1457 exit(EXIT_FAILURE);
1458}
1459#undef BOTH_SET
1460#undef BOTH_SET_OR_BOTH_UNSET
1461#undef THREE_SET_OR_THREE_UNSET
1462
1463static void ValidateParser(AppProto alproto)
1464{
1465 ValidateParserProto(alproto, IPPROTO_TCP);
1466 ValidateParserProto(alproto, IPPROTO_UDP);
1467}
1468
1469static void ValidateParsers(void)
1470{
1471 AppProto p = 0;
1472 for ( ; p < ALPROTO_MAX; p++) {
1473 ValidateParser(p);
1474 }
1475}
432c3317 1476
429c6388
AS
1477void AppLayerParserRegisterProtocolParsers(void)
1478{
1479 SCEnter();
d9686fae 1480
429c6388
AS
1481 RegisterHTPParsers();
1482 RegisterSSLParsers();
429c6388
AS
1483 RegisterDCERPCParsers();
1484 RegisterDCERPCUDPParsers();
c2cb155e 1485 RegisterSMBParsers();
429c6388 1486 RegisterFTPParsers();
429c6388 1487 RegisterSSHParsers();
429c6388
AS
1488 RegisterSMTPParsers();
1489 RegisterDNSUDPParsers();
1490 RegisterDNSTCPParsers();
5a040995 1491 RegisterModbusParsers();
a3ffebd8 1492 RegisterENIPUDPParsers();
1493 RegisterENIPTCPParsers();
bbaa79b8 1494 RegisterDNP3Parsers();
0d79181d
VJ
1495 RegisterNFSTCPParsers();
1496 RegisterNFSUDPParsers();
efe11dc3 1497 RegisterNTPParsers();
b9cf49e9 1498 RegisterTFTPParsers();
c99b9462 1499 RegisterIKEV2Parsers();
77f0c11c 1500 RegisterKRB5Parsers();
9210d874 1501 RegisterDHCPParsers();
96dc20ab 1502 RegisterTemplateRustParsers();
c1b92126 1503 RegisterTemplateParsers();
432c3317 1504
429c6388
AS
1505 /** IMAP */
1506 AppLayerProtoDetectRegisterProtocol(ALPROTO_IMAP, "imap");
1507 if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", "imap")) {
1508 if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_IMAP,
1509 "1|20|capability", 12, 0, STREAM_TOSERVER) < 0)
1510 {
1511 SCLogInfo("imap proto registration failure\n");
1512 exit(EXIT_FAILURE);
d9686fae 1513 }
429c6388
AS
1514 } else {
1515 SCLogInfo("Protocol detection and parser disabled for %s protocol.",
1516 "imap");
d9686fae 1517 }
429c6388
AS
1518
1519 /** MSN Messenger */
1520 AppLayerProtoDetectRegisterProtocol(ALPROTO_MSN, "msn");
1521 if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", "msn")) {
1522 if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_MSN,
1523 "msn", 10, 6, STREAM_TOSERVER) < 0)
1524 {
1525 SCLogInfo("msn proto registration failure\n");
1526 exit(EXIT_FAILURE);
7c31a232 1527 }
d9686fae 1528 } else {
429c6388
AS
1529 SCLogInfo("Protocol detection and parser disabled for %s protocol.",
1530 "msn");
7c31a232 1531 }
432c3317 1532
ed172985 1533 ValidateParsers();
432c3317
AS
1534 return;
1535}
1536
0d7159b5 1537
9634e60e 1538void AppLayerParserStateSetFlag(AppLayerParserState *pstate, uint8_t flag)
429c6388
AS
1539{
1540 SCEnter();
9634e60e 1541 pstate->flags |= flag;
429c6388 1542 SCReturn;
0d7159b5
AS
1543}
1544
9634e60e 1545int AppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint8_t flag)
0d7159b5 1546{
429c6388 1547 SCEnter();
9634e60e 1548 SCReturnInt(pstate->flags & flag);
0d7159b5
AS
1549}
1550
429c6388 1551
5cdeadb3 1552void AppLayerParserStreamTruncated(uint8_t ipproto, AppProto alproto, void *alstate,
429c6388 1553 uint8_t direction)
d9686fae 1554{
429c6388 1555 SCEnter();
432c3317 1556
429c6388
AS
1557
1558 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].Truncate != NULL)
1559 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].Truncate(alstate, direction);
1560
1561 SCReturn;
7c31a232
AS
1562}
1563
429c6388 1564#ifdef DEBUG
9634e60e 1565void AppLayerParserStatePrintDetails(AppLayerParserState *pstate)
7c31a232 1566{
429c6388 1567 SCEnter();
980934d6 1568
429c6388
AS
1569 if (pstate == NULL)
1570 SCReturn;
7c31a232 1571
9634e60e 1572 AppLayerParserState *p = pstate;
429c6388
AS
1573 SCLogDebug("AppLayerParser parser state information for parser state p(%p). "
1574 "p->inspect_id[0](%"PRIu64"), "
1575 "p->inspect_id[1](%"PRIu64"), "
1576 "p->log_id(%"PRIu64"), "
429c6388
AS
1577 "p->decoder_events(%p).",
1578 pstate, p->inspect_id[0], p->inspect_id[1], p->log_id,
e24eb0f2 1579 p->decoder_events);
7c31a232 1580
429c6388 1581 SCReturn;
7c31a232 1582}
429c6388
AS
1583#endif
1584
077ac816 1585#ifdef AFLFUZZ_APPLAYER
4683b0e6 1586int AppLayerParserRequestFromFile(uint8_t ipproto, AppProto alproto, char *filename)
077ac816 1587{
71c3141e 1588 bool do_dump = (getenv("SC_AFL_DUMP_FILES") != NULL);
31daf435
VJ
1589 struct timeval ts;
1590 memset(&ts, 0, sizeof(ts));
1591 gettimeofday(&ts, NULL);
1592
077ac816
VJ
1593 int result = 1;
1594 Flow *f = NULL;
1595 TcpSession ssn;
1596 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1597
1598 memset(&ssn, 0, sizeof(ssn));
1599
1600 f = SCCalloc(1, sizeof(Flow));
1601 if (f == NULL)
1602 goto end;
1603 FLOW_INITIALIZE(f);
1604
1605 f->flags |= FLOW_IPV4;
1606 f->src.addr_data32[0] = 0x01020304;
1607 f->dst.addr_data32[0] = 0x05060708;
1608 f->sp = 10000;
1609 f->dp = 80;
1610 f->protoctx = &ssn;
4683b0e6
VJ
1611 f->proto = ipproto;
1612 f->protomap = FlowGetProtoMapping(f->proto);
077ac816
VJ
1613 f->alproto = alproto;
1614
31daf435
VJ
1615 uint8_t buffer[65536];
1616 uint32_t cnt = 0;
077ac816 1617
45d87d66
MK
1618#ifdef AFLFUZZ_PERSISTANT_MODE
1619 while (__AFL_LOOP(1000)) {
1620 /* reset state */
1621 memset(buffer, 0, sizeof(buffer));
1622#endif /* AFLFUZZ_PERSISTANT_MODE */
077ac816 1623
45d87d66
MK
1624 FILE *fp = fopen(filename, "r");
1625 BUG_ON(fp == NULL);
077ac816 1626
45d87d66
MK
1627 int start = 1;
1628 while (1) {
1629 int done = 0;
c89ce170
VJ
1630 size_t size = fread(&buffer, 1, sizeof(buffer), fp);
1631 if (size < sizeof(buffer))
45d87d66 1632 done = 1;
077ac816 1633
71c3141e
VJ
1634 if (do_dump) {
1635 char outfilename[256];
1636 snprintf(outfilename, sizeof(outfilename), "dump/%u-%u.%u",
1637 (unsigned int)ts.tv_sec, (unsigned int)ts.tv_usec, cnt);
1638 FILE *out_fp = fopen(outfilename, "w");
1639 BUG_ON(out_fp == NULL);
1640 (void)fwrite(buffer, size, 1, out_fp);
1641 fclose(out_fp);
1642 }
45d87d66 1643 //SCLogInfo("result %u done %d start %d", (uint)result, done, start);
077ac816 1644
45d87d66 1645 uint8_t flags = STREAM_TOSERVER;
45d87d66
MK
1646 if (start--) {
1647 flags |= STREAM_START;
1648 }
1649 if (done) {
1650 flags |= STREAM_EOF;
1651 }
1652 //PrintRawDataFp(stdout, buffer, result);
1653
675fa564 1654 (void)AppLayerParserParse(NULL, alp_tctx, f, alproto, flags,
c89ce170 1655 buffer, size);
31daf435
VJ
1656 cnt++;
1657
45d87d66
MK
1658 if (done)
1659 break;
077ac816 1660 }
077ac816 1661
45d87d66
MK
1662 fclose(fp);
1663
1664#ifdef AFLFUZZ_PERSISTANT_MODE
077ac816 1665 }
45d87d66 1666#endif /* AFLFUZZ_PERSISTANT_MODE */
077ac816 1667
71c3141e
VJ
1668 if (do_dump) {
1669 /* if we get here there was no crash, so we can remove our files */
1670 uint32_t x = 0;
1671 for (x = 0; x < cnt; x++) {
1672 char rmfilename[256];
1673 snprintf(rmfilename, sizeof(rmfilename), "dump/%u-%u.%u",
1674 (unsigned int)ts.tv_sec, (unsigned int)ts.tv_usec, x);
1675 unlink(rmfilename);
1676 }
31daf435
VJ
1677 }
1678
1679 result = 0;
1680
1681end:
1682 if (alp_tctx != NULL)
1683 AppLayerParserThreadCtxFree(alp_tctx);
1684 if (f != NULL) {
1685 FlowFree(f);
1686 }
1687 return result;
1688}
1689
1690/* load a serie of files generated by DecoderParseDataFromFile() in
1691 * the same order as it was produced. */
1692int AppLayerParserRequestFromFileSerie(uint8_t ipproto, AppProto alproto, char *fileprefix)
1693{
1694 uint32_t cnt = 0;
1695 int start = 1;
1696 int result = 1;
1697 Flow *f = NULL;
1698 TcpSession ssn;
1699 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1700
1701 memset(&ssn, 0, sizeof(ssn));
1702
1703 f = SCCalloc(1, sizeof(Flow));
1704 if (f == NULL)
1705 goto end;
1706 FLOW_INITIALIZE(f);
1707
1708 f->flags |= FLOW_IPV4;
1709 f->src.addr_data32[0] = 0x01020304;
1710 f->dst.addr_data32[0] = 0x05060708;
1711 f->sp = 10000;
1712 f->dp = 80;
1713 f->protoctx = &ssn;
1714 f->proto = ipproto;
1715 f->protomap = FlowGetProtoMapping(f->proto);
1716 f->alproto = alproto;
1717
1718 uint8_t buffer[65536];
1719
1720 char filename[256];
1721 snprintf(filename, sizeof(filename), "dump/%s.%u", fileprefix, cnt);
1722 FILE *fp;
1723 while ((fp = fopen(filename, "r")) != NULL)
1724 {
1725 memset(buffer, 0, sizeof(buffer));
1726
1727 size_t size = fread(&buffer, 1, sizeof(buffer), fp);
1728
1729 uint8_t flags = STREAM_TOSERVER;
1730 if (start--) {
1731 flags |= STREAM_START;
1732 }
1733
1734 (void)AppLayerParserParse(NULL, alp_tctx, f, alproto, flags,
1735 buffer, size);
1736
1737 fclose(fp);
1738 cnt++;
1739
1740 snprintf(filename, sizeof(filename), "dump/%s.%u", fileprefix, cnt);
1741 }
1742
077ac816 1743 result = 0;
45d87d66 1744
077ac816
VJ
1745end:
1746 if (alp_tctx != NULL)
1747 AppLayerParserThreadCtxFree(alp_tctx);
1748 if (f != NULL) {
1749 FlowFree(f);
1750 }
1751 return result;
1752}
1753
4683b0e6 1754int AppLayerParserFromFile(uint8_t ipproto, AppProto alproto, char *filename)
077ac816 1755{
71c3141e 1756 bool do_dump = (getenv("SC_AFL_DUMP_FILES") != NULL);
31daf435
VJ
1757 struct timeval ts;
1758 memset(&ts, 0, sizeof(ts));
1759 gettimeofday(&ts, NULL);
1760
077ac816
VJ
1761 int result = 1;
1762 Flow *f = NULL;
1763 TcpSession ssn;
1764 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1765
1766 memset(&ssn, 0, sizeof(ssn));
1767
1768 f = SCCalloc(1, sizeof(Flow));
1769 if (f == NULL)
1770 goto end;
1771 FLOW_INITIALIZE(f);
1772
1773 f->flags |= FLOW_IPV4;
1774 f->src.addr_data32[0] = 0x01020304;
1775 f->dst.addr_data32[0] = 0x05060708;
1776 f->sp = 10000;
1777 f->dp = 80;
1778 f->protoctx = &ssn;
4683b0e6
VJ
1779 f->proto = ipproto;
1780 f->protomap = FlowGetProtoMapping(f->proto);
077ac816
VJ
1781 f->alproto = alproto;
1782
31daf435
VJ
1783 uint8_t buffer[65536];
1784 uint32_t cnt = 0;
077ac816 1785
45d87d66
MK
1786#ifdef AFLFUZZ_PERSISTANT_MODE
1787 while (__AFL_LOOP(1000)) {
1788 /* reset state */
1789 memset(buffer, 0, sizeof(buffer));
1790#endif /* AFLFUZZ_PERSISTANT_MODE */
1791
1792 FILE *fp = fopen(filename, "r");
1793 BUG_ON(fp == NULL);
1794
1795 int start = 1;
1796 int flip = 0;
1797 while (1) {
1798 int done = 0;
c89ce170
VJ
1799 size_t size = fread(&buffer, 1, sizeof(buffer), fp);
1800 if (size < sizeof(buffer))
45d87d66 1801 done = 1;
71c3141e
VJ
1802 if (do_dump) {
1803 char outfilename[256];
1804 snprintf(outfilename, sizeof(outfilename), "dump/%u-%u.%u",
1805 (unsigned int)ts.tv_sec, (unsigned int)ts.tv_usec, cnt);
1806 FILE *out_fp = fopen(outfilename, "w");
1807 BUG_ON(out_fp == NULL);
1808 (void)fwrite(buffer, size, 1, out_fp);
1809 fclose(out_fp);
1810 }
45d87d66
MK
1811 //SCLogInfo("result %u done %d start %d", (uint)result, done, start);
1812
1813 uint8_t flags = 0;
1814 if (flip) {
1815 flags = STREAM_TOCLIENT;
1816 flip = 0;
1817 } else {
1818 flags = STREAM_TOSERVER;
1819 flip = 1;
1820 }
077ac816 1821
45d87d66
MK
1822 if (start--) {
1823 flags |= STREAM_START;
1824 }
1825 if (done) {
1826 flags |= STREAM_EOF;
1827 }
1828 //PrintRawDataFp(stdout, buffer, result);
077ac816 1829
675fa564 1830 (void)AppLayerParserParse(NULL, alp_tctx, f, alproto, flags,
c89ce170 1831 buffer, size);
31daf435
VJ
1832
1833 cnt++;
1834
45d87d66
MK
1835 if (done)
1836 break;
077ac816
VJ
1837 }
1838
45d87d66 1839 fclose(fp);
077ac816 1840
45d87d66 1841#ifdef AFLFUZZ_PERSISTANT_MODE
077ac816 1842 }
45d87d66 1843#endif /* AFLFUZZ_PERSISTANT_MODE */
077ac816 1844
71c3141e
VJ
1845 if (do_dump) {
1846 /* if we get here there was no crash, so we can remove our files */
1847 uint32_t x = 0;
1848 for (x = 0; x < cnt; x++) {
1849 char rmfilename[256];
1850 snprintf(rmfilename, sizeof(rmfilename), "dump/%u-%u.%u",
1851 (unsigned int)ts.tv_sec, (unsigned int)ts.tv_usec, x);
1852 unlink(rmfilename);
1853 }
31daf435
VJ
1854 }
1855
1856 result = 0;
1857end:
1858 if (alp_tctx != NULL)
1859 AppLayerParserThreadCtxFree(alp_tctx);
1860 if (f != NULL) {
1861 FlowFree(f);
1862 }
1863 return result;
1864}
1865
1866/* load a serie of files generated by DecoderParseDataFromFile() in
1867 * the same order as it was produced. */
1868int AppLayerParserFromFileSerie(uint8_t ipproto, AppProto alproto, char *fileprefix)
1869{
1870 uint32_t cnt = 0;
1871 int start = 1;
1872 int result = 1;
1873 Flow *f = NULL;
1874 TcpSession ssn;
1875 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1876
1877 memset(&ssn, 0, sizeof(ssn));
1878
1879 f = SCCalloc(1, sizeof(Flow));
1880 if (f == NULL)
1881 goto end;
1882 FLOW_INITIALIZE(f);
1883
1884 f->flags |= FLOW_IPV4;
1885 f->src.addr_data32[0] = 0x01020304;
1886 f->dst.addr_data32[0] = 0x05060708;
1887 f->sp = 10000;
1888 f->dp = 80;
1889 f->protoctx = &ssn;
1890 f->proto = ipproto;
1891 f->protomap = FlowGetProtoMapping(f->proto);
1892 f->alproto = alproto;
1893
1894 uint8_t buffer[65536];
1895 int flip = 0;
1896 char filename[256];
1897 snprintf(filename, sizeof(filename), "dump/%s.%u", fileprefix, cnt);
1898 FILE *fp;
1899 while ((fp = fopen(filename, "r")) != NULL)
1900 {
1901 memset(buffer, 0, sizeof(buffer));
1902
1903 size_t size = fread(&buffer, 1, sizeof(buffer), fp);
1904
1905 uint8_t flags = 0;
1906 if (flip) {
1907 flags = STREAM_TOCLIENT;
1908 flip = 0;
1909 } else {
1910 flags = STREAM_TOSERVER;
1911 flip = 1;
1912 }
1913
1914 if (start--) {
1915 flags |= STREAM_START;
1916 }
1917
1918 (void)AppLayerParserParse(NULL, alp_tctx, f, alproto, flags,
1919 buffer, size);
1920
1921 fclose(fp);
1922 cnt++;
1923
1924 snprintf(filename, sizeof(filename), "dump/%s.%u", fileprefix, cnt);
1925 }
1926
077ac816 1927 result = 0;
31daf435 1928
077ac816
VJ
1929end:
1930 if (alp_tctx != NULL)
1931 AppLayerParserThreadCtxFree(alp_tctx);
1932 if (f != NULL) {
1933 FlowFree(f);
1934 }
1935 return result;
1936}
31daf435 1937
45d87d66 1938#endif /* AFLFUZZ_APPLAYER */
7c31a232 1939
429c6388 1940/***** Unittests *****/
7c31a232 1941
c1e485cc
GS
1942#ifdef UNITTESTS
1943
429c6388
AS
1944static AppLayerParserCtx alp_ctx_backup_unittest;
1945
c1e485cc
GS
1946typedef struct TestState_ {
1947 uint8_t test;
429c6388 1948} TestState;
c1e485cc
GS
1949
1950/**
1951 * \brief Test parser function to test the memory deallocation of app layer
1952 * parser of occurence of an error.
1953 */
9634e60e 1954static int TestProtocolParser(Flow *f, void *test_state, AppLayerParserState *pstate,
9a6aef45 1955 uint8_t *input, uint32_t input_len,
7bc3c3ac 1956 void *local_data, const uint8_t flags)
c1e485cc 1957{
429c6388
AS
1958 SCEnter();
1959 SCReturnInt(-1);
c1e485cc
GS
1960}
1961
1962/** \brief Function to allocates the Test protocol state memory
1963 */
1964static void *TestProtocolStateAlloc(void)
1965{
429c6388 1966 SCEnter();
25a3a5c6 1967 void *s = SCMalloc(sizeof(TestState));
e176be6f 1968 if (unlikely(s == NULL))
429c6388 1969 goto end;
c1e485cc 1970 memset(s, 0, sizeof(TestState));
429c6388
AS
1971 end:
1972 SCReturnPtr(s, "TestState");
c1e485cc
GS
1973}
1974
1975/** \brief Function to free the Test Protocol state memory
1976 */
1977static void TestProtocolStateFree(void *s)
1978{
25a3a5c6 1979 SCFree(s);
c1e485cc
GS
1980}
1981
8bc1e120
VJ
1982static uint64_t TestProtocolGetTxCnt(void *state)
1983{
1984 /* single tx */
1985 return 1;
1986}
1987
5cdeadb3 1988void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto,
429c6388 1989 void (*RegisterUnittests)(void))
6cb00142 1990{
429c6388
AS
1991 SCEnter();
1992 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
1993 RegisterUnittests = RegisterUnittests;
1994 SCReturn;
6cb00142
AS
1995}
1996
429c6388 1997void AppLayerParserBackupParserTable(void)
6cb00142 1998{
429c6388
AS
1999 SCEnter();
2000 alp_ctx_backup_unittest = alp_ctx;
2001 memset(&alp_ctx, 0, sizeof(alp_ctx));
2002 SCReturn;
2003}
6cb00142 2004
429c6388
AS
2005void AppLayerParserRestoreParserTable(void)
2006{
2007 SCEnter();
2008 alp_ctx = alp_ctx_backup_unittest;
2009 memset(&alp_ctx_backup_unittest, 0, sizeof(alp_ctx_backup_unittest));
2010 SCReturn;
6cb00142
AS
2011}
2012
2013/**
2014 * \test Test the deallocation of app layer parser memory on occurance of
2015 * error in the parsing process.
c1e485cc 2016 */
429c6388 2017static int AppLayerParserTest01(void)
c1e485cc 2018{
429c6388
AS
2019 AppLayerParserBackupParserTable();
2020
9f95ab74 2021 int result = 0;
262a7300 2022 Flow *f = NULL;
c1e485cc
GS
2023 uint8_t testbuf[] = { 0x11 };
2024 uint32_t testlen = sizeof(testbuf);
2025 TcpSession ssn;
8dbf7a0d 2026 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
c1e485cc 2027
c1e485cc 2028 memset(&ssn, 0, sizeof(ssn));
c1e485cc
GS
2029
2030 /* Register the Test protocol state and parser functions */
429c6388
AS
2031 AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_TEST, STREAM_TOSERVER,
2032 TestProtocolParser);
2033 AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_TEST,
2034 TestProtocolStateAlloc, TestProtocolStateFree);
8bc1e120 2035 AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_TEST, TestProtocolGetTxCnt);
c1e485cc 2036
262a7300
VJ
2037 f = UTHBuildFlow(AF_INET, "1.2.3.4", "4.3.2.1", 20, 40);
2038 if (f == NULL)
2039 goto end;
2040 f->protoctx = &ssn;
262a7300
VJ
2041 f->alproto = ALPROTO_TEST;
2042 f->proto = IPPROTO_TCP;
c1e485cc 2043
6a53ab9c 2044 StreamTcpInitConfig(TRUE);
6a53ab9c 2045
6530c3d0 2046 FLOWLOCK_WRLOCK(f);
675fa564
GL
2047 int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_TEST,
2048 STREAM_TOSERVER | STREAM_EOF, testbuf,
2049 testlen);
c1e485cc 2050 if (r != -1) {
9f95ab74 2051 printf("returned %" PRId32 ", expected -1: ", r);
6530c3d0 2052 FLOWLOCK_UNLOCK(f);
c1e485cc
GS
2053 goto end;
2054 }
6530c3d0 2055 FLOWLOCK_UNLOCK(f);
c1e485cc 2056
c1558f5a 2057 if (!(ssn.flags & STREAMTCP_FLAG_APP_LAYER_DISABLED)) {
9f95ab74 2058 printf("flag should have been set, but is not: ");
c1e485cc
GS
2059 goto end;
2060 }
2061
9f95ab74 2062 result = 1;
429c6388
AS
2063 end:
2064 AppLayerParserRestoreParserTable();
8cc525c9 2065 StreamTcpFreeConfig(TRUE);
262a7300
VJ
2066
2067 UTHFreeFlow(f);
8cc525c9
PR
2068 return result;
2069}
2070
6cb00142
AS
2071/**
2072 * \test Test the deallocation of app layer parser memory on occurance of
2073 * error in the parsing process for UDP.
8cc525c9 2074 */
429c6388 2075static int AppLayerParserTest02(void)
8cc525c9 2076{
429c6388
AS
2077 AppLayerParserBackupParserTable();
2078
8cc525c9 2079 int result = 1;
262a7300 2080 Flow *f = NULL;
8cc525c9
PR
2081 uint8_t testbuf[] = { 0x11 };
2082 uint32_t testlen = sizeof(testbuf);
8dbf7a0d 2083 AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
8cc525c9
PR
2084
2085 /* Register the Test protocol state and parser functions */
429c6388
AS
2086 AppLayerParserRegisterParser(IPPROTO_UDP, ALPROTO_TEST, STREAM_TOSERVER,
2087 TestProtocolParser);
2088 AppLayerParserRegisterStateFuncs(IPPROTO_UDP, ALPROTO_TEST,
2089 TestProtocolStateAlloc, TestProtocolStateFree);
8bc1e120 2090 AppLayerParserRegisterGetTxCnt(IPPROTO_UDP, ALPROTO_TEST, TestProtocolGetTxCnt);
8cc525c9 2091
262a7300
VJ
2092 f = UTHBuildFlow(AF_INET, "1.2.3.4", "4.3.2.1", 20, 40);
2093 if (f == NULL)
2094 goto end;
2095 f->alproto = ALPROTO_TEST;
2096 f->proto = IPPROTO_UDP;
a77b9b36 2097 f->protomap = FlowGetProtoMapping(f->proto);
8cc525c9
PR
2098
2099 StreamTcpInitConfig(TRUE);
8cc525c9 2100
6530c3d0 2101 FLOWLOCK_WRLOCK(f);
675fa564
GL
2102 int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_TEST,
2103 STREAM_TOSERVER | STREAM_EOF, testbuf,
2104 testlen);
8cc525c9
PR
2105 if (r != -1) {
2106 printf("returned %" PRId32 ", expected -1: \n", r);
2107 result = 0;
6530c3d0 2108 FLOWLOCK_UNLOCK(f);
8cc525c9
PR
2109 goto end;
2110 }
6530c3d0 2111 FLOWLOCK_UNLOCK(f);
8cc525c9 2112
429c6388
AS
2113 end:
2114 AppLayerParserRestoreParserTable();
6a53ab9c 2115 StreamTcpFreeConfig(TRUE);
262a7300 2116 UTHFreeFlow(f);
c1e485cc
GS
2117 return result;
2118}
2119
7c31a232 2120
429c6388 2121void AppLayerParserRegisterUnittests(void)
7c31a232 2122{
429c6388 2123 SCEnter();
9faa4b74 2124
429c6388 2125 int ip;
f5f14880 2126 AppProto alproto;
c23742a0 2127 AppLayerParserProtoCtx *ctx;
9faa4b74 2128
429c6388
AS
2129 for (ip = 0; ip < FLOW_PROTO_DEFAULT; ip++) {
2130 for (alproto = 0; alproto < ALPROTO_MAX; alproto++) {
2131 ctx = &alp_ctx.ctxs[ip][alproto];
2132 if (ctx->RegisterUnittests == NULL)
2133 continue;
2134 ctx->RegisterUnittests();
9faa4b74
VJ
2135 }
2136 }
2137
796dd522
JI
2138 UtRegisterTest("AppLayerParserTest01", AppLayerParserTest01);
2139 UtRegisterTest("AppLayerParserTest02", AppLayerParserTest02);
7c31a232 2140
429c6388 2141 SCReturn;
c1e485cc 2142}
429c6388
AS
2143
2144#endif