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