]> git.ipfire.org Git - people/ms/suricata.git/blame - src/app-layer-parser.c
app-layer: Use opaque pointers instead of void
[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 49#include "app-layer-smb.h"
9faa4b74 50#include "app-layer-smb2.h"
000ce98c
AS
51#include "app-layer-dcerpc.h"
52#include "app-layer-dcerpc-udp.h"
53#include "app-layer-htp.h"
54#include "app-layer-ftp.h"
55#include "app-layer-ssl.h"
56#include "app-layer-ssh.h"
576ec7da 57#include "app-layer-smtp.h"
8e01cba8
VJ
58#include "app-layer-dns-udp.h"
59#include "app-layer-dns-tcp.h"
8e10844f 60
ddde572f 61#include "conf.h"
705471e4 62#include "util-spm.h"
9f78d47c 63
91bc83e5 64#include "util-debug.h"
eea5ab4a 65#include "decode-events.h"
262a7300 66#include "util-unittest-helper.h"
5ba41c78 67#include "util-validate.h"
91bc83e5 68
429c6388 69#include "runmodes.h"
cae8e06c 70
72a16459 71typedef struct AppLayerParserThreadCtx_ {
429c6388 72 void *alproto_local_storage[FLOW_PROTO_MAX][ALPROTO_MAX];
72a16459 73} AppLayerParserThreadCtx;
cae8e06c 74
b74c7330 75
429c6388
AS
76/**
77 * \brief App layer protocol parser context.
78 */
c23742a0 79typedef struct AppLayerParserProtoCtx_
429c6388
AS
80{
81 /* 0 - to_server, 1 - to_client. */
82 int (*Parser[2])(Flow *f, void *protocol_state,
9634e60e 83 AppLayerParserState *pstate,
429c6388
AS
84 uint8_t *input, uint32_t input_len,
85 void *local_storage);
86 char logger;
87
88 void *(*StateAlloc)(void);
89 void (*StateFree)(void *);
90 void (*StateTransactionFree)(void *, uint64_t);
91 void *(*LocalStorageAlloc)(void);
92 void (*LocalStorageFree)(void *);
93
94 void (*Truncate)(void *, uint8_t);
95 FileContainer *(*StateGetFiles)(void *, uint8_t);
96 AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t);
97 int (*StateHasEvents)(void *);
98
99 int (*StateGetProgress)(void *alstate, uint8_t direction);
100 uint64_t (*StateGetTxCnt)(void *alstate);
101 void *(*StateGetTx)(void *alstate, uint64_t tx_id);
102 int (*StateGetProgressCompletionStatus)(uint8_t direction);
103 int (*StateGetEventInfo)(const char *event_name,
104 int *event_id, AppLayerEventType *event_type);
105
106 /* Indicates the direction the parser is ready to see the data
107 * the first time for a flow. Values accepted -
108 * STREAM_TOSERVER, STREAM_TOCLIENT */
109 uint8_t first_data_dir;
e1022ee5 110
429c6388
AS
111#ifdef UNITTESTS
112 void (*RegisterUnittests)(void);
113#endif
c23742a0 114} AppLayerParserProtoCtx;
429c6388
AS
115
116typedef struct AppLayerParserCtx_ {
c23742a0 117 AppLayerParserProtoCtx ctxs[FLOW_PROTO_MAX][ALPROTO_MAX];
429c6388
AS
118} AppLayerParserCtx;
119
cd0627cd 120typedef struct AppLayerParserState_ {
429c6388
AS
121 uint8_t flags;
122
123 /* Indicates the current transaction that is being inspected.
124 * We have a var per direction. */
125 uint64_t inspect_id[2];
126 /* Indicates the current transaction being logged. Unlike inspect_id,
127 * we don't need a var per direction since we don't log a transaction
128 * unless we have the entire transaction. */
129 uint64_t log_id;
130 /* State version, incremented for each update. Can wrap around. */
131 uint16_t version;
132
133 /* Used to store decoder events. */
134 AppLayerDecoderEvents *decoder_events;
cd0627cd 135} AppLayerParserState;
e1022ee5 136
429c6388
AS
137/* Static global version of the parser context.
138 * Post 2.0 let's look at changing this to move it out to app-layer.c. */
139static AppLayerParserCtx alp_ctx;
5a9a23f9 140
5cdeadb3 141static void AppLayerParserTransactionsCleanup(uint8_t ipproto, AppProto alproto,
9634e60e 142 void *alstate, AppLayerParserState *parser_state_store)
429c6388 143{
9dc04d9f
VJ
144 SCEnter();
145
429c6388
AS
146 uint64_t inspect = 0, log = 0;
147 uint64_t min;
c23742a0 148 AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto];
429c6388
AS
149
150 if (ctx->StateTransactionFree == NULL)
151 goto end;
9dc04d9f 152
429c6388
AS
153 if (parser_state_store->inspect_id[0] < parser_state_store->inspect_id[1])
154 inspect = parser_state_store->inspect_id[0];
155 else
156 inspect = parser_state_store->inspect_id[1];
157 log = parser_state_store->log_id;
9dc04d9f 158
429c6388
AS
159 if (ctx->logger == TRUE) {
160 min = log < inspect ? log : inspect;
161 if (min > 0)
162 ctx->StateTransactionFree(alstate, min - 1);
9dc04d9f 163 } else {
429c6388
AS
164 if (inspect > 0)
165 ctx->StateTransactionFree(alstate, inspect - 1);
9dc04d9f 166 }
9dc04d9f 167
429c6388
AS
168 end:
169 SCReturn;
170}
e8ad876b 171
9634e60e 172AppLayerParserState *AppLayerParserStateAlloc(void)
429c6388
AS
173{
174 SCEnter();
9dc04d9f 175
cd0627cd 176 AppLayerParserState *pstate = (AppLayerParserState *)SCMalloc(sizeof(*pstate));
429c6388
AS
177 if (pstate == NULL)
178 goto end;
179 memset(pstate, 0, sizeof(*pstate));
9dc04d9f 180
429c6388 181 end:
9634e60e 182 SCReturnPtr(pstate, "AppLayerParserState");
9dc04d9f
VJ
183}
184
9634e60e 185void AppLayerParserStateFree(AppLayerParserState *pstate)
429c6388
AS
186{
187 SCEnter();
188
9634e60e
VJ
189 if (pstate->decoder_events != NULL)
190 AppLayerDecoderEventsFreeEvents(pstate->decoder_events);
429c6388 191 SCFree(pstate);
9dc04d9f 192
429c6388 193 SCReturn;
9dc04d9f
VJ
194}
195
429c6388 196int AppLayerParserSetup(void)
c1e485cc 197{
429c6388 198 SCEnter();
fa079c1d 199
429c6388 200 memset(&alp_ctx, 0, sizeof(alp_ctx));
5a9a23f9 201
429c6388 202 SCReturnInt(0);
5a9a23f9 203}
5a9a23f9 204
429c6388 205int AppLayerParserDeSetup(void)
d4d18e31 206{
429c6388 207 SCEnter();
d4d18e31 208
429c6388 209 SCReturnInt(0);
d4d18e31
AS
210}
211
9634e60e 212AppLayerParserThreadCtx *AppLayerParserThreadCtxAlloc(void)
d4d18e31 213{
429c6388 214 SCEnter();
d4d18e31 215
429c6388
AS
216 AppProto i = 0;
217 int j = 0;
72a16459 218 AppLayerParserThreadCtx *tctx;
d4d18e31 219
429c6388
AS
220 tctx = SCMalloc(sizeof(*tctx));
221 if (tctx == NULL)
222 goto end;
223 memset(tctx, 0, sizeof(*tctx));
224
225 for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
226 for (j = 0; j < ALPROTO_MAX; j++) {
227 tctx->alproto_local_storage[i][j] =
59327e0f 228 AppLayerParserGetProtocolParserLocalStorage(FlowGetReverseProtoMapping(i), j);
429c6388
AS
229 }
230 }
231
232 end:
233 SCReturnPtr(tctx, "void *");
d4d18e31
AS
234}
235
9634e60e 236void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
c1e485cc 237{
429c6388 238 SCEnter();
9f78d47c 239
429c6388
AS
240 AppProto i = 0;
241 int j = 0;
429c6388
AS
242
243 for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
244 for (j = 0; j < ALPROTO_MAX; j++) {
245 AppLayerParserDestroyProtocolParserLocalStorage(FlowGetReverseProtoMapping(i),
246 j,
247 tctx->alproto_local_storage[i][j]);
248 }
9f78d47c 249 }
cae8e06c 250
0bac43a1 251 SCFree(tctx);
429c6388 252 SCReturn;
9f78d47c
VJ
253}
254
429c6388
AS
255int AppLayerParserConfParserEnabled(const char *ipproto,
256 const char *alproto_name)
c1e485cc 257{
429c6388
AS
258 SCEnter();
259
260 int enabled = 1;
261 char param[100];
262 ConfNode *node;
263 int r;
cae8e06c 264
429c6388
AS
265 if (RunmodeIsUnittests())
266 goto enabled;
267
268 r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
269 alproto_name, ".enabled");
270 if (r < 0) {
271 SCLogError(SC_ERR_FATAL, "snprintf failure.");
272 exit(EXIT_FAILURE);
273 } else if (r > (int)sizeof(param)) {
274 SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
275 exit(EXIT_FAILURE);
4914d8d9 276 }
5a9a23f9 277
429c6388
AS
278 node = ConfGetNode(param);
279 if (node == NULL) {
280 SCLogDebug("Entry for %s not found.", param);
281 r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
282 alproto_name, ".", ipproto, ".enabled");
283 if (r < 0) {
284 SCLogError(SC_ERR_FATAL, "snprintf failure.");
285 exit(EXIT_FAILURE);
286 } else if (r > (int)sizeof(param)) {
287 SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
288 exit(EXIT_FAILURE);
289 }
290
291 node = ConfGetNode(param);
292 if (node == NULL) {
293 SCLogDebug("Entry for %s not found.", param);
294 goto enabled;
295 }
9f78d47c 296 }
9f78d47c 297
429c6388
AS
298 if (strcasecmp(node->val, "yes") == 0) {
299 goto enabled;
300 } else if (strcasecmp(node->val, "no") == 0) {
301 goto disabled;
302 } else if (strcasecmp(node->val, "detection-only") == 0) {
303 goto enabled;
9f78d47c 304 } else {
429c6388
AS
305 SCLogError(SC_ERR_FATAL, "Invalid value found for %s.", param);
306 exit(EXIT_FAILURE);
9f78d47c 307 }
429c6388
AS
308
309 disabled:
310 enabled = 0;
311 enabled:
312 SCReturnInt(enabled);
9f78d47c
VJ
313}
314
429c6388
AS
315/***** Parser related registration *****/
316
5cdeadb3 317int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto,
429c6388
AS
318 uint8_t direction,
319 int (*Parser)(Flow *f, void *protocol_state,
9634e60e 320 AppLayerParserState *pstate,
429c6388
AS
321 uint8_t *buf, uint32_t buf_len,
322 void *local_storage))
c1e485cc 323{
574bcea0
VJ
324 SCEnter();
325
429c6388
AS
326 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
327 Parser[(direction & STREAM_TOSERVER) ? 0 : 1] = Parser;
9f78d47c 328
574bcea0 329 SCReturnInt(0);
9f78d47c
VJ
330}
331
5cdeadb3 332void AppLayerParserRegisterParserAcceptableDataDirection(uint8_t ipproto, AppProto alproto,
429c6388 333 uint8_t direction)
c13ad8c2 334{
429c6388
AS
335 SCEnter();
336
337 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].first_data_dir |=
338 (direction & (STREAM_TOSERVER | STREAM_TOCLIENT));
339
340 SCReturn;
c13ad8c2
AS
341}
342
5cdeadb3 343void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto,
429c6388
AS
344 void *(*StateAlloc)(void),
345 void (*StateFree)(void *))
c1e485cc 346{
574bcea0
VJ
347 SCEnter();
348
429c6388
AS
349 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateAlloc =
350 StateAlloc;
351 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateFree =
352 StateFree;
086ba5f4 353
429c6388
AS
354 SCReturn;
355}
086ba5f4 356
5cdeadb3 357void AppLayerParserRegisterLocalStorageFunc(uint8_t ipproto, AppProto alproto,
429c6388
AS
358 void *(*LocalStorageAlloc)(void),
359 void (*LocalStorageFree)(void *))
360{
361 SCEnter();
574bcea0 362
429c6388
AS
363 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].LocalStorageAlloc =
364 LocalStorageAlloc;
365 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].LocalStorageFree =
366 LocalStorageFree;
086ba5f4 367
429c6388
AS
368 SCReturn;
369}
086ba5f4 370
5cdeadb3 371void AppLayerParserRegisterGetFilesFunc(uint8_t ipproto, AppProto alproto,
429c6388
AS
372 FileContainer *(*StateGetFiles)(void *, uint8_t))
373{
374 SCEnter();
086ba5f4 375
429c6388
AS
376 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetFiles =
377 StateGetFiles;
086ba5f4 378
429c6388
AS
379 SCReturn;
380}
086ba5f4 381
5cdeadb3 382void AppLayerParserRegisterGetEventsFunc(uint8_t ipproto, AppProto alproto,
429c6388
AS
383 AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t))
384{
385 SCEnter();
574bcea0 386
429c6388
AS
387 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetEvents =
388 StateGetEvents;
086ba5f4 389
429c6388 390 SCReturn;
086ba5f4
VJ
391}
392
5cdeadb3 393void AppLayerParserRegisterHasEventsFunc(uint8_t ipproto, AppProto alproto,
429c6388 394 int (*StateHasEvents)(void *))
c1e485cc 395{
574bcea0 396 SCEnter();
574bcea0 397
429c6388
AS
398 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateHasEvents =
399 StateHasEvents;
574bcea0 400
429c6388
AS
401 SCReturn;
402}
574bcea0 403
5cdeadb3 404void AppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto)
429c6388
AS
405{
406 SCEnter();
9f78d47c 407
429c6388 408 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].logger = TRUE;
9f78d47c 409
429c6388
AS
410 SCReturn;
411}
9f78d47c 412
5cdeadb3 413void AppLayerParserRegisterTruncateFunc(uint8_t ipproto, AppProto alproto,
429c6388
AS
414 void (*Truncate)(void *, uint8_t))
415{
416 SCEnter();
574bcea0 417
429c6388 418 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].Truncate = Truncate;
574bcea0 419
429c6388
AS
420 SCReturn;
421}
9f78d47c 422
5cdeadb3 423void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto,
429c6388
AS
424 int (*StateGetProgress)(void *alstate, uint8_t direction))
425{
426 SCEnter();
9f78d47c 427
429c6388
AS
428 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
429 StateGetProgress = StateGetProgress;
9f78d47c 430
429c6388 431 SCReturn;
9f78d47c
VJ
432}
433
5cdeadb3 434void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto,
429c6388 435 void (*StateTransactionFree)(void *, uint64_t))
c1e485cc 436{
574bcea0 437 SCEnter();
9f78d47c 438
429c6388
AS
439 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
440 StateTransactionFree = StateTransactionFree;
9f78d47c 441
429c6388
AS
442 SCReturn;
443}
9f78d47c 444
5cdeadb3 445void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto,
429c6388
AS
446 uint64_t (*StateGetTxCnt)(void *alstate))
447{
448 SCEnter();
9f78d47c 449
429c6388
AS
450 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
451 StateGetTxCnt = StateGetTxCnt;
9f78d47c 452
429c6388
AS
453 SCReturn;
454}
9f78d47c 455
5cdeadb3 456void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto,
429c6388
AS
457 void *(StateGetTx)(void *alstate, uint64_t tx_id))
458{
459 SCEnter();
9f78d47c 460
429c6388
AS
461 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
462 StateGetTx = StateGetTx;
9f78d47c 463
429c6388 464 SCReturn;
9f78d47c
VJ
465}
466
5cdeadb3 467void AppLayerParserRegisterGetStateProgressCompletionStatus(uint8_t ipproto,
f5f14880 468 AppProto alproto,
429c6388 469 int (*StateGetProgressCompletionStatus)(uint8_t direction))
c1e485cc 470{
429c6388 471 SCEnter();
f1f7df07 472
429c6388
AS
473 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
474 StateGetProgressCompletionStatus = StateGetProgressCompletionStatus;
f1f7df07 475
429c6388
AS
476 SCReturn;
477}
f1f7df07 478
5cdeadb3 479void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto,
429c6388
AS
480 int (*StateGetEventInfo)(const char *event_name, int *event_id,
481 AppLayerEventType *event_type))
482{
483 SCEnter();
f1f7df07 484
429c6388
AS
485 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
486 StateGetEventInfo = StateGetEventInfo;
d9686fae 487
429c6388
AS
488 SCReturn;
489}
d9686fae 490
429c6388 491/***** Get and transaction functions *****/
d9686fae 492
5cdeadb3 493void *AppLayerParserGetProtocolParserLocalStorage(uint8_t ipproto, AppProto alproto)
429c6388
AS
494{
495 SCEnter();
496
497 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
498 LocalStorageAlloc != NULL)
499 {
500 SCReturnPtr(alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
501 LocalStorageAlloc(), "void *");
d9686fae
AS
502 }
503
429c6388 504 SCReturnPtr(NULL, "void *");
f1f7df07
VJ
505}
506
5cdeadb3 507void AppLayerParserDestroyProtocolParserLocalStorage(uint8_t ipproto, AppProto alproto,
429c6388 508 void *local_data)
68425453 509{
429c6388 510 SCEnter();
68425453 511
429c6388
AS
512 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
513 LocalStorageFree != NULL)
514 {
515 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
516 LocalStorageFree(local_data);
68425453
EL
517 }
518
429c6388 519 SCReturn;
68425453
EL
520}
521
9634e60e 522uint64_t AppLayerParserGetTransactionLogId(AppLayerParserState *pstate)
c1e485cc 523{
429c6388 524 SCEnter();
8e10844f 525
9634e60e 526 SCReturnCT(pstate->log_id, "uint64_t");
429c6388 527}
8e10844f 528
9634e60e 529void AppLayerParserSetTransactionLogId(AppLayerParserState *pstate)
429c6388
AS
530{
531 SCEnter();
5fc30051 532
9634e60e 533 pstate->log_id++;
5a9a23f9 534
429c6388 535 SCReturn;
8e10844f
VJ
536}
537
9634e60e 538uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction)
c1e485cc 539{
429c6388 540 SCEnter();
8e10844f 541
9634e60e 542 SCReturnCT(pstate->inspect_id[direction & STREAM_TOSERVER ? 0 : 1], "uint64_t");
429c6388 543}
5fc30051 544
9634e60e 545void AppLayerParserSetTransactionInspectId(AppLayerParserState *pstate,
5cdeadb3 546 uint8_t ipproto, AppProto alproto, void *alstate,
429c6388
AS
547 uint8_t direction)
548{
549 SCEnter();
59780ca7 550
429c6388
AS
551 uint8_t dir = (direction & STREAM_TOSERVER) ? 0 : 1;
552 uint64_t total_txs = AppLayerParserGetTxCnt(ipproto, alproto, alstate);
553 uint64_t idx = AppLayerParserGetTransactionInspectId(pstate, direction);
554 int state_done_progress = AppLayerParserGetStateProgressCompletionStatus(ipproto, alproto, direction);
555 void *tx;
556 int state_progress;
8e10844f 557
429c6388
AS
558 for (; idx < total_txs; idx++) {
559 tx = AppLayerParserGetTx(ipproto, alproto, alstate, idx);
560 if (tx == NULL)
561 continue;
562 state_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx, direction);
563 if (state_progress >= state_done_progress)
564 continue;
565 else
566 break;
8e10844f 567 }
9634e60e 568 pstate->inspect_id[dir] = idx;
8e10844f 569
429c6388 570 SCReturn;
9faa4b74 571}
9faa4b74 572
9634e60e 573AppLayerDecoderEvents *AppLayerParserGetDecoderEvents(AppLayerParserState *pstate)
c1e485cc 574{
429c6388 575 SCEnter();
9f78d47c 576
9634e60e 577 SCReturnPtr(pstate->decoder_events,
429c6388 578 "AppLayerDecoderEvents *");
70b32f73
VJ
579}
580
9634e60e 581void AppLayerParserSetDecoderEvents(AppLayerParserState *pstate, AppLayerDecoderEvents *devents)
9a6aef45 582{
9634e60e 583 pstate->decoder_events = devents;
9a6aef45
AS
584}
585
5cdeadb3 586AppLayerDecoderEvents *AppLayerParserGetEventsByTx(uint8_t ipproto, AppProto alproto,
429c6388 587 void *alstate, uint64_t tx_id)
869109a6 588{
429c6388 589 SCEnter();
869109a6 590
429c6388 591 AppLayerDecoderEvents *ptr = NULL;
869109a6 592
429c6388
AS
593 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
594 StateGetEvents != NULL)
595 {
596 ptr = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
597 StateGetEvents(alstate, tx_id);
01a35bb6
AS
598 }
599
429c6388 600 SCReturnPtr(ptr, "AppLayerDecoderEvents *");
6cb00142 601}
70b32f73 602
9634e60e 603uint16_t AppLayerParserGetStateVersion(AppLayerParserState *pstate)
c1e485cc
GS
604{
605 SCEnter();
9634e60e 606 SCReturnCT((pstate == NULL) ? 0 : pstate->version, "uint16_t");
9f78d47c
VJ
607}
608
5cdeadb3 609FileContainer *AppLayerParserGetFiles(uint8_t ipproto, AppProto alproto,
429c6388 610 void *alstate, uint8_t direction)
c1e485cc 611{
91bc83e5 612 SCEnter();
8e10844f 613
429c6388 614 FileContainer *ptr = NULL;
45d86ff5 615
429c6388
AS
616 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
617 StateGetFiles != NULL)
618 {
619 ptr = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
620 StateGetFiles(alstate, direction);
3b3dce83 621 }
5ba41c78 622
429c6388 623 SCReturnPtr(ptr, "FileContainer *");
70b32f73 624}
70b32f73 625
5cdeadb3 626int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto,
429c6388 627 void *alstate, uint8_t direction)
d4d18e31 628{
73efb4c7 629 SCEnter();
429c6388
AS
630 SCReturnInt(alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
631 StateGetProgress(alstate, direction));
d4d18e31 632}
70b32f73 633
5cdeadb3 634uint64_t AppLayerParserGetTxCnt(uint8_t ipproto, AppProto alproto, void *alstate)
d4d18e31 635{
16cfae2f 636 SCEnter();
429c6388
AS
637 SCReturnCT(alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
638 StateGetTxCnt(alstate), "uint64_t");
16cfae2f
VJ
639}
640
5cdeadb3 641void *AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
ddde572f 642{
429c6388
AS
643 SCEnter();
644 SCReturnPtr(alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
645 StateGetTx(alstate, tx_id), "void *");
ddde572f
AS
646}
647
5cdeadb3 648int AppLayerParserGetStateProgressCompletionStatus(uint8_t ipproto, AppProto alproto,
429c6388 649 uint8_t direction)
6cb00142 650{
429c6388
AS
651 SCEnter();
652 SCReturnInt(alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
653 StateGetProgressCompletionStatus(direction));
6cb00142 654
6cb00142
AS
655}
656
5cdeadb3 657int AppLayerParserGetEventInfo(uint8_t ipproto, AppProto alproto, const char *event_name,
429c6388 658 int *event_id, AppLayerEventType *event_type)
6f8cfd99 659{
429c6388
AS
660 SCEnter();
661 int ipproto_map = FlowGetProtoMapping(ipproto);
1cbd1cdf
VJ
662 int r = (alp_ctx.ctxs[ipproto_map][alproto].StateGetEventInfo == NULL) ?
663 -1 : alp_ctx.ctxs[ipproto_map][alproto].StateGetEventInfo(event_name, event_id, event_type);
664 SCReturnInt(r);
6f8cfd99
AS
665}
666
f5f14880 667uint8_t AppLayerParserGetFirstDataDir(uint8_t ipproto, AppProto alproto)
432c3317 668{
429c6388
AS
669 SCEnter();
670 SCReturnCT(alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
671 first_data_dir, "uint8_t");
432c3317 672}
7c31a232 673
9634e60e
VJ
674uint64_t AppLayerParserGetTransactionActive(uint8_t ipproto, AppProto alproto,
675 AppLayerParserState *pstate, uint8_t direction)
d9686fae 676{
429c6388 677 SCEnter();
d9686fae 678
429c6388 679 uint64_t active_id;
d9686fae 680
9634e60e
VJ
681 uint64_t log_id = pstate->log_id;
682 uint64_t inspect_id = pstate->inspect_id[direction & STREAM_TOSERVER ? 0 : 1];
429c6388
AS
683 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].logger == TRUE) {
684 active_id = (log_id < inspect_id) ? log_id : inspect_id;
685 } else {
686 active_id = inspect_id;
d9686fae 687 }
d9686fae 688
429c6388 689 SCReturnCT(active_id, "uint64_t");
d9686fae
AS
690}
691
429c6388
AS
692/***** General *****/
693
9634e60e 694int AppLayerParserParse(AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto,
429c6388 695 uint8_t flags, uint8_t *input, uint32_t input_len)
d9686fae 696{
429c6388 697 SCEnter();
d9686fae 698
cd0627cd 699 AppLayerParserState *pstate = NULL;
c23742a0 700 AppLayerParserProtoCtx *p = &alp_ctx.ctxs[FlowGetProtoMapping(f->proto)][alproto];
429c6388
AS
701 TcpSession *ssn = NULL;
702 void *alstate = NULL;
d9686fae 703
429c6388
AS
704 /* we don't have the parser registered for this protocol */
705 if (p->StateAlloc == NULL)
706 goto end;
d9686fae 707
429c6388
AS
708 /* Used only if it's TCP */
709 ssn = f->protoctx;
d9686fae 710
429c6388
AS
711 /* Do this check before calling AppLayerParse */
712 if (flags & STREAM_GAP) {
713 SCLogDebug("stream gap detected (missing packets), "
714 "this is not yet supported.");
d9686fae 715
429c6388
AS
716 if (f->alstate != NULL)
717 AppLayerParserStreamTruncated(f->proto, alproto, f->alstate, flags);
718 goto error;
d9686fae 719 }
d9686fae 720
429c6388
AS
721 /* Get the parser state (if any) */
722 pstate = f->alparser;
723 if (pstate == NULL) {
8527b8e0 724 f->alparser = pstate = AppLayerParserStateAlloc();
429c6388
AS
725 if (pstate == NULL)
726 goto error;
d9686fae 727 }
429c6388
AS
728 pstate->version++;
729 SCLogDebug("app layer parser state version incremented to %"PRIu16,
730 pstate->version);
d9686fae 731
429c6388 732 if (flags & STREAM_EOF)
8527b8e0 733 AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_EOF);
7c31a232 734
429c6388
AS
735 alstate = f->alstate;
736 if (alstate == NULL) {
737 f->alstate = alstate = p->StateAlloc();
738 if (alstate == NULL)
739 goto error;
740 SCLogDebug("alloced new app layer state %p (name %s)",
741 alstate, AppLayerGetProtoName(f->alproto));
742 } else {
743 SCLogDebug("using existing app layer state %p (name %s))",
744 alstate, AppLayerGetProtoName(f->alproto));
6e0d98d9 745 }
429c6388
AS
746
747 /* invoke the recursive parser, but only on data. We may get empty msgs on EOF */
748 if (input_len > 0) {
749 /* invoke the parser */
750 if (p->Parser[(flags & STREAM_TOSERVER) ? 0 : 1](f, alstate, pstate,
751 input, input_len,
752 alp_tctx->alproto_local_storage[FlowGetProtoMapping(f->proto)][alproto]) < 0)
59327e0f
VJ
753 {
754 goto error;
755 }
6e0d98d9 756 }
429c6388
AS
757
758 /* set the packets to no inspection and reassembly if required */
759 if (pstate->flags & APP_LAYER_PARSER_NO_INSPECTION) {
760 AppLayerParserSetEOF(pstate);
761 FlowSetNoPayloadInspectionFlag(f);
762 FlowSetSessionNoApplayerInspectionFlag(f);
763
764 /* Set the no reassembly flag for both the stream in this TcpSession */
765 if (pstate->flags & APP_LAYER_PARSER_NO_REASSEMBLY) {
766 if (ssn != NULL) {
767 StreamTcpSetSessionNoReassemblyFlag(ssn,
768 flags & STREAM_TOCLIENT ? 1 : 0);
769 StreamTcpSetSessionNoReassemblyFlag(ssn,
770 flags & STREAM_TOSERVER ? 1 : 0);
771 }
772 }
7f8fb0f0
AS
773 }
774
429c6388
AS
775 /* next, see if we can get rid of transactions now */
776 AppLayerParserTransactionsCleanup(f->proto, alproto, alstate, pstate);
777
778 /* stream truncated, inform app layer */
779 if (flags & STREAM_DEPTH)
780 AppLayerParserStreamTruncated(f->proto, alproto, alstate, flags);
781
782 end:
783 SCReturnInt(0);
6e0d98d9 784 error:
429c6388
AS
785 if (ssn != NULL) {
786 /* Set the no app layer inspection flag for both
787 * the stream in this Flow */
788 FlowSetSessionNoApplayerInspectionFlag(f);
789 AppLayerParserSetEOF(pstate);
790 }
791 SCReturnInt(-1);
7c31a232
AS
792}
793
9634e60e 794void AppLayerParserSetEOF(AppLayerParserState *pstate)
7c31a232 795{
429c6388 796 SCEnter();
7c31a232 797
429c6388
AS
798 if (pstate == NULL)
799 goto end;
800
8527b8e0 801 AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_EOF);
429c6388
AS
802 /* increase version so we will inspect it one more time
803 * with the EOF flags now set */
9634e60e 804 pstate->version++;
429c6388
AS
805
806 end:
807 SCReturn;
432c3317
AS
808}
809
5cdeadb3 810int AppLayerParserHasDecoderEvents(uint8_t ipproto, AppProto alproto,
9634e60e 811 void *alstate, AppLayerParserState *pstate,
429c6388 812 uint8_t flags)
432c3317 813{
429c6388 814 SCEnter();
432c3317 815
429c6388
AS
816 if (alstate == NULL || pstate == NULL)
817 goto not_present;
7c31a232 818
429c6388
AS
819 AppLayerDecoderEvents *decoder_events;
820 uint64_t tx_id;
821 uint64_t max_id;
822
823 if (AppLayerParserProtocolIsTxEventAware(ipproto, alproto)) {
824 /* fast path if supported by alproto */
825 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateHasEvents != NULL) {
826 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
827 StateHasEvents(alstate) == 1)
828 {
829 goto present;
d9686fae 830 }
429c6388
AS
831 } else {
832 /* check each tx */
833 tx_id = AppLayerParserGetTransactionInspectId(pstate, flags);
834 max_id = AppLayerParserGetTxCnt(ipproto, alproto, alstate);
835 for ( ; tx_id < max_id; tx_id++) {
836 decoder_events = AppLayerParserGetEventsByTx(ipproto, alproto, alstate, tx_id);
837 if (decoder_events && decoder_events->cnt)
838 goto present;
7c31a232 839 }
7c31a232 840 }
7c31a232
AS
841 }
842
429c6388
AS
843 decoder_events = AppLayerParserGetDecoderEvents(pstate);
844 if (decoder_events && decoder_events->cnt)
845 goto present;
846
847 /* if we have reached here, we don't have events */
848 not_present:
849 SCReturnInt(0);
850 present:
851 SCReturnInt(1);
d9686fae
AS
852}
853
5cdeadb3 854int AppLayerParserProtocolIsTxEventAware(uint8_t ipproto, AppProto alproto)
d9686fae 855{
429c6388
AS
856 SCEnter();
857 int ipproto_map = FlowGetProtoMapping(ipproto);
1cbd1cdf
VJ
858 int r = (alp_ctx.ctxs[ipproto_map][alproto].StateHasEvents == NULL) ? 0 : 1;
859 SCReturnInt(r);
429c6388 860}
432c3317 861
5cdeadb3 862int AppLayerParserProtocolSupportsTxs(uint8_t ipproto, AppProto alproto)
429c6388
AS
863{
864 SCEnter();
865 int ipproto_map = FlowGetProtoMapping(ipproto);
1cbd1cdf
VJ
866 int r = (alp_ctx.ctxs[ipproto_map][alproto].StateTransactionFree == NULL) ? 0 : 1;
867 SCReturnInt(r);
432c3317
AS
868}
869
429c6388 870void AppLayerParserTriggerRawStreamReassembly(Flow *f)
432c3317 871{
429c6388 872 SCEnter();
432c3317 873
429c6388
AS
874 if (f != NULL && f->protoctx != NULL)
875 StreamTcpReassembleTriggerRawReassembly(f->protoctx);
d9686fae 876
429c6388 877 SCReturn;
7c31a232
AS
878}
879
429c6388
AS
880/***** Cleanup *****/
881
9634e60e
VJ
882void AppLayerParserStateCleanup(uint8_t ipproto, AppProto alproto, void *alstate,
883 AppLayerParserState *pstate)
7c31a232 884{
429c6388 885 SCEnter();
7c31a232 886
c23742a0 887 AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto];
7c31a232 888
429c6388
AS
889 if (ctx->StateFree != NULL && alstate != NULL)
890 ctx->StateFree(alstate);
7c31a232 891
429c6388
AS
892 /* free the app layer parser api state */
893 if (pstate != NULL)
8527b8e0 894 AppLayerParserStateFree(pstate);
432c3317 895
429c6388
AS
896 SCReturn;
897}
432c3317 898
432c3317 899
429c6388
AS
900void AppLayerParserRegisterProtocolParsers(void)
901{
902 SCEnter();
d9686fae 903
429c6388
AS
904 RegisterHTPParsers();
905 RegisterSSLParsers();
906 RegisterSMBParsers();
907 /** \todo bug 719 */
908 //RegisterSMB2Parsers();
909 RegisterDCERPCParsers();
910 RegisterDCERPCUDPParsers();
911 RegisterFTPParsers();
912 /* we are disabling the ssh parser temporarily, since we are moving away
913 * from some of the archaic features we use in the app layer. We will
914 * reintroduce this parser. Also do note that keywords that rely on
915 * the ssh parser would now be disabled */
916#if 0
917 RegisterSSHParsers();
918#endif
919 RegisterSMTPParsers();
920 RegisterDNSUDPParsers();
921 RegisterDNSTCPParsers();
432c3317 922
429c6388
AS
923 /** IMAP */
924 AppLayerProtoDetectRegisterProtocol(ALPROTO_IMAP, "imap");
925 if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", "imap")) {
926 if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_IMAP,
927 "1|20|capability", 12, 0, STREAM_TOSERVER) < 0)
928 {
929 SCLogInfo("imap proto registration failure\n");
930 exit(EXIT_FAILURE);
d9686fae 931 }
429c6388
AS
932 } else {
933 SCLogInfo("Protocol detection and parser disabled for %s protocol.",
934 "imap");
d9686fae 935 }
429c6388
AS
936
937 /** MSN Messenger */
938 AppLayerProtoDetectRegisterProtocol(ALPROTO_MSN, "msn");
939 if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", "msn")) {
940 if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_MSN,
941 "msn", 10, 6, STREAM_TOSERVER) < 0)
942 {
943 SCLogInfo("msn proto registration failure\n");
944 exit(EXIT_FAILURE);
7c31a232 945 }
d9686fae 946 } else {
429c6388
AS
947 SCLogInfo("Protocol detection and parser disabled for %s protocol.",
948 "msn");
7c31a232 949 }
432c3317 950
432c3317
AS
951 return;
952}
953
0d7159b5 954
9634e60e 955void AppLayerParserStateSetFlag(AppLayerParserState *pstate, uint8_t flag)
429c6388
AS
956{
957 SCEnter();
9634e60e 958 pstate->flags |= flag;
429c6388 959 SCReturn;
0d7159b5
AS
960}
961
9634e60e 962int AppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint8_t flag)
0d7159b5 963{
429c6388 964 SCEnter();
9634e60e 965 SCReturnInt(pstate->flags & flag);
0d7159b5
AS
966}
967
429c6388 968
5cdeadb3 969void AppLayerParserStreamTruncated(uint8_t ipproto, AppProto alproto, void *alstate,
429c6388 970 uint8_t direction)
d9686fae 971{
429c6388 972 SCEnter();
432c3317 973
429c6388
AS
974
975 if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].Truncate != NULL)
976 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].Truncate(alstate, direction);
977
978 SCReturn;
7c31a232
AS
979}
980
429c6388 981#ifdef DEBUG
9634e60e 982void AppLayerParserStatePrintDetails(AppLayerParserState *pstate)
7c31a232 983{
429c6388 984 SCEnter();
980934d6 985
429c6388
AS
986 if (pstate == NULL)
987 SCReturn;
7c31a232 988
9634e60e 989 AppLayerParserState *p = pstate;
429c6388
AS
990 SCLogDebug("AppLayerParser parser state information for parser state p(%p). "
991 "p->inspect_id[0](%"PRIu64"), "
992 "p->inspect_id[1](%"PRIu64"), "
993 "p->log_id(%"PRIu64"), "
994 "p->version(%"PRIu16"), "
995 "p->decoder_events(%p).",
996 pstate, p->inspect_id[0], p->inspect_id[1], p->log_id,
997 p->version, p->decoder_events);
7c31a232 998
429c6388 999 SCReturn;
7c31a232 1000}
429c6388
AS
1001#endif
1002
7c31a232 1003
429c6388 1004/***** Unittests *****/
7c31a232 1005
c1e485cc
GS
1006#ifdef UNITTESTS
1007
429c6388
AS
1008static AppLayerParserCtx alp_ctx_backup_unittest;
1009
c1e485cc
GS
1010typedef struct TestState_ {
1011 uint8_t test;
429c6388 1012} TestState;
c1e485cc
GS
1013
1014/**
1015 * \brief Test parser function to test the memory deallocation of app layer
1016 * parser of occurence of an error.
1017 */
9634e60e 1018static int TestProtocolParser(Flow *f, void *test_state, AppLayerParserState *pstate,
9a6aef45 1019 uint8_t *input, uint32_t input_len,
429c6388 1020 void *local_data)
c1e485cc 1021{
429c6388
AS
1022 SCEnter();
1023 SCReturnInt(-1);
c1e485cc
GS
1024}
1025
1026/** \brief Function to allocates the Test protocol state memory
1027 */
1028static void *TestProtocolStateAlloc(void)
1029{
429c6388 1030 SCEnter();
25a3a5c6 1031 void *s = SCMalloc(sizeof(TestState));
e176be6f 1032 if (unlikely(s == NULL))
429c6388 1033 goto end;
c1e485cc 1034 memset(s, 0, sizeof(TestState));
429c6388
AS
1035 end:
1036 SCReturnPtr(s, "TestState");
c1e485cc
GS
1037}
1038
1039/** \brief Function to free the Test Protocol state memory
1040 */
1041static void TestProtocolStateFree(void *s)
1042{
25a3a5c6 1043 SCFree(s);
c1e485cc
GS
1044}
1045
5cdeadb3 1046void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto,
429c6388 1047 void (*RegisterUnittests)(void))
6cb00142 1048{
429c6388
AS
1049 SCEnter();
1050 alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
1051 RegisterUnittests = RegisterUnittests;
1052 SCReturn;
6cb00142
AS
1053}
1054
429c6388 1055void AppLayerParserBackupParserTable(void)
6cb00142 1056{
429c6388
AS
1057 SCEnter();
1058 alp_ctx_backup_unittest = alp_ctx;
1059 memset(&alp_ctx, 0, sizeof(alp_ctx));
1060 SCReturn;
1061}
6cb00142 1062
429c6388
AS
1063void AppLayerParserRestoreParserTable(void)
1064{
1065 SCEnter();
1066 alp_ctx = alp_ctx_backup_unittest;
1067 memset(&alp_ctx_backup_unittest, 0, sizeof(alp_ctx_backup_unittest));
1068 SCReturn;
6cb00142
AS
1069}
1070
1071/**
1072 * \test Test the deallocation of app layer parser memory on occurance of
1073 * error in the parsing process.
c1e485cc 1074 */
429c6388 1075static int AppLayerParserTest01(void)
c1e485cc 1076{
429c6388
AS
1077 AppLayerParserBackupParserTable();
1078
9f95ab74 1079 int result = 0;
262a7300 1080 Flow *f = NULL;
c1e485cc
GS
1081 uint8_t testbuf[] = { 0x11 };
1082 uint32_t testlen = sizeof(testbuf);
1083 TcpSession ssn;
fdefb65b 1084 void *alp_tctx = AppLayerParserThreadCtxAlloc();
c1e485cc 1085
c1e485cc 1086 memset(&ssn, 0, sizeof(ssn));
c1e485cc
GS
1087
1088 /* Register the Test protocol state and parser functions */
429c6388
AS
1089 AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_TEST, STREAM_TOSERVER,
1090 TestProtocolParser);
1091 AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_TEST,
1092 TestProtocolStateAlloc, TestProtocolStateFree);
c1e485cc 1093
262a7300
VJ
1094 f = UTHBuildFlow(AF_INET, "1.2.3.4", "4.3.2.1", 20, 40);
1095 if (f == NULL)
1096 goto end;
1097 f->protoctx = &ssn;
262a7300
VJ
1098 f->alproto = ALPROTO_TEST;
1099 f->proto = IPPROTO_TCP;
c1e485cc 1100
6a53ab9c 1101 StreamTcpInitConfig(TRUE);
6a53ab9c 1102
cd3e32ce 1103 SCMutexLock(&f->m);
429c6388
AS
1104 int r = AppLayerParserParse(alp_tctx, f, ALPROTO_TEST, STREAM_TOSERVER|STREAM_EOF,
1105 testbuf, testlen);
c1e485cc 1106 if (r != -1) {
9f95ab74 1107 printf("returned %" PRId32 ", expected -1: ", r);
cd3e32ce 1108 SCMutexUnlock(&f->m);
c1e485cc
GS
1109 goto end;
1110 }
cd3e32ce 1111 SCMutexUnlock(&f->m);
c1e485cc 1112
429c6388 1113 if (!(f->flags & FLOW_NO_APPLAYER_INSPECTION)) {
9f95ab74 1114 printf("flag should have been set, but is not: ");
c1e485cc
GS
1115 goto end;
1116 }
1117
9f95ab74 1118 result = 1;
429c6388
AS
1119 end:
1120 AppLayerParserRestoreParserTable();
8cc525c9 1121 StreamTcpFreeConfig(TRUE);
262a7300
VJ
1122
1123 UTHFreeFlow(f);
8cc525c9
PR
1124 return result;
1125}
1126
6cb00142
AS
1127/**
1128 * \test Test the deallocation of app layer parser memory on occurance of
1129 * error in the parsing process for UDP.
8cc525c9 1130 */
429c6388 1131static int AppLayerParserTest02(void)
8cc525c9 1132{
429c6388
AS
1133 AppLayerParserBackupParserTable();
1134
8cc525c9 1135 int result = 1;
262a7300 1136 Flow *f = NULL;
8cc525c9
PR
1137 uint8_t testbuf[] = { 0x11 };
1138 uint32_t testlen = sizeof(testbuf);
fdefb65b 1139 void *alp_tctx = AppLayerParserThreadCtxAlloc();
8cc525c9
PR
1140
1141 /* Register the Test protocol state and parser functions */
429c6388
AS
1142 AppLayerParserRegisterParser(IPPROTO_UDP, ALPROTO_TEST, STREAM_TOSERVER,
1143 TestProtocolParser);
1144 AppLayerParserRegisterStateFuncs(IPPROTO_UDP, ALPROTO_TEST,
1145 TestProtocolStateAlloc, TestProtocolStateFree);
8cc525c9 1146
262a7300
VJ
1147 f = UTHBuildFlow(AF_INET, "1.2.3.4", "4.3.2.1", 20, 40);
1148 if (f == NULL)
1149 goto end;
1150 f->alproto = ALPROTO_TEST;
1151 f->proto = IPPROTO_UDP;
8cc525c9
PR
1152
1153 StreamTcpInitConfig(TRUE);
8cc525c9 1154
cd3e32ce 1155 SCMutexLock(&f->m);
429c6388 1156 int r = AppLayerParserParse(alp_tctx, f, ALPROTO_TEST, STREAM_TOSERVER|STREAM_EOF, testbuf,
8cc525c9
PR
1157 testlen);
1158 if (r != -1) {
1159 printf("returned %" PRId32 ", expected -1: \n", r);
1160 result = 0;
cd3e32ce 1161 SCMutexUnlock(&f->m);
8cc525c9
PR
1162 goto end;
1163 }
cd3e32ce 1164 SCMutexUnlock(&f->m);
8cc525c9 1165
429c6388
AS
1166 end:
1167 AppLayerParserRestoreParserTable();
6a53ab9c 1168 StreamTcpFreeConfig(TRUE);
262a7300 1169 UTHFreeFlow(f);
c1e485cc
GS
1170 return result;
1171}
1172
7c31a232 1173
429c6388 1174void AppLayerParserRegisterUnittests(void)
7c31a232 1175{
429c6388 1176 SCEnter();
9faa4b74 1177
429c6388 1178 int ip;
f5f14880 1179 AppProto alproto;
c23742a0 1180 AppLayerParserProtoCtx *ctx;
9faa4b74 1181
429c6388
AS
1182 for (ip = 0; ip < FLOW_PROTO_DEFAULT; ip++) {
1183 for (alproto = 0; alproto < ALPROTO_MAX; alproto++) {
1184 ctx = &alp_ctx.ctxs[ip][alproto];
1185 if (ctx->RegisterUnittests == NULL)
1186 continue;
1187 ctx->RegisterUnittests();
9faa4b74
VJ
1188 }
1189 }
1190
7c31a232
AS
1191 UtRegisterTest("AppLayerParserTest01", AppLayerParserTest01, 1);
1192 UtRegisterTest("AppLayerParserTest02", AppLayerParserTest02, 1);
7c31a232 1193
429c6388 1194 SCReturn;
c1e485cc 1195}
429c6388
AS
1196
1197#endif