Coverage Report

Created: 2026-01-16 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/app-layer-parser.c
Line
Count
Source
1
/* Copyright (C) 2007-2025 Open Information Security Foundation
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
 */
25
26
#include "suricata-common.h"
27
#include "app-layer-parser.h"
28
29
#include "flow.h"
30
#include "flow-private.h"
31
#include "flow-util.h"
32
33
#include "app-layer-frames.h"
34
35
#include "stream-tcp.h"
36
37
#include "util-validate.h"
38
39
#include "app-layer.h"
40
#include "app-layer-detect-proto.h"
41
42
#include "app-layer-ftp.h"
43
#include "app-layer-smtp.h"
44
45
#include "app-layer-smb.h"
46
#include "app-layer-htp.h"
47
#include "app-layer-ssl.h"
48
#include "app-layer-ssh.h"
49
#include "app-layer-modbus.h"
50
#include "app-layer-enip.h"
51
#include "app-layer-dnp3.h"
52
#include "app-layer-nfs-tcp.h"
53
#include "app-layer-nfs-udp.h"
54
#include "app-layer-ntp.h"
55
#include "app-layer-tftp.h"
56
#include "app-layer-ike.h"
57
#include "app-layer-krb5.h"
58
#include "app-layer-sip.h"
59
#include "app-layer-rfb.h"
60
#include "app-layer-mqtt.h"
61
#include "app-layer-snmp.h"
62
#include "app-layer-quic.h"
63
#include "app-layer-rdp.h"
64
#include "app-layer-http2.h"
65
66
struct AppLayerParserThreadCtx_ {
67
    void *alproto_local_storage[FLOW_PROTO_MAX][ALPROTO_MAX];
68
};
69
70
71
/**
72
 * \brief App layer protocol parser context.
73
 */
74
typedef struct AppLayerParserProtoCtx_
75
{
76
    /* 0 - to_server, 1 - to_client. */
77
    AppLayerParserFPtr Parser[2];
78
79
    bool logger;
80
81
    /* Indicates the direction the parser is ready to see the data
82
     * the first time for a flow.  Values accepted -
83
     * STREAM_TOSERVER, STREAM_TOCLIENT */
84
    uint8_t first_data_dir;
85
86
    uint32_t logger_bits;   /**< registered loggers for this proto */
87
88
    void *(*StateAlloc)(void *, AppProto);
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
96
    /** get FileContainer reference from the TX. MUST return a non-NULL reference if the TX
97
     *  has or may have files in the requested direction at some point. */
98
    AppLayerGetFileState (*GetTxFiles)(void *, void *, uint8_t);
99
100
    int (*StateGetProgress)(void *alstate, uint8_t direction);
101
    uint64_t (*StateGetTxCnt)(void *alstate);
102
    void *(*StateGetTx)(void *alstate, uint64_t tx_id);
103
    AppLayerGetTxIteratorFunc StateGetTxIterator;
104
    int complete_ts;
105
    int complete_tc;
106
    int (*StateGetEventInfoById)(int event_id, const char **event_name,
107
                                 AppLayerEventType *event_type);
108
    int (*StateGetEventInfo)(const char *event_name,
109
                             int *event_id, AppLayerEventType *event_type);
110
111
    AppLayerStateData *(*GetStateData)(void *state);
112
    AppLayerTxData *(*GetTxData)(void *tx);
113
    bool (*ApplyTxConfig)(void *state, void *tx, int mode, AppLayerTxConfig);
114
115
    void (*SetStreamDepthFlag)(void *tx, uint8_t flags);
116
117
    AppLayerParserGetFrameIdByNameFn GetFrameIdByName;
118
    AppLayerParserGetFrameNameByIdFn GetFrameNameById;
119
120
    /* each app-layer has its own value */
121
    uint32_t stream_depth;
122
123
    /* Option flags such as supporting gaps or not. */
124
    uint32_t option_flags;
125
    /* coccinelle: AppLayerParserProtoCtx:option_flags:APP_LAYER_PARSER_OPT_ */
126
127
    uint32_t internal_flags;
128
    /* coccinelle: AppLayerParserProtoCtx:internal_flags:APP_LAYER_PARSER_INT_ */
129
130
#ifdef UNITTESTS
131
    void (*RegisterUnittests)(void);
132
#endif
133
} AppLayerParserProtoCtx;
134
135
typedef struct AppLayerParserCtx_ {
136
    AppLayerParserProtoCtx ctxs[FLOW_PROTO_MAX][ALPROTO_MAX];
137
} AppLayerParserCtx;
138
139
struct AppLayerParserState_ {
140
    /* coccinelle: AppLayerParserState:flags:APP_LAYER_PARSER_ */
141
    uint16_t flags;
142
143
    /* Indicates the current transaction that is being inspected.
144
     * We have a var per direction. */
145
    uint64_t inspect_id[2];
146
    /* Indicates the current transaction being logged.  Unlike inspect_id,
147
     * we don't need a var per direction since we don't log a transaction
148
     * unless we have the entire transaction. */
149
    uint64_t log_id;
150
151
    uint64_t min_id;
152
153
    /* Used to store decoder events. */
154
    AppLayerDecoderEvents *decoder_events;
155
156
    FramesContainer *frames;
157
};
158
159
enum ExceptionPolicy g_applayerparser_error_policy = EXCEPTION_POLICY_NOT_SET;
160
161
static void AppLayerConfig(void)
162
74
{
163
74
    g_applayerparser_error_policy = ExceptionPolicyParse("app-layer.error-policy", true);
164
74
}
165
166
enum ExceptionPolicy AppLayerErrorGetExceptionPolicy(void)
167
26.0k
{
168
26.0k
    return g_applayerparser_error_policy;
169
26.0k
}
170
171
static void AppLayerParserFramesFreeContainer(FramesContainer *frames)
172
666k
{
173
666k
    if (frames != NULL) {
174
113k
        FramesFree(&frames->toserver);
175
113k
        FramesFree(&frames->toclient);
176
113k
        SCFree(frames);
177
113k
    }
178
666k
}
179
180
void AppLayerFramesFreeContainer(Flow *f)
181
10.0k
{
182
10.0k
    if (f == NULL || f->alparser == NULL || f->alparser->frames == NULL)
183
0
        return;
184
10.0k
    AppLayerParserFramesFreeContainer(f->alparser->frames);
185
10.0k
    f->alparser->frames = NULL;
186
10.0k
}
187
188
FramesContainer *AppLayerFramesGetContainer(Flow *f)
189
31.4M
{
190
31.4M
    if (f == NULL || f->alparser == NULL)
191
4.55M
        return NULL;
192
26.8M
    return f->alparser->frames;
193
31.4M
}
194
195
FramesContainer *AppLayerFramesSetupContainer(Flow *f)
196
4.94M
{
197
#ifdef UNITTESTS
198
    if (f == NULL || f->alparser == NULL || (f->proto == IPPROTO_TCP && f->protoctx == NULL))
199
        return NULL;
200
#endif
201
4.94M
    DEBUG_VALIDATE_BUG_ON(f == NULL || f->alparser == NULL);
202
4.94M
    if (f->alparser->frames == NULL) {
203
113k
        f->alparser->frames = SCCalloc(1, sizeof(FramesContainer));
204
113k
        if (f->alparser->frames == NULL) {
205
0
            return NULL;
206
0
        }
207
#ifdef DEBUG
208
        f->alparser->frames->toserver.ipproto = f->proto;
209
        f->alparser->frames->toserver.alproto = f->alproto;
210
        f->alparser->frames->toclient.ipproto = f->proto;
211
        f->alparser->frames->toclient.alproto = f->alproto;
212
#endif
213
113k
    }
214
4.94M
    return f->alparser->frames;
215
4.94M
}
216
217
static inline void AppLayerParserStreamTruncated(AppLayerParserState *pstate, const uint8_t ipproto,
218
        const AppProto alproto, void *alstate, const uint8_t direction);
219
220
#ifdef UNITTESTS
221
void UTHAppLayerParserStateGetIds(void *ptr, uint64_t *i1, uint64_t *i2, uint64_t *log, uint64_t *min)
222
{
223
    struct AppLayerParserState_ *s = ptr;
224
    *i1 = s->inspect_id[0];
225
    *i2 = s->inspect_id[1];
226
    *log = s->log_id;
227
    *min = s->min_id;
228
}
229
#endif
230
231
/* Static global version of the parser context.
232
 * Post 2.0 let's look at changing this to move it out to app-layer.c. */
233
static AppLayerParserCtx alp_ctx;
234
235
int AppLayerParserProtoIsRegistered(uint8_t ipproto, AppProto alproto)
236
3.23k
{
237
3.23k
    uint8_t ipproto_map = FlowGetProtoMapping(ipproto);
238
239
3.23k
    return (alp_ctx.ctxs[ipproto_map][alproto].StateAlloc != NULL) ? 1 : 0;
240
3.23k
}
241
242
AppLayerParserState *AppLayerParserStateAlloc(void)
243
656k
{
244
656k
    SCEnter();
245
246
656k
    AppLayerParserState *pstate = (AppLayerParserState *)SCMalloc(sizeof(*pstate));
247
656k
    if (pstate == NULL)
248
0
        goto end;
249
656k
    memset(pstate, 0, sizeof(*pstate));
250
251
656k
 end:
252
656k
    SCReturnPtr(pstate, "AppLayerParserState");
253
656k
}
254
255
void AppLayerParserStateFree(AppLayerParserState *pstate)
256
656k
{
257
656k
    SCEnter();
258
259
656k
    if (pstate->decoder_events != NULL)
260
0
        AppLayerDecoderEventsFreeEvents(&pstate->decoder_events);
261
656k
    AppLayerParserFramesFreeContainer(pstate->frames);
262
656k
    SCFree(pstate);
263
264
656k
    SCReturn;
265
656k
}
266
267
int AppLayerParserSetup(void)
268
34
{
269
34
    SCEnter();
270
34
    memset(&alp_ctx, 0, sizeof(alp_ctx));
271
34
    SCReturnInt(0);
272
34
}
273
274
void AppLayerParserPostStreamSetup(void)
275
71
{
276
    /* lets set a default value for stream_depth */
277
284
    for (int flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) {
278
8.23k
        for (AppProto alproto = 0; alproto < ALPROTO_MAX; alproto++) {
279
8.02k
            if (!(alp_ctx.ctxs[flow_proto][alproto].internal_flags &
280
8.02k
                        APP_LAYER_PARSER_INT_STREAM_DEPTH_SET)) {
281
7.95k
                alp_ctx.ctxs[flow_proto][alproto].stream_depth =
282
7.95k
                    stream_config.reassembly_depth;
283
7.95k
            }
284
8.02k
        }
285
213
    }
286
71
}
287
288
int AppLayerParserDeSetup(void)
289
0
{
290
0
    SCEnter();
291
292
0
    FTPParserCleanup();
293
0
    SMTPParserCleanup();
294
295
0
    SCReturnInt(0);
296
0
}
297
298
AppLayerParserThreadCtx *AppLayerParserThreadCtxAlloc(void)
299
37
{
300
37
    SCEnter();
301
302
37
    AppLayerParserThreadCtx *tctx = SCCalloc(1, sizeof(*tctx));
303
37
    if (tctx == NULL)
304
0
        goto end;
305
306
148
    for (uint8_t flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) {
307
3.99k
        for (AppProto alproto = 0; alproto < ALPROTO_MAX; alproto++) {
308
3.88k
            uint8_t ipproto = FlowGetReverseProtoMapping(flow_proto);
309
310
3.88k
            tctx->alproto_local_storage[flow_proto][alproto] =
311
3.88k
                AppLayerParserGetProtocolParserLocalStorage(ipproto, alproto);
312
3.88k
        }
313
111
    }
314
315
37
 end:
316
37
    SCReturnPtr(tctx, "void *");
317
37
}
318
319
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
320
0
{
321
0
    SCEnter();
322
323
0
    for (uint8_t flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) {
324
0
        for (AppProto alproto = 0; alproto < ALPROTO_MAX; alproto++) {
325
0
            uint8_t ipproto = FlowGetReverseProtoMapping(flow_proto);
326
327
0
            AppLayerParserDestroyProtocolParserLocalStorage(ipproto, alproto,
328
0
                                                            tctx->alproto_local_storage[flow_proto][alproto]);
329
0
        }
330
0
    }
331
332
0
    SCFree(tctx);
333
0
    SCReturn;
334
0
}
335
336
/** \brief check if a parser is enabled in the config
337
 *  Returns enabled always if: were running unittests
338
 */
339
int AppLayerParserConfParserEnabled(const char *ipproto,
340
                                    const char *alproto_name)
341
1.18k
{
342
1.18k
    SCEnter();
343
344
1.18k
    int enabled = 1;
345
1.18k
    char param[100];
346
1.18k
    ConfNode *node;
347
1.18k
    int r;
348
349
1.18k
    if (RunmodeIsUnittests())
350
0
        goto enabled;
351
352
1.18k
    r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
353
1.18k
                 alproto_name, ".enabled");
354
1.18k
    if (r < 0) {
355
0
        FatalError("snprintf failure.");
356
1.18k
    } else if (r > (int)sizeof(param)) {
357
0
        FatalError("buffer not big enough to write param.");
358
0
    }
359
360
1.18k
    node = ConfGetNode(param);
361
1.18k
    if (node == NULL) {
362
758
        SCLogDebug("Entry for %s not found.", param);
363
758
        r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
364
758
                     alproto_name, ".", ipproto, ".enabled");
365
758
        if (r < 0) {
366
0
            FatalError("snprintf failure.");
367
758
        } else if (r > (int)sizeof(param)) {
368
0
            FatalError("buffer not big enough to write param.");
369
0
        }
370
371
758
        node = ConfGetNode(param);
372
758
        if (node == NULL) {
373
758
            SCLogDebug("Entry for %s not found.", param);
374
758
            goto enabled;
375
758
        }
376
758
    }
377
378
429
    if (ConfValIsTrue(node->val)) {
379
429
        goto enabled;
380
429
    } else if (ConfValIsFalse(node->val)) {
381
0
        goto disabled;
382
0
    } else if (strcasecmp(node->val, "detection-only") == 0) {
383
0
        goto disabled;
384
0
    } else {
385
0
        SCLogError("Invalid value found for %s.", param);
386
0
        exit(EXIT_FAILURE);
387
0
    }
388
389
0
 disabled:
390
0
    enabled = 0;
391
1.18k
 enabled:
392
1.18k
    SCReturnInt(enabled);
393
0
}
394
395
/***** Parser related registration *****/
396
397
int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto,
398
                      uint8_t direction,
399
                      AppLayerParserFPtr Parser)
400
5.72k
{
401
5.72k
    SCEnter();
402
403
5.72k
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
404
5.72k
        Parser[(direction & STREAM_TOSERVER) ? 0 : 1] = Parser;
405
406
5.72k
    SCReturnInt(0);
407
5.72k
}
408
409
void AppLayerParserRegisterParserAcceptableDataDirection(uint8_t ipproto, AppProto alproto,
410
                                              uint8_t direction)
411
203
{
412
203
    SCEnter();
413
414
203
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].first_data_dir |=
415
203
        (direction & (STREAM_TOSERVER | STREAM_TOCLIENT));
416
417
203
    SCReturn;
418
203
}
419
420
void AppLayerParserRegisterOptionFlags(uint8_t ipproto, AppProto alproto,
421
        uint32_t flags)
422
775
{
423
775
    SCEnter();
424
425
775
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].option_flags |= flags;
426
427
775
    SCReturn;
428
775
}
429
430
uint32_t AppLayerParserGetOptionFlags(uint8_t protomap, AppProto alproto)
431
0
{
432
0
    SCEnter();
433
0
    SCReturnUInt(alp_ctx.ctxs[protomap][alproto].option_flags);
434
0
}
435
436
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto,
437
        void *(*StateAlloc)(void *, AppProto), void (*StateFree)(void *))
438
2.86k
{
439
2.86k
    SCEnter();
440
441
2.86k
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateAlloc =
442
2.86k
        StateAlloc;
443
2.86k
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateFree =
444
2.86k
        StateFree;
445
446
2.86k
    SCReturn;
447
2.86k
}
448
449
void AppLayerParserRegisterLocalStorageFunc(uint8_t ipproto, AppProto alproto,
450
                                 void *(*LocalStorageAlloc)(void),
451
                                 void (*LocalStorageFree)(void *))
452
148
{
453
148
    SCEnter();
454
455
148
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].LocalStorageAlloc =
456
148
        LocalStorageAlloc;
457
148
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].LocalStorageFree =
458
148
        LocalStorageFree;
459
460
148
    SCReturn;
461
148
}
462
463
void AppLayerParserRegisterGetTxFilesFunc(uint8_t ipproto, AppProto alproto,
464
        AppLayerGetFileState (*GetTxFiles)(void *, void *, uint8_t))
465
558
{
466
558
    SCEnter();
467
468
558
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxFiles = GetTxFiles;
469
470
558
    SCReturn;
471
558
}
472
473
void AppLayerParserRegisterLoggerBits(uint8_t ipproto, AppProto alproto, LoggerId bits)
474
172
{
475
172
    SCEnter();
476
477
172
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].logger_bits = bits;
478
479
172
    SCReturn;
480
172
}
481
482
void AppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto)
483
56
{
484
56
    SCEnter();
485
486
56
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].logger = true;
487
488
56
    SCReturn;
489
56
}
490
491
void AppLayerParserRegisterTruncateFunc(uint8_t ipproto, AppProto alproto,
492
                                        void (*Truncate)(void *, uint8_t))
493
34
{
494
34
    SCEnter();
495
496
34
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].Truncate = Truncate;
497
498
34
    SCReturn;
499
34
}
500
501
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto,
502
    int (*StateGetProgress)(void *alstate, uint8_t direction))
503
2.86k
{
504
2.86k
    SCEnter();
505
506
2.86k
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
507
2.86k
        StateGetProgress = StateGetProgress;
508
509
2.86k
    SCReturn;
510
2.86k
}
511
512
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto,
513
                           void (*StateTransactionFree)(void *, uint64_t))
514
2.86k
{
515
2.86k
    SCEnter();
516
517
2.86k
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
518
2.86k
        StateTransactionFree = StateTransactionFree;
519
520
2.86k
    SCReturn;
521
2.86k
}
522
523
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto,
524
                         uint64_t (*StateGetTxCnt)(void *alstate))
525
2.86k
{
526
2.86k
    SCEnter();
527
528
2.86k
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
529
2.86k
        StateGetTxCnt = StateGetTxCnt;
530
531
2.86k
    SCReturn;
532
2.86k
}
533
534
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto,
535
                      void *(StateGetTx)(void *alstate, uint64_t tx_id))
536
2.86k
{
537
2.86k
    SCEnter();
538
539
2.86k
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
540
2.86k
        StateGetTx = StateGetTx;
541
542
2.86k
    SCReturn;
543
2.86k
}
544
545
void AppLayerParserRegisterGetTxIterator(uint8_t ipproto, AppProto alproto,
546
                      AppLayerGetTxIteratorFunc Func)
547
2.53k
{
548
2.53k
    SCEnter();
549
2.53k
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetTxIterator = Func;
550
2.53k
    SCReturn;
551
2.53k
}
552
553
void AppLayerParserRegisterStateProgressCompletionStatus(
554
        AppProto alproto, const int ts, const int tc)
555
2.86k
{
556
2.86k
    BUG_ON(ts == 0);
557
2.86k
    BUG_ON(tc == 0);
558
2.86k
    BUG_ON(!AppProtoIsValid(alproto));
559
2.86k
    BUG_ON(alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].complete_ts != 0 &&
560
2.86k
            alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].complete_ts != ts);
561
2.86k
    BUG_ON(alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].complete_tc != 0 &&
562
2.86k
            alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].complete_tc != tc);
563
564
2.86k
    alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].complete_ts = ts;
565
2.86k
    alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].complete_tc = tc;
566
2.86k
}
567
568
void AppLayerParserRegisterGetEventInfoById(uint8_t ipproto, AppProto alproto,
569
    int (*StateGetEventInfoById)(int event_id, const char **event_name,
570
                                 AppLayerEventType *event_type))
571
2.42k
{
572
2.42k
    SCEnter();
573
574
2.42k
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
575
2.42k
        StateGetEventInfoById = StateGetEventInfoById;
576
577
2.42k
    SCReturn;
578
2.42k
}
579
580
void AppLayerParserRegisterGetFrameFuncs(uint8_t ipproto, AppProto alproto,
581
        AppLayerParserGetFrameIdByNameFn GetIdByNameFunc,
582
        AppLayerParserGetFrameNameByIdFn GetNameByIdFunc)
583
1.29k
{
584
1.29k
    SCEnter();
585
1.29k
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetFrameIdByName = GetIdByNameFunc;
586
1.29k
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetFrameNameById = GetNameByIdFunc;
587
1.29k
    SCReturn;
588
1.29k
}
589
590
void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto,
591
    int (*StateGetEventInfo)(const char *event_name, int *event_id,
592
                             AppLayerEventType *event_type))
593
2.53k
{
594
2.53k
    SCEnter();
595
596
2.53k
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
597
2.53k
        StateGetEventInfo = StateGetEventInfo;
598
599
2.53k
    SCReturn;
600
2.53k
}
601
602
void AppLayerParserRegisterTxDataFunc(uint8_t ipproto, AppProto alproto,
603
        AppLayerTxData *(*GetTxData)(void *tx))
604
2.86k
{
605
2.86k
    SCEnter();
606
607
2.86k
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxData = GetTxData;
608
609
2.86k
    SCReturn;
610
2.86k
}
611
612
void AppLayerParserRegisterStateDataFunc(
613
        uint8_t ipproto, AppProto alproto, AppLayerStateData *(*GetStateData)(void *state))
614
2.86k
{
615
2.86k
    SCEnter();
616
617
2.86k
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetStateData = GetStateData;
618
619
2.86k
    SCReturn;
620
2.86k
}
621
622
void AppLayerParserRegisterApplyTxConfigFunc(uint8_t ipproto, AppProto alproto,
623
        bool (*ApplyTxConfig)(void *state, void *tx, int mode, AppLayerTxConfig))
624
148
{
625
148
    SCEnter();
626
627
148
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].ApplyTxConfig = ApplyTxConfig;
628
629
148
    SCReturn;
630
148
}
631
632
void AppLayerParserRegisterSetStreamDepthFlag(uint8_t ipproto, AppProto alproto,
633
        void (*SetStreamDepthFlag)(void *tx, uint8_t flags))
634
74
{
635
74
    SCEnter();
636
637
74
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetStreamDepthFlag = SetStreamDepthFlag;
638
639
74
    SCReturn;
640
74
}
641
642
/***** Get and transaction functions *****/
643
644
void *AppLayerParserGetProtocolParserLocalStorage(uint8_t ipproto, AppProto alproto)
645
8.92k
{
646
8.92k
    SCEnter();
647
8.92k
    void * r = NULL;
648
649
8.92k
    if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
650
8.92k
        LocalStorageAlloc != NULL)
651
158
    {
652
158
        r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
653
158
                    LocalStorageAlloc();
654
158
    }
655
656
8.92k
    SCReturnPtr(r, "void *");
657
8.92k
}
658
659
void AppLayerParserDestroyProtocolParserLocalStorage(uint8_t ipproto, AppProto alproto,
660
                                          void *local_data)
661
0
{
662
0
    SCEnter();
663
664
0
    if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
665
0
        LocalStorageFree != NULL)
666
0
    {
667
0
        alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
668
0
            LocalStorageFree(local_data);
669
0
    }
670
671
0
    SCReturn;
672
0
}
673
674
/** \brief default tx iterator
675
 *
676
 *  Used if the app layer parser doesn't register its own iterator.
677
 *  Simply walks the tx_id space until it finds a tx. Uses 'state' to
678
 *  keep track of where it left off.
679
 *
680
 *  \retval txptr or NULL if no more txs in list
681
 */
682
static AppLayerGetTxIterTuple AppLayerDefaultGetTxIterator(
683
        const uint8_t ipproto, const AppProto alproto,
684
        void *alstate, uint64_t min_tx_id, uint64_t max_tx_id,
685
        AppLayerGetTxIterState *state)
686
49.6M
{
687
49.6M
    uint64_t ustate = *(uint64_t *)state;
688
49.6M
    uint64_t tx_id = MAX(min_tx_id, ustate);
689
86.4M
    for ( ; tx_id < max_tx_id; tx_id++) {
690
86.2M
        void *tx_ptr = AppLayerParserGetTx(ipproto, alproto, alstate, tx_id);
691
86.2M
        if (tx_ptr != NULL) {
692
49.4M
            ustate = tx_id + 1;
693
49.4M
            *state = *(AppLayerGetTxIterState *)&ustate;
694
49.4M
            AppLayerGetTxIterTuple tuple = {
695
49.4M
                .tx_ptr = tx_ptr,
696
49.4M
                .tx_id = tx_id,
697
49.4M
                .has_next = (tx_id + 1 < max_tx_id),
698
49.4M
            };
699
49.4M
            SCLogDebug("tuple: %p/%"PRIu64"/%s", tuple.tx_ptr, tuple.tx_id,
700
49.4M
                    tuple.has_next ? "true" : "false");
701
49.4M
            return tuple;
702
49.4M
        }
703
86.2M
    }
704
705
180k
    AppLayerGetTxIterTuple no_tuple = { NULL, 0, false };
706
180k
    return no_tuple;
707
49.6M
}
708
709
AppLayerGetTxIteratorFunc AppLayerGetTxIterator(const uint8_t ipproto,
710
        const AppProto alproto)
711
46.4M
{
712
46.4M
    AppLayerGetTxIteratorFunc Func =
713
46.4M
        alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetTxIterator;
714
46.4M
    return Func ? Func : AppLayerDefaultGetTxIterator;
715
46.4M
}
716
717
uint64_t AppLayerParserGetTransactionLogId(AppLayerParserState *pstate)
718
5.15M
{
719
5.15M
    SCEnter();
720
721
5.15M
    SCReturnCT((pstate == NULL) ? 0 : pstate->log_id, "uint64_t");
722
5.15M
}
723
724
uint64_t AppLayerParserGetMinId(AppLayerParserState *pstate)
725
60.4k
{
726
60.4k
    SCEnter();
727
728
60.4k
    SCReturnCT((pstate == NULL) ? 0 : pstate->min_id, "uint64_t");
729
60.4k
}
730
731
void AppLayerParserSetTransactionLogId(AppLayerParserState *pstate, uint64_t tx_id)
732
641k
{
733
641k
    SCEnter();
734
735
641k
    if (pstate != NULL)
736
641k
        pstate->log_id = tx_id;
737
738
641k
    SCReturn;
739
641k
}
740
741
uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction)
742
1.62M
{
743
1.62M
    SCEnter();
744
745
1.62M
    if (pstate == NULL)
746
0
        SCReturnCT(0ULL, "uint64_t");
747
748
1.62M
    SCReturnCT(pstate->inspect_id[(direction & STREAM_TOSERVER) ? 0 : 1], "uint64_t");
749
1.62M
}
750
751
inline uint64_t AppLayerParserGetTxDetectFlags(AppLayerTxData *txd, const uint8_t dir)
752
1.51M
{
753
1.51M
    uint64_t detect_flags =
754
1.51M
        (dir & STREAM_TOSERVER) ? txd->detect_flags_ts : txd->detect_flags_tc;
755
1.51M
    return detect_flags;
756
1.51M
}
757
758
static inline void SetTxDetectFlags(AppLayerTxData *txd, const uint8_t dir, const uint64_t detect_flags)
759
2.71k
{
760
2.71k
    if (dir & STREAM_TOSERVER) {
761
1.77k
        txd->detect_flags_ts = detect_flags;
762
1.77k
    } else {
763
935
        txd->detect_flags_tc = detect_flags;
764
935
    }
765
2.71k
}
766
767
static inline uint32_t GetTxLogged(AppLayerTxData *txd)
768
1.12M
{
769
1.12M
    return txd->logged.flags;
770
1.12M
}
771
772
void AppLayerParserSetTransactionInspectId(const Flow *f, AppLayerParserState *pstate,
773
                                           void *alstate, const uint8_t flags,
774
                                           bool tag_txs_as_inspected)
775
664k
{
776
664k
    SCEnter();
777
778
664k
    const int direction = (flags & STREAM_TOSERVER) ? 0 : 1;
779
664k
    const uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
780
664k
    uint64_t idx = AppLayerParserGetTransactionInspectId(pstate, flags);
781
664k
    const int state_done_progress = AppLayerParserGetStateProgressCompletionStatus(f->alproto, flags);
782
664k
    const uint8_t ipproto = f->proto;
783
664k
    const AppProto alproto = f->alproto;
784
785
664k
    AppLayerGetTxIteratorFunc IterFunc = AppLayerGetTxIterator(ipproto, alproto);
786
664k
    AppLayerGetTxIterState state;
787
664k
    memset(&state, 0, sizeof(state));
788
789
664k
    SCLogDebug("called: %s, tag_txs_as_inspected %s",direction==0?"toserver":"toclient",
790
664k
            tag_txs_as_inspected?"true":"false");
791
792
    /* mark all txs as inspected if the applayer progress is
793
     * at the 'end state'. */
794
782k
    while (1) {
795
782k
        AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, idx, total_txs, &state);
796
782k
        if (ires.tx_ptr == NULL)
797
100k
            break;
798
799
682k
        void *tx = ires.tx_ptr;
800
682k
        idx = ires.tx_id;
801
802
682k
        int state_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx, flags);
803
682k
        if (state_progress < state_done_progress)
804
435k
            break;
805
806
247k
        AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
807
247k
        if (txd && tag_txs_as_inspected) {
808
2.68k
            uint64_t detect_flags = AppLayerParserGetTxDetectFlags(txd, flags);
809
2.68k
            if ((detect_flags & APP_LAYER_TX_INSPECTED_FLAG) == 0) {
810
2.67k
                detect_flags |= APP_LAYER_TX_INSPECTED_FLAG;
811
2.67k
                SetTxDetectFlags(txd, flags, detect_flags);
812
2.67k
                SCLogDebug("%p/%"PRIu64" in-order tx is done for direction %s. Flag %016"PRIx64,
813
2.67k
                        tx, idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags);
814
2.67k
            }
815
2.68k
        }
816
247k
        idx++;
817
247k
        if (!ires.has_next)
818
129k
            break;
819
247k
    }
820
664k
    pstate->inspect_id[direction] = idx;
821
664k
    SCLogDebug("inspect_id now %"PRIu64, pstate->inspect_id[direction]);
822
823
    /* if necessary we flag all txs that are complete as 'inspected'
824
     * also move inspect_id forward. */
825
664k
    if (tag_txs_as_inspected) {
826
        /* continue at idx */
827
11.7k
        while (1) {
828
11.7k
            AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, idx, total_txs, &state);
829
11.7k
            if (ires.tx_ptr == NULL)
830
9.71k
                break;
831
832
2.05k
            void *tx = ires.tx_ptr;
833
            /* if we got a higher id than the minimum we requested, we
834
             * skipped a bunch of 'null-txs'. Lets see if we can up the
835
             * inspect tracker */
836
2.05k
            if (ires.tx_id > idx && pstate->inspect_id[direction] == idx) {
837
678
                pstate->inspect_id[direction] = ires.tx_id;
838
678
            }
839
2.05k
            idx = ires.tx_id;
840
841
2.05k
            const int state_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx, flags);
842
2.05k
            if (state_progress < state_done_progress)
843
2.01k
                break;
844
845
            /* txd can be NULL for HTTP sessions where the user data alloc failed */
846
39
            AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
847
39
            if (likely(txd)) {
848
39
                uint64_t detect_flags = AppLayerParserGetTxDetectFlags(txd, flags);
849
39
                if ((detect_flags & APP_LAYER_TX_INSPECTED_FLAG) == 0) {
850
39
                    detect_flags |= APP_LAYER_TX_INSPECTED_FLAG;
851
39
                    SetTxDetectFlags(txd, flags, detect_flags);
852
39
                    SCLogDebug("%p/%"PRIu64" out of order tx is done for direction %s. Flag %016"PRIx64,
853
39
                            tx, idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", detect_flags);
854
855
39
                    SCLogDebug("%p/%"PRIu64" out of order tx. Update inspect_id? %"PRIu64,
856
39
                            tx, idx, pstate->inspect_id[direction]);
857
39
                    if (pstate->inspect_id[direction]+1 == idx)
858
25
                        pstate->inspect_id[direction] = idx;
859
39
                }
860
39
            } else {
861
0
                if (pstate->inspect_id[direction]+1 == idx)
862
0
                    pstate->inspect_id[direction] = idx;
863
0
            }
864
39
            if (!ires.has_next)
865
0
                break;
866
39
            idx++;
867
39
        }
868
11.7k
    }
869
870
664k
    SCReturn;
871
664k
}
872
873
AppLayerDecoderEvents *AppLayerParserGetDecoderEvents(AppLayerParserState *pstate)
874
21.7M
{
875
21.7M
    SCEnter();
876
877
21.7M
    SCReturnPtr(pstate->decoder_events,
878
21.7M
                "AppLayerDecoderEvents *");
879
21.7M
}
880
881
void AppLayerParserSetDecoderEvents(AppLayerParserState *pstate, AppLayerDecoderEvents *devents)
882
0
{
883
0
    pstate->decoder_events = devents;
884
0
}
885
886
AppLayerDecoderEvents *AppLayerParserGetEventsByTx(uint8_t ipproto, AppProto alproto,
887
                                        void *tx)
888
22.4M
{
889
22.4M
    SCEnter();
890
891
22.4M
    AppLayerDecoderEvents *ptr = NULL;
892
893
    /* Access events via the tx_data. */
894
22.4M
    AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
895
22.4M
    if (txd != NULL && txd->events != NULL) {
896
6.97M
        ptr = txd->events;
897
6.97M
    }
898
899
22.4M
    SCReturnPtr(ptr, "AppLayerDecoderEvents *");
900
22.4M
}
901
902
AppLayerGetFileState AppLayerParserGetTxFiles(
903
        const Flow *f, void *state, void *tx, const uint8_t direction)
904
204M
{
905
204M
    SCEnter();
906
907
204M
    if (alp_ctx.ctxs[f->protomap][f->alproto].GetTxFiles != NULL) {
908
204M
        return alp_ctx.ctxs[f->protomap][f->alproto].GetTxFiles(state, tx, direction);
909
204M
    }
910
911
57.7k
    AppLayerGetFileState files = { .fc = NULL, .cfg = NULL };
912
57.7k
    return files;
913
204M
}
914
915
static void AppLayerParserFileTxHousekeeping(
916
        const Flow *f, void *tx, const uint8_t pkt_dir, const bool trunc)
917
94.0M
{
918
94.0M
    AppLayerGetFileState files = AppLayerParserGetTxFiles(f, FlowGetAppState(f), tx, pkt_dir);
919
94.0M
    if (files.fc) {
920
94.0M
        FilesPrune(files.fc, files.cfg, trunc);
921
94.0M
    }
922
94.0M
}
923
924
104M
#define IS_DISRUPTED(flags) ((flags) & (STREAM_DEPTH | STREAM_GAP))
925
926
extern int g_detect_disabled;
927
extern bool g_file_logger_enabled;
928
extern bool g_filedata_logger_enabled;
929
930
/**
931
 * \brief remove obsolete (inspected and logged) transactions
932
 */
933
void AppLayerParserTransactionsCleanup(Flow *f, const uint8_t pkt_dir)
934
16.5M
{
935
16.5M
    SCEnter();
936
16.5M
    DEBUG_ASSERT_FLOW_LOCKED(f);
937
938
16.5M
    AppLayerParserProtoCtx *p = &alp_ctx.ctxs[f->protomap][f->alproto];
939
16.5M
    if (unlikely(p->StateTransactionFree == NULL))
940
294k
        SCReturn;
941
942
16.2M
    const bool has_tx_detect_flags = !g_detect_disabled;
943
16.2M
    const uint8_t ipproto = f->proto;
944
16.2M
    const AppProto alproto = f->alproto;
945
16.2M
    void * const alstate = f->alstate;
946
16.2M
    AppLayerParserState * const alparser = f->alparser;
947
948
16.2M
    if (alstate == NULL || alparser == NULL)
949
372
        SCReturn;
950
951
16.2M
    const uint64_t min = alparser->min_id;
952
16.2M
    const uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
953
16.2M
    const LoggerId logger_expectation = AppLayerParserProtocolGetLoggerBits(ipproto, alproto);
954
16.2M
    const int tx_end_state_ts = AppLayerParserGetStateProgressCompletionStatus(alproto, STREAM_TOSERVER);
955
16.2M
    const int tx_end_state_tc = AppLayerParserGetStateProgressCompletionStatus(alproto, STREAM_TOCLIENT);
956
16.2M
    const uint8_t ts_disrupt_flags = FlowGetDisruptionFlags(f, STREAM_TOSERVER);
957
16.2M
    const uint8_t tc_disrupt_flags = FlowGetDisruptionFlags(f, STREAM_TOCLIENT);
958
959
16.2M
    int pkt_dir_trunc = -1;
960
961
16.2M
    AppLayerGetTxIteratorFunc IterFunc = AppLayerGetTxIterator(ipproto, alproto);
962
16.2M
    AppLayerGetTxIterState state;
963
16.2M
    memset(&state, 0, sizeof(state));
964
16.2M
    uint64_t i = min;
965
16.2M
    uint64_t new_min = min;
966
16.2M
    SCLogDebug("start min %"PRIu64, min);
967
16.2M
    bool skipped = false;
968
    // const bool support_files = AppLayerParserSupportsFiles(f->proto, f->alproto);
969
970
953M
    while (1) {
971
953M
        AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, i, total_txs, &state);
972
953M
        if (ires.tx_ptr == NULL)
973
3.99M
            break;
974
975
953M
        bool tx_skipped = false;
976
949M
        void *tx = ires.tx_ptr;
977
949M
        i = ires.tx_id; // actual tx id for the tx the IterFunc returned
978
979
949M
        SCLogDebug("%p/%"PRIu64" checking", tx, i);
980
949M
        AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
981
949M
        if (txd != NULL && AppLayerParserHasFilesInDir(txd, pkt_dir)) {
982
37.2M
            if (pkt_dir_trunc == -1)
983
3.19M
                pkt_dir_trunc =
984
3.19M
                        AppLayerParserStateIssetFlag(f->alparser,
985
3.19M
                                (pkt_dir == STREAM_TOSERVER) ? APP_LAYER_PARSER_TRUNC_TS
986
3.19M
                                                             : APP_LAYER_PARSER_TRUNC_TC) != 0;
987
988
37.2M
            AppLayerParserFileTxHousekeeping(f, tx, pkt_dir, (bool)pkt_dir_trunc);
989
37.2M
        }
990
949M
        if (txd) {
991
            // should be reset by parser next time it updates the tx
992
949M
            if (pkt_dir & STREAM_TOSERVER) {
993
507M
                txd->updated_ts = false;
994
507M
            } else {
995
441M
                txd->updated_tc = false;
996
441M
            }
997
949M
        }
998
949M
        const int tx_progress_tc =
999
949M
                AppLayerParserGetStateProgress(ipproto, alproto, tx, tc_disrupt_flags);
1000
949M
        if (tx_progress_tc < tx_end_state_tc) {
1001
737M
            SCLogDebug("%p/%"PRIu64" skipping: tc parser not done", tx, i);
1002
737M
            skipped = true;
1003
737M
            goto next;
1004
737M
        }
1005
211M
        const int tx_progress_ts =
1006
211M
                AppLayerParserGetStateProgress(ipproto, alproto, tx, ts_disrupt_flags);
1007
211M
        if (tx_progress_ts < tx_end_state_ts) {
1008
185M
            SCLogDebug("%p/%"PRIu64" skipping: ts parser not done", tx, i);
1009
185M
            skipped = true;
1010
185M
            goto next;
1011
185M
        }
1012
1013
26.0M
        if (txd && has_tx_detect_flags) {
1014
26.0M
            if (!IS_DISRUPTED(ts_disrupt_flags) &&
1015
26.0M
                    (f->sgh_toserver != NULL || (f->flags & FLOW_SGH_TOSERVER) == 0)) {
1016
734k
                uint64_t detect_flags_ts = AppLayerParserGetTxDetectFlags(txd, STREAM_TOSERVER);
1017
734k
                if (!(detect_flags_ts &
1018
734k
                            (APP_LAYER_TX_INSPECTED_FLAG | APP_LAYER_TX_SKIP_INSPECT_FLAG))) {
1019
35.4k
                    SCLogDebug("%p/%" PRIu64 " skipping: TS inspect not done: ts:%" PRIx64, tx, i,
1020
35.4k
                            detect_flags_ts);
1021
35.4k
                    tx_skipped = true;
1022
35.4k
                }
1023
734k
            }
1024
26.0M
            if (!IS_DISRUPTED(tc_disrupt_flags) &&
1025
26.0M
                    (f->sgh_toclient != NULL || (f->flags & FLOW_SGH_TOCLIENT) == 0)) {
1026
779k
                uint64_t detect_flags_tc = AppLayerParserGetTxDetectFlags(txd, STREAM_TOCLIENT);
1027
779k
                if (!(detect_flags_tc &
1028
779k
                            (APP_LAYER_TX_INSPECTED_FLAG | APP_LAYER_TX_SKIP_INSPECT_FLAG))) {
1029
543k
                    SCLogDebug("%p/%" PRIu64 " skipping: TC inspect not done: ts:%" PRIx64, tx, i,
1030
543k
                            detect_flags_tc);
1031
543k
                    tx_skipped = true;
1032
543k
                }
1033
779k
            }
1034
26.0M
        }
1035
1036
26.0M
        if (tx_skipped) {
1037
578k
            SCLogDebug("%p/%" PRIu64 " tx_skipped", tx, i);
1038
578k
            skipped = true;
1039
578k
            goto next;
1040
578k
        }
1041
1042
25.4M
        if (txd && logger_expectation != 0) {
1043
301k
            LoggerId tx_logged = GetTxLogged(txd);
1044
301k
            if (tx_logged != logger_expectation) {
1045
13.7k
                SCLogDebug("%p/%"PRIu64" skipping: logging not done: want:%"PRIx32", have:%"PRIx32,
1046
13.7k
                        tx, i, logger_expectation, tx_logged);
1047
13.7k
                skipped = true;
1048
13.7k
                goto next;
1049
13.7k
            }
1050
301k
        }
1051
1052
        /* if file logging is enabled, we keep a tx active while some of the files aren't
1053
         * logged yet. */
1054
25.4M
        if (txd) {
1055
25.4M
            SCLogDebug("files_opened %u files_logged %u files_stored %u", txd->files_opened,
1056
25.4M
                    txd->files_logged, txd->files_stored);
1057
1058
25.4M
            if (txd->files_opened) {
1059
245k
                if (g_file_logger_enabled && txd->files_opened != txd->files_logged) {
1060
36.4k
                    skipped = true;
1061
36.4k
                    goto next;
1062
36.4k
                }
1063
209k
                if (g_filedata_logger_enabled && txd->files_opened != txd->files_stored) {
1064
0
                    skipped = true;
1065
0
                    goto next;
1066
0
                }
1067
209k
            }
1068
25.4M
        }
1069
1070
        /* if we are here, the tx can be freed. */
1071
25.3M
        p->StateTransactionFree(alstate, i);
1072
25.3M
        SCLogDebug("%p/%"PRIu64" freed", tx, i);
1073
1074
        /* if we didn't skip any tx so far, up the minimum */
1075
25.3M
        SCLogDebug("skipped? %s i %"PRIu64", new_min %"PRIu64, skipped ? "true" : "false", i, new_min);
1076
25.3M
        if (!skipped)
1077
21.3M
            new_min = i + 1;
1078
25.3M
        SCLogDebug("final i %"PRIu64", new_min %"PRIu64, i, new_min);
1079
1080
949M
next:
1081
949M
        if (!ires.has_next) {
1082
            /* this was the last tx. See if we skipped any. If not
1083
             * we removed all and can update the minimum to the max
1084
             * id. */
1085
12.2M
            SCLogDebug("no next: cur tx i %"PRIu64", total %"PRIu64, i, total_txs);
1086
12.2M
            if (!skipped) {
1087
2.57M
                new_min = total_txs;
1088
2.57M
                SCLogDebug("no next: cur tx i %"PRIu64", total %"PRIu64": "
1089
2.57M
                        "new_min updated to %"PRIu64, i, total_txs, new_min);
1090
2.57M
            }
1091
12.2M
            break;
1092
12.2M
        }
1093
937M
        i++;
1094
937M
    }
1095
1096
    /* see if we need to bring all trackers up to date. */
1097
16.2M
    SCLogDebug("update f->alparser->min_id? %"PRIu64" vs %"PRIu64, new_min, alparser->min_id);
1098
16.2M
    if (new_min > alparser->min_id) {
1099
2.90M
        const uint64_t next_id = new_min;
1100
2.90M
        alparser->min_id = next_id;
1101
2.90M
        alparser->inspect_id[0] = MAX(alparser->inspect_id[0], next_id);
1102
2.90M
        alparser->inspect_id[1] = MAX(alparser->inspect_id[1], next_id);
1103
2.90M
        alparser->log_id = MAX(alparser->log_id, next_id);
1104
2.90M
        SCLogDebug("updated f->alparser->min_id %"PRIu64, alparser->min_id);
1105
2.90M
    }
1106
16.2M
    SCReturn;
1107
16.2M
}
1108
1109
static inline int StateGetProgressCompletionStatus(const AppProto alproto, const uint8_t flags)
1110
88.6M
{
1111
88.6M
    if (flags & STREAM_TOSERVER) {
1112
44.5M
        return alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].complete_ts;
1113
44.5M
    } else if (flags & STREAM_TOCLIENT) {
1114
44.0M
        return alp_ctx.ctxs[FLOW_PROTO_DEFAULT][alproto].complete_tc;
1115
44.0M
    } else {
1116
0
        DEBUG_VALIDATE_BUG_ON(1);
1117
0
        return 0;
1118
0
    }
1119
88.6M
}
1120
1121
/**
1122
 *  \brief get the progress value for a tx/protocol
1123
 *
1124
 *  If the stream is disrupted, we return the 'completion' value.
1125
 */
1126
int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto,
1127
                        void *alstate, uint8_t flags)
1128
2.92G
{
1129
2.92G
    SCEnter();
1130
2.92G
    int r;
1131
2.92G
    if (unlikely(IS_DISRUPTED(flags))) {
1132
5.17k
        r = StateGetProgressCompletionStatus(alproto, flags);
1133
2.92G
    } else {
1134
2.92G
        uint8_t direction = flags & (STREAM_TOCLIENT | STREAM_TOSERVER);
1135
2.92G
        r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetProgress(
1136
2.92G
                alstate, direction);
1137
2.92G
    }
1138
2.92G
    SCReturnInt(r);
1139
2.92G
}
1140
1141
uint64_t AppLayerParserGetTxCnt(const Flow *f, void *alstate)
1142
120M
{
1143
120M
    SCEnter();
1144
120M
    uint64_t r = alp_ctx.ctxs[f->protomap][f->alproto].StateGetTxCnt(alstate);
1145
120M
    SCReturnCT(r, "uint64_t");
1146
120M
}
1147
1148
void *AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
1149
87.5M
{
1150
87.5M
    SCEnter();
1151
87.5M
    void *r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetTx(alstate, tx_id);
1152
87.5M
    SCReturnPtr(r, "void *");
1153
87.5M
}
1154
1155
int AppLayerParserGetStateProgressCompletionStatus(AppProto alproto,
1156
                                                   uint8_t direction)
1157
88.6M
{
1158
88.6M
    SCEnter();
1159
88.6M
    int r = StateGetProgressCompletionStatus(alproto, direction);
1160
88.6M
    SCReturnInt(r);
1161
88.6M
}
1162
1163
int AppLayerParserGetEventInfo(uint8_t ipproto, AppProto alproto, const char *event_name,
1164
                    int *event_id, AppLayerEventType *event_type)
1165
94.7k
{
1166
94.7k
    SCEnter();
1167
94.7k
    const int ipproto_map = FlowGetProtoMapping(ipproto);
1168
94.7k
    int r = (alp_ctx.ctxs[ipproto_map][alproto].StateGetEventInfo == NULL) ?
1169
93.8k
                -1 : alp_ctx.ctxs[ipproto_map][alproto].StateGetEventInfo(event_name, event_id, event_type);
1170
94.7k
    SCReturnInt(r);
1171
94.7k
}
1172
1173
int AppLayerParserGetEventInfoById(uint8_t ipproto, AppProto alproto, int event_id,
1174
                    const char **event_name, AppLayerEventType *event_type)
1175
1.03M
{
1176
1.03M
    SCEnter();
1177
1.03M
    const int ipproto_map = FlowGetProtoMapping(ipproto);
1178
1.03M
    *event_name = (const char *)NULL;
1179
1.03M
    int r = (alp_ctx.ctxs[ipproto_map][alproto].StateGetEventInfoById == NULL) ?
1180
1.03M
                -1 : alp_ctx.ctxs[ipproto_map][alproto].StateGetEventInfoById(event_id, event_name, event_type);
1181
1.03M
    SCReturnInt(r);
1182
1.03M
}
1183
1184
uint8_t AppLayerParserGetFirstDataDir(uint8_t ipproto, AppProto alproto)
1185
276k
{
1186
276k
    SCEnter();
1187
276k
    uint8_t r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].first_data_dir;
1188
276k
    SCReturnCT(r, "uint8_t");
1189
276k
}
1190
1191
uint64_t AppLayerParserGetTransactionActive(const Flow *f,
1192
        AppLayerParserState *pstate, uint8_t direction)
1193
48.7k
{
1194
48.7k
    SCEnter();
1195
1196
48.7k
    uint64_t active_id;
1197
48.7k
    uint64_t log_id = pstate->log_id;
1198
48.7k
    uint64_t inspect_id = pstate->inspect_id[(direction & STREAM_TOSERVER) ? 0 : 1];
1199
48.7k
    if (alp_ctx.ctxs[f->protomap][f->alproto].logger == true) {
1200
44.5k
        active_id = MIN(log_id, inspect_id);
1201
44.5k
    } else {
1202
4.20k
        active_id = inspect_id;
1203
4.20k
    }
1204
1205
48.7k
    SCReturnCT(active_id, "uint64_t");
1206
48.7k
}
1207
1208
int AppLayerParserSupportsFiles(uint8_t ipproto, AppProto alproto)
1209
1.80M
{
1210
    // Custom case for only signature-only protocol so far
1211
1.80M
    if (alproto == ALPROTO_HTTP) {
1212
6.12k
        return AppLayerParserSupportsFiles(ipproto, ALPROTO_HTTP1) ||
1213
2
               AppLayerParserSupportsFiles(ipproto, ALPROTO_HTTP2);
1214
6.12k
    }
1215
1.79M
    if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxFiles != NULL)
1216
1.01M
        return TRUE;
1217
784k
    return FALSE;
1218
1.79M
}
1219
1220
AppLayerTxData *AppLayerParserGetTxData(uint8_t ipproto, AppProto alproto, void *tx)
1221
2.48G
{
1222
2.48G
    SCEnter();
1223
2.48G
    AppLayerTxData *d = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxData(tx);
1224
2.48G
    SCReturnPtr(d, "AppLayerTxData");
1225
2.48G
}
1226
1227
AppLayerStateData *AppLayerParserGetStateData(uint8_t ipproto, AppProto alproto, void *state)
1228
306k
{
1229
306k
    SCEnter();
1230
306k
    if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetStateData) {
1231
306k
        AppLayerStateData *d =
1232
306k
                alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetStateData(state);
1233
306k
        SCReturnPtr(d, "AppLayerStateData");
1234
306k
    }
1235
306k
    SCReturnPtr(NULL, "AppLayerStateData");
1236
306k
}
1237
1238
void AppLayerParserApplyTxConfig(uint8_t ipproto, AppProto alproto,
1239
        void *state, void *tx, enum ConfigAction mode, AppLayerTxConfig config)
1240
3
{
1241
3
    SCEnter();
1242
3
    const int ipproto_map = FlowGetProtoMapping(ipproto);
1243
3
    if (alp_ctx.ctxs[ipproto_map][alproto].ApplyTxConfig) {
1244
3
        alp_ctx.ctxs[ipproto_map][alproto].ApplyTxConfig(state, tx, mode, config);
1245
3
    }
1246
3
    SCReturn;
1247
3
}
1248
1249
/***** General *****/
1250
1251
static inline void SetEOFFlags(AppLayerParserState *pstate, const uint8_t flags)
1252
36.6M
{
1253
36.6M
    if ((flags & (STREAM_EOF|STREAM_TOSERVER)) == (STREAM_EOF|STREAM_TOSERVER)) {
1254
361k
        SCLogDebug("setting APP_LAYER_PARSER_EOF_TS");
1255
361k
        AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_EOF_TS);
1256
36.2M
    } else if ((flags & (STREAM_EOF|STREAM_TOCLIENT)) == (STREAM_EOF|STREAM_TOCLIENT)) {
1257
207k
        SCLogDebug("setting APP_LAYER_PARSER_EOF_TC");
1258
207k
        AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_EOF_TC);
1259
207k
    }
1260
36.6M
}
1261
1262
// if there is a stream frame, it should always be the first
1263
485k
#define FRAME_STREAM_ID 1
1264
1265
/** \internal
1266
 *  \brief create/close stream frames
1267
 *  On first invocation of TCP parser in a direction, create a <alproto>.stream frame.
1268
 *  On STREAM_EOF, set the final length. */
1269
static void HandleStreamFrames(Flow *f, StreamSlice stream_slice, const uint8_t *input,
1270
        const uint32_t input_len, const uint8_t flags)
1271
16.5M
{
1272
16.5M
    const uint8_t direction = (flags & STREAM_TOSERVER) ? 0 : 1;
1273
16.5M
    AppLayerParserState *pstate = f->alparser;
1274
1275
    /* setup the generic stream frame */
1276
16.5M
    if (((direction == 0 && (pstate->flags & APP_LAYER_PARSER_SFRAME_TS) == 0) ||
1277
14.0M
                (direction == 1 && (pstate->flags & APP_LAYER_PARSER_SFRAME_TC) == 0)) &&
1278
4.28M
            input != NULL && f->proto == IPPROTO_TCP) {
1279
329k
        Frame *frame = AppLayerFrameGetById(f, direction, FRAME_STREAM_ID);
1280
329k
        if (frame == NULL || frame->type != FRAME_STREAM_TYPE) {
1281
329k
            int64_t frame_len = -1;
1282
329k
            if (flags & STREAM_EOF)
1283
104k
                frame_len = input_len;
1284
1285
329k
            frame = AppLayerFrameNewByAbsoluteOffset(
1286
329k
                    f, &stream_slice, stream_slice.offset, frame_len, direction, FRAME_STREAM_TYPE);
1287
329k
            if (frame) {
1288
18.7k
                SCLogDebug("opened: frame %p id %" PRIi64, frame, frame->id);
1289
18.7k
                frame->flags = FRAME_FLAG_ENDS_AT_EOF; // TODO logic is not yet implemented
1290
18.7k
                DEBUG_VALIDATE_BUG_ON(
1291
18.7k
                        frame->id != 1); // should always be the first frame that is created
1292
18.7k
            }
1293
329k
            if (direction == 0) {
1294
193k
                pstate->flags |= APP_LAYER_PARSER_SFRAME_TS;
1295
193k
            } else {
1296
136k
                pstate->flags |= APP_LAYER_PARSER_SFRAME_TC;
1297
136k
            }
1298
329k
        }
1299
16.2M
    } else if (flags & STREAM_EOF) {
1300
155k
        Frame *frame = AppLayerFrameGetById(f, direction, FRAME_STREAM_ID);
1301
155k
        SCLogDebug("EOF closing: frame %p", frame);
1302
155k
        if (frame && frame->type == FRAME_STREAM_TYPE) {
1303
            /* calculate final frame length */
1304
3.87k
            int64_t slice_o = (int64_t)stream_slice.offset - (int64_t)frame->offset;
1305
3.87k
            int64_t frame_len = slice_o + (int64_t)input_len;
1306
3.87k
            SCLogDebug("%s: EOF frame->offset %" PRIu64 " -> %" PRIi64 ": o %" PRIi64,
1307
3.87k
                    AppProtoToString(f->alproto), frame->offset, frame_len, slice_o);
1308
3.87k
            frame->len = frame_len;
1309
3.87k
        }
1310
155k
    }
1311
16.5M
}
1312
1313
static void Setup(Flow *f, const uint8_t direction, const uint8_t *input, uint32_t input_len,
1314
        const uint8_t flags, StreamSlice *as)
1315
36.6M
{
1316
36.6M
    memset(as, 0, sizeof(*as));
1317
36.6M
    as->input = input;
1318
36.6M
    as->input_len = input_len;
1319
36.6M
    as->flags = flags;
1320
1321
36.6M
    if (f->proto == IPPROTO_TCP && f->protoctx != NULL) {
1322
27.7M
        TcpSession *ssn = f->protoctx;
1323
27.7M
        TcpStream *stream = (direction & STREAM_TOSERVER) ? &ssn->client : &ssn->server;
1324
27.7M
        as->offset = STREAM_APP_PROGRESS(stream);
1325
27.7M
    }
1326
36.6M
}
1327
1328
/** \retval int -1 in case of unrecoverable error. App-layer tracking stops for this flow.
1329
 *  \retval int 0 ok: we did not update app_progress
1330
 *  \retval int 1 ok: we updated app_progress */
1331
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto,
1332
                        uint8_t flags, const uint8_t *input, uint32_t input_len)
1333
16.7M
{
1334
16.7M
    SCEnter();
1335
16.7M
#ifdef DEBUG_VALIDATION
1336
16.7M
    BUG_ON(f->protomap != FlowGetProtoMapping(f->proto));
1337
16.7M
#endif
1338
16.7M
    AppLayerParserState *pstate = f->alparser;
1339
16.7M
    AppLayerParserProtoCtx *p = &alp_ctx.ctxs[f->protomap][alproto];
1340
16.7M
    StreamSlice stream_slice;
1341
16.7M
    void *alstate = NULL;
1342
16.7M
    uint64_t p_tx_cnt = 0;
1343
16.7M
    uint32_t consumed = input_len;
1344
16.7M
    const uint8_t direction = (flags & STREAM_TOSERVER) ? 0 : 1;
1345
1346
    /* we don't have the parser registered for this protocol */
1347
16.7M
    if (p->StateAlloc == NULL) {
1348
229k
        if (f->proto == IPPROTO_TCP) {
1349
5.32k
            StreamTcpDisableAppLayer(f);
1350
5.32k
        }
1351
229k
        goto end;
1352
229k
    }
1353
1354
16.5M
    if (flags & STREAM_GAP) {
1355
35.1k
        if (!(p->option_flags & APP_LAYER_PARSER_OPT_ACCEPT_GAPS)) {
1356
2.81k
            SCLogDebug("app-layer parser does not accept gaps");
1357
2.81k
            if (f->alstate != NULL && !FlowChangeProto(f)) {
1358
2.62k
                AppLayerParserStreamTruncated(pstate, f->proto, alproto, f->alstate, flags);
1359
2.62k
            }
1360
2.81k
            AppLayerIncGapErrorCounter(tv, f);
1361
2.81k
            goto error;
1362
2.81k
        }
1363
35.1k
    }
1364
1365
    /* Get the parser state (if any) */
1366
16.5M
    if (pstate == NULL) {
1367
284k
        f->alparser = pstate = AppLayerParserStateAlloc();
1368
284k
        if (pstate == NULL) {
1369
0
            AppLayerIncAllocErrorCounter(tv, f);
1370
0
            goto error;
1371
0
        }
1372
284k
    }
1373
1374
16.5M
    SetEOFFlags(pstate, flags);
1375
1376
16.5M
    alstate = f->alstate;
1377
16.5M
    if (alstate == NULL || FlowChangeProto(f)) {
1378
284k
        f->alstate = alstate = p->StateAlloc(alstate, f->alproto_orig);
1379
284k
        if (alstate == NULL) {
1380
0
            AppLayerIncAllocErrorCounter(tv, f);
1381
0
            goto error;
1382
0
        }
1383
284k
        SCLogDebug("alloced new app layer state %p (name %s)",
1384
284k
                   alstate, AppLayerGetProtoName(f->alproto));
1385
1386
        /* set flow flags to state */
1387
284k
        if (f->file_flags != 0) {
1388
72.4k
            AppLayerStateData *sd = AppLayerParserGetStateData(f->proto, f->alproto, f->alstate);
1389
72.4k
            if (sd != NULL) {
1390
72.4k
                if ((sd->file_flags & f->file_flags) != f->file_flags) {
1391
72.4k
                    SCLogDebug("state data: updating file_flags %04x with flow file_flags %04x",
1392
72.4k
                            sd->file_flags, f->file_flags);
1393
72.4k
                    sd->file_flags |= f->file_flags;
1394
72.4k
                }
1395
72.4k
            }
1396
72.4k
        }
1397
16.2M
    } else {
1398
16.2M
        SCLogDebug("using existing app layer state %p (name %s))",
1399
16.2M
                   alstate, AppLayerGetProtoName(f->alproto));
1400
16.2M
    }
1401
1402
16.5M
    p_tx_cnt = AppLayerParserGetTxCnt(f, f->alstate);
1403
1404
    /* invoke the recursive parser, but only on data. We may get empty msgs on EOF */
1405
16.5M
    if (input_len > 0 || (flags & STREAM_EOF)) {
1406
16.5M
        Setup(f, flags & (STREAM_TOSERVER | STREAM_TOCLIENT), input, input_len, flags,
1407
16.5M
                &stream_slice);
1408
16.5M
        HandleStreamFrames(f, stream_slice, input, input_len, flags);
1409
1410
#ifdef DEBUG
1411
        if (((stream_slice.flags & STREAM_TOSERVER) &&
1412
                    stream_slice.offset >= g_eps_applayer_error_offset_ts)) {
1413
            SCLogNotice("putting parser %s into an error state from toserver offset %" PRIu64,
1414
                    AppProtoToString(alproto), g_eps_applayer_error_offset_ts);
1415
            AppLayerIncParserErrorCounter(tv, f);
1416
            goto error;
1417
        }
1418
        if (((stream_slice.flags & STREAM_TOCLIENT) &&
1419
                    stream_slice.offset >= g_eps_applayer_error_offset_tc)) {
1420
            SCLogNotice("putting parser %s into an error state from toclient offset %" PRIu64,
1421
                    AppProtoToString(alproto), g_eps_applayer_error_offset_tc);
1422
            AppLayerIncParserErrorCounter(tv, f);
1423
            goto error;
1424
        }
1425
#endif
1426
        /* invoke the parser */
1427
16.5M
        AppLayerResult res = p->Parser[direction](f, alstate, pstate, stream_slice,
1428
16.5M
                alp_tctx->alproto_local_storage[f->protomap][alproto]);
1429
16.5M
        if (res.status < 0) {
1430
73.7k
            AppLayerIncParserErrorCounter(tv, f);
1431
73.7k
            goto error;
1432
16.4M
        } else if (res.status > 0) {
1433
8.08M
            DEBUG_VALIDATE_BUG_ON(res.consumed > input_len);
1434
8.08M
            DEBUG_VALIDATE_BUG_ON(res.needed + res.consumed < input_len);
1435
8.08M
            DEBUG_VALIDATE_BUG_ON(res.needed == 0);
1436
            /* incomplete is only supported for TCP */
1437
8.08M
            DEBUG_VALIDATE_BUG_ON(f->proto != IPPROTO_TCP);
1438
1439
            /* put protocol in error state on improper use of the
1440
             * return codes. */
1441
8.08M
            if (res.consumed > input_len || res.needed + res.consumed < input_len) {
1442
0
                AppLayerIncInternalErrorCounter(tv, f);
1443
0
                goto error;
1444
0
            }
1445
1446
8.08M
            if (f->proto == IPPROTO_TCP && f->protoctx != NULL) {
1447
8.08M
                TcpSession *ssn = f->protoctx;
1448
8.08M
                SCLogDebug("direction %d/%s", direction,
1449
8.08M
                        (flags & STREAM_TOSERVER) ? "toserver" : "toclient");
1450
8.08M
                if (direction == 0) {
1451
                    /* parser told us how much data it needs on top of what it
1452
                     * consumed. So we need tell stream engine how much we need
1453
                     * before the next call */
1454
3.87M
                    ssn->client.data_required = res.needed;
1455
3.87M
                    SCLogDebug("setting data_required %u", ssn->client.data_required);
1456
4.20M
                } else {
1457
                    /* parser told us how much data it needs on top of what it
1458
                     * consumed. So we need tell stream engine how much we need
1459
                     * before the next call */
1460
4.20M
                    ssn->server.data_required = res.needed;
1461
4.20M
                    SCLogDebug("setting data_required %u", ssn->server.data_required);
1462
4.20M
                }
1463
8.08M
            }
1464
8.08M
            consumed = res.consumed;
1465
8.08M
        }
1466
16.5M
    }
1467
1468
    /* set the packets to no inspection and reassembly if required */
1469
16.4M
    if (pstate->flags & APP_LAYER_PARSER_NO_INSPECTION) {
1470
32
        AppLayerParserSetEOF(pstate);
1471
1472
32
        if (f->proto == IPPROTO_TCP) {
1473
32
            StreamTcpDisableAppLayer(f);
1474
1475
            /* Set the no reassembly flag for both the stream in this TcpSession */
1476
32
            if (pstate->flags & APP_LAYER_PARSER_NO_REASSEMBLY) {
1477
                /* Used only if it's TCP */
1478
27
                TcpSession *ssn = f->protoctx;
1479
27
                if (ssn != NULL) {
1480
27
                    StreamTcpSetSessionNoReassemblyFlag(ssn, 0);
1481
27
                    StreamTcpSetSessionNoReassemblyFlag(ssn, 1);
1482
27
                }
1483
27
            }
1484
            /* Set the bypass flag for both the stream in this TcpSession */
1485
32
            if (pstate->flags & APP_LAYER_PARSER_BYPASS_READY) {
1486
                /* Used only if it's TCP */
1487
27
                TcpSession *ssn = f->protoctx;
1488
27
                if (ssn != NULL) {
1489
27
                    StreamTcpSetSessionBypassFlag(ssn);
1490
27
                }
1491
27
            }
1492
32
        } else {
1493
            // for TCP, this is set after flushing
1494
0
            FlowSetNoPayloadInspectionFlag(f);
1495
0
        }
1496
32
    }
1497
1498
    /* In cases like HeartBleed for TLS we need to inspect AppLayer but not Payload */
1499
16.4M
    if (!(f->flags & FLOW_NOPAYLOAD_INSPECTION) && pstate->flags & APP_LAYER_PARSER_NO_INSPECTION_PAYLOAD) {
1500
2.36k
        FlowSetNoPayloadInspectionFlag(f);
1501
        /* Set the no reassembly flag for both the stream in this TcpSession */
1502
2.36k
        if (f->proto == IPPROTO_TCP) {
1503
            /* Used only if it's TCP */
1504
2.36k
            TcpSession *ssn = f->protoctx;
1505
2.36k
            if (ssn != NULL) {
1506
2.36k
                StreamTcpSetDisableRawReassemblyFlag(ssn, 0);
1507
2.36k
                StreamTcpSetDisableRawReassemblyFlag(ssn, 1);
1508
2.36k
            }
1509
2.36k
        }
1510
2.36k
    }
1511
1512
    /* get the diff in tx cnt for stats keeping */
1513
16.4M
    uint64_t cur_tx_cnt = AppLayerParserGetTxCnt(f, f->alstate);
1514
16.4M
    if (cur_tx_cnt > p_tx_cnt && tv) {
1515
382k
        AppLayerIncTxCounter(tv, f, cur_tx_cnt - p_tx_cnt);
1516
382k
    }
1517
1518
    /* stream truncated, inform app layer */
1519
16.4M
    if (flags & STREAM_DEPTH)
1520
0
        AppLayerParserStreamTruncated(pstate, f->proto, alproto, f->alstate, flags);
1521
1522
16.6M
 end:
1523
    /* update app progress */
1524
16.6M
    if (consumed != input_len && f->proto == IPPROTO_TCP && f->protoctx != NULL) {
1525
8.08M
        TcpSession *ssn = f->protoctx;
1526
8.08M
        StreamTcpUpdateAppLayerProgress(ssn, direction, consumed);
1527
8.08M
        SCReturnInt(1);
1528
8.08M
    }
1529
1530
16.6M
    SCReturnInt(0);
1531
76.5k
 error:
1532
    /* Set the no app layer inspection flag for both
1533
     * the stream in this Flow */
1534
76.5k
    if (f->proto == IPPROTO_TCP) {
1535
28.9k
        StreamTcpDisableAppLayer(f);
1536
28.9k
    }
1537
76.5k
    AppLayerParserSetEOF(pstate);
1538
76.5k
    SCReturnInt(-1);
1539
16.6M
}
1540
1541
void AppLayerParserSetEOF(AppLayerParserState *pstate)
1542
245k
{
1543
245k
    SCEnter();
1544
1545
245k
    if (pstate == NULL)
1546
300
        goto end;
1547
1548
244k
    SCLogDebug("setting APP_LAYER_PARSER_EOF_TC and APP_LAYER_PARSER_EOF_TS");
1549
244k
    AppLayerParserStateSetFlag(pstate, (APP_LAYER_PARSER_EOF_TS|APP_LAYER_PARSER_EOF_TC));
1550
1551
245k
 end:
1552
245k
    SCReturn;
1553
244k
}
1554
1555
/* return true if there are app parser decoder events. These are
1556
 * only the ones that are set during protocol detection. */
1557
bool AppLayerParserHasDecoderEvents(AppLayerParserState *pstate)
1558
25.8M
{
1559
25.8M
    SCEnter();
1560
1561
25.8M
    if (pstate == NULL)
1562
4.07M
        return false;
1563
1564
21.7M
    const AppLayerDecoderEvents *decoder_events = AppLayerParserGetDecoderEvents(pstate);
1565
21.7M
    if (decoder_events && decoder_events->cnt)
1566
0
        return true;
1567
1568
    /* if we have reached here, we don't have events */
1569
21.7M
    return false;
1570
21.7M
}
1571
1572
/** \brief simple way to globally test if a alproto is registered
1573
 *         and fully enabled in the configuration.
1574
 */
1575
int AppLayerParserIsEnabled(AppProto alproto)
1576
86
{
1577
104
    for (int i = 0; i < FLOW_PROTO_APPLAYER_MAX; i++) {
1578
104
        if (alp_ctx.ctxs[i][alproto].StateGetProgress != NULL) {
1579
86
            return 1;
1580
86
        }
1581
104
    }
1582
0
    return 0;
1583
86
}
1584
1585
int AppLayerParserProtocolHasLogger(uint8_t ipproto, AppProto alproto)
1586
84
{
1587
84
    SCEnter();
1588
84
    int ipproto_map = FlowGetProtoMapping(ipproto);
1589
84
    int r = (alp_ctx.ctxs[ipproto_map][alproto].logger == false) ? 0 : 1;
1590
84
    SCReturnInt(r);
1591
84
}
1592
1593
LoggerId AppLayerParserProtocolGetLoggerBits(uint8_t ipproto, AppProto alproto)
1594
42.8M
{
1595
42.8M
    SCEnter();
1596
42.8M
    const int ipproto_map = FlowGetProtoMapping(ipproto);
1597
42.8M
    LoggerId r = alp_ctx.ctxs[ipproto_map][alproto].logger_bits;
1598
42.8M
    SCReturnUInt(r);
1599
42.8M
}
1600
1601
void AppLayerParserTriggerRawStreamReassembly(Flow *f, int direction)
1602
10.3M
{
1603
10.3M
    SCEnter();
1604
1605
10.3M
    SCLogDebug("f %p tcp %p direction %d", f, f ? f->protoctx : NULL, direction);
1606
10.3M
    if (f != NULL && f->protoctx != NULL)
1607
10.3M
        StreamTcpReassembleTriggerRawReassembly(f->protoctx, direction);
1608
1609
10.3M
    SCReturn;
1610
10.3M
}
1611
1612
void AppLayerParserSetStreamDepth(uint8_t ipproto, AppProto alproto, uint32_t stream_depth)
1613
34
{
1614
34
    SCEnter();
1615
1616
34
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].stream_depth = stream_depth;
1617
34
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].internal_flags |=
1618
34
        APP_LAYER_PARSER_INT_STREAM_DEPTH_SET;
1619
1620
34
    SCReturn;
1621
34
}
1622
1623
uint32_t AppLayerParserGetStreamDepth(const Flow *f)
1624
246k
{
1625
246k
    SCReturnInt(alp_ctx.ctxs[f->protomap][f->alproto].stream_depth);
1626
246k
}
1627
1628
void AppLayerParserSetStreamDepthFlag(uint8_t ipproto, AppProto alproto, void *state, uint64_t tx_id, uint8_t flags)
1629
36.7k
{
1630
36.7k
    SCEnter();
1631
36.7k
    void *tx = NULL;
1632
36.7k
    if (state != NULL) {
1633
36.7k
        if ((tx = AppLayerParserGetTx(ipproto, alproto, state, tx_id)) != NULL) {
1634
36.7k
            if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetStreamDepthFlag != NULL) {
1635
32.4k
                alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetStreamDepthFlag(tx, flags);
1636
32.4k
            }
1637
36.7k
        }
1638
36.7k
    }
1639
36.7k
    SCReturn;
1640
36.7k
}
1641
1642
int AppLayerParserGetFrameIdByName(uint8_t ipproto, AppProto alproto, const char *name)
1643
44.6k
{
1644
44.6k
    if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetFrameIdByName != NULL) {
1645
42.5k
        return alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetFrameIdByName(name);
1646
42.5k
    } else {
1647
2.11k
        return -1;
1648
2.11k
    }
1649
44.6k
}
1650
1651
const char *AppLayerParserGetFrameNameById(uint8_t ipproto, AppProto alproto, const uint8_t id)
1652
50.6k
{
1653
50.6k
    if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetFrameNameById != NULL) {
1654
50.6k
        return alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetFrameNameById(id);
1655
50.6k
    } else {
1656
0
        return NULL;
1657
0
    }
1658
50.6k
}
1659
1660
/***** Cleanup *****/
1661
1662
void AppLayerParserStateProtoCleanup(
1663
        uint8_t protomap, AppProto alproto, void *alstate, AppLayerParserState *pstate)
1664
960k
{
1665
960k
    SCEnter();
1666
1667
960k
    AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[protomap][alproto];
1668
1669
960k
    if (ctx->StateFree != NULL && alstate != NULL)
1670
656k
        ctx->StateFree(alstate);
1671
1672
    /* free the app layer parser api state */
1673
960k
    if (pstate != NULL)
1674
656k
        AppLayerParserStateFree(pstate);
1675
1676
960k
    SCReturn;
1677
960k
}
1678
1679
void AppLayerParserStateCleanup(const Flow *f, void *alstate, AppLayerParserState *pstate)
1680
955k
{
1681
955k
    AppLayerParserStateProtoCleanup(f->protomap, f->alproto, alstate, pstate);
1682
955k
}
1683
1684
static void ValidateParserProtoDump(AppProto alproto, uint8_t ipproto)
1685
0
{
1686
0
    uint8_t map = FlowGetProtoMapping(ipproto);
1687
0
    const AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[map][alproto];
1688
0
    printf("ERROR: incomplete app-layer registration\n");
1689
0
    printf("AppLayer protocol %s ipproto %u\n", AppProtoToString(alproto), ipproto);
1690
0
    printf("- option flags %"PRIx32"\n", ctx->option_flags);
1691
0
    printf("- first_data_dir %"PRIx8"\n", ctx->first_data_dir);
1692
0
    printf("Mandatory:\n");
1693
0
    printf("- Parser[0] %p Parser[1] %p\n", ctx->Parser[0], ctx->Parser[1]);
1694
0
    printf("- StateAlloc %p StateFree %p\n", ctx->StateAlloc, ctx->StateFree);
1695
0
    printf("- StateGetTx %p StateGetTxCnt %p StateTransactionFree %p\n",
1696
0
            ctx->StateGetTx, ctx->StateGetTxCnt, ctx->StateTransactionFree);
1697
0
    printf("- GetTxData %p\n", ctx->GetTxData);
1698
0
    printf("- GetStateData %p\n", ctx->GetStateData);
1699
0
    printf("- StateGetProgress %p\n", ctx->StateGetProgress);
1700
0
    printf("Optional:\n");
1701
0
    printf("- LocalStorageAlloc %p LocalStorageFree %p\n", ctx->LocalStorageAlloc, ctx->LocalStorageFree);
1702
0
    printf("- StateGetEventInfo %p StateGetEventInfoById %p\n", ctx->StateGetEventInfo,
1703
0
            ctx->StateGetEventInfoById);
1704
0
}
1705
1706
5.57k
#define BOTH_SET(a, b) ((a) != NULL && (b) != NULL)
1707
2.78k
#define BOTH_SET_OR_BOTH_UNSET(a, b) (((a) == NULL && (b) == NULL) || ((a) != NULL && (b) != NULL))
1708
#define THREE_SET_OR_THREE_UNSET(a, b, c) (((a) == NULL && (b) == NULL && (c) == NULL) || ((a) != NULL && (b) != NULL && (c) != NULL))
1709
2.78k
#define THREE_SET(a, b, c) ((a) != NULL && (b) != NULL && (c) != NULL)
1710
1711
static void ValidateParserProto(AppProto alproto, uint8_t ipproto)
1712
5.58k
{
1713
5.58k
    uint8_t map = FlowGetProtoMapping(ipproto);
1714
5.58k
    const AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[map][alproto];
1715
1716
5.58k
    if (ctx->Parser[0] == NULL && ctx->Parser[1] == NULL)
1717
2.79k
        return;
1718
1719
2.78k
    if (!(BOTH_SET(ctx->Parser[0], ctx->Parser[1]))) {
1720
0
        goto bad;
1721
0
    }
1722
2.78k
    if (!(BOTH_SET(ctx->StateFree, ctx->StateAlloc))) {
1723
0
        goto bad;
1724
0
    }
1725
2.78k
    if (!(THREE_SET(ctx->StateGetTx, ctx->StateGetTxCnt, ctx->StateTransactionFree))) {
1726
0
        goto bad;
1727
0
    }
1728
2.78k
    if (ctx->StateGetProgress == NULL) {
1729
0
        goto bad;
1730
0
    }
1731
    /* local storage is optional, but needs both set if used */
1732
2.78k
    if (!(BOTH_SET_OR_BOTH_UNSET(ctx->LocalStorageAlloc, ctx->LocalStorageFree))) {
1733
0
        goto bad;
1734
0
    }
1735
2.78k
    if (ctx->GetTxData == NULL) {
1736
0
        goto bad;
1737
0
    }
1738
2.78k
    if (ctx->GetStateData == NULL) {
1739
0
        goto bad;
1740
0
    }
1741
2.78k
    return;
1742
2.78k
bad:
1743
0
    ValidateParserProtoDump(alproto, ipproto);
1744
0
    exit(EXIT_FAILURE);
1745
2.78k
}
1746
#undef BOTH_SET
1747
#undef BOTH_SET_OR_BOTH_UNSET
1748
#undef THREE_SET_OR_THREE_UNSET
1749
#undef THREE_SET
1750
1751
static void ValidateParser(AppProto alproto)
1752
2.79k
{
1753
2.79k
    ValidateParserProto(alproto, IPPROTO_TCP);
1754
2.79k
    ValidateParserProto(alproto, IPPROTO_UDP);
1755
2.79k
}
1756
1757
static void ValidateParsers(void)
1758
74
{
1759
74
    AppProto p = 0;
1760
2.86k
    for ( ; p < ALPROTO_MAX; p++) {
1761
2.79k
        ValidateParser(p);
1762
2.79k
    }
1763
74
}
1764
1765
void AppLayerParserRegisterProtocolParsers(void)
1766
34
{
1767
34
    SCEnter();
1768
1769
34
    AppLayerConfig();
1770
1771
34
    RegisterHTPParsers();
1772
34
    RegisterSSLParsers();
1773
34
    rs_dcerpc_register_parser();
1774
34
    rs_dcerpc_udp_register_parser();
1775
34
    RegisterSMBParsers();
1776
34
    RegisterFTPParsers();
1777
34
    RegisterSSHParsers();
1778
34
    RegisterSMTPParsers();
1779
34
    rs_dns_udp_register_parser();
1780
34
    rs_dns_tcp_register_parser();
1781
34
    rs_bittorrent_dht_udp_register_parser();
1782
34
    RegisterModbusParsers();
1783
34
    RegisterENIPUDPParsers();
1784
34
    RegisterENIPTCPParsers();
1785
34
    RegisterDNP3Parsers();
1786
34
    RegisterNFSTCPParsers();
1787
34
    RegisterNFSUDPParsers();
1788
34
    RegisterNTPParsers();
1789
34
    RegisterTFTPParsers();
1790
34
    RegisterIKEParsers();
1791
34
    RegisterKRB5Parsers();
1792
34
    rs_dhcp_register_parser();
1793
34
    RegisterSNMPParsers();
1794
34
    RegisterSIPParsers();
1795
34
    RegisterQuicParsers();
1796
34
    rs_template_register_parser();
1797
34
    RegisterRFBParsers();
1798
34
    RegisterMQTTParsers();
1799
34
    SCRegisterPgsqlParser();
1800
34
    RegisterRdpParsers();
1801
34
    RegisterHTTP2Parsers();
1802
34
    rs_telnet_register_parser();
1803
1804
    /** IMAP */
1805
34
    AppLayerProtoDetectRegisterProtocol(ALPROTO_IMAP, "imap");
1806
34
    if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", "imap")) {
1807
34
        if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_IMAP,
1808
34
                                  "1|20|capability", 12, 0, STREAM_TOSERVER) < 0)
1809
0
        {
1810
0
            SCLogInfo("imap proto registration failure");
1811
0
            exit(EXIT_FAILURE);
1812
0
        }
1813
34
    } else {
1814
0
        SCLogInfo("Protocol detection and parser disabled for %s protocol.",
1815
0
                  "imap");
1816
0
    }
1817
1818
34
    ValidateParsers();
1819
34
    return;
1820
34
}
1821
1822
1823
/* coccinelle: AppLayerParserStateSetFlag():2,2:APP_LAYER_PARSER_ */
1824
void AppLayerParserStateSetFlag(AppLayerParserState *pstate, uint16_t flag)
1825
433k
{
1826
433k
    SCEnter();
1827
433k
    pstate->flags |= flag;
1828
433k
    SCReturn;
1829
433k
}
1830
1831
/* coccinelle: AppLayerParserStateIssetFlag():2,2:APP_LAYER_PARSER_ */
1832
uint16_t AppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint16_t flag)
1833
27.6M
{
1834
27.6M
    SCEnter();
1835
27.6M
    SCReturnUInt(pstate->flags & flag);
1836
27.6M
}
1837
1838
static inline void AppLayerParserStreamTruncated(AppLayerParserState *pstate, const uint8_t ipproto,
1839
        const AppProto alproto, void *alstate, const uint8_t direction)
1840
2.62k
{
1841
2.62k
    SCEnter();
1842
1843
2.62k
    if (direction & STREAM_TOSERVER) {
1844
1.51k
        AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_TRUNC_TS);
1845
1.51k
    } else {
1846
1.10k
        AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_TRUNC_TC);
1847
1.10k
    }
1848
1849
2.62k
    if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].Truncate != NULL) {
1850
0
        alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].Truncate(alstate, direction);
1851
0
    }
1852
1853
2.62k
    SCReturn;
1854
2.62k
}
1855
1856
#ifdef DEBUG
1857
void AppLayerParserStatePrintDetails(AppLayerParserState *pstate)
1858
{
1859
    SCEnter();
1860
1861
    if (pstate == NULL)
1862
        SCReturn;
1863
1864
    AppLayerParserState *p = pstate;
1865
    SCLogDebug("AppLayerParser parser state information for parser state p(%p). "
1866
               "p->inspect_id[0](%"PRIu64"), "
1867
               "p->inspect_id[1](%"PRIu64"), "
1868
               "p->log_id(%"PRIu64"), "
1869
               "p->decoder_events(%p).",
1870
               pstate, p->inspect_id[0], p->inspect_id[1], p->log_id,
1871
               p->decoder_events);
1872
1873
    SCReturn;
1874
}
1875
#endif
1876
1877
/***** Unittests *****/
1878
1879
#ifdef UNITTESTS
1880
#include "util-unittest-helper.h"
1881
1882
static AppLayerParserCtx alp_ctx_backup_unittest;
1883
1884
typedef struct TestState_ {
1885
    uint8_t test;
1886
} TestState;
1887
1888
/**
1889
 *  \brief  Test parser function to test the memory deallocation of app layer
1890
 *          parser of occurrence of an error.
1891
 */
1892
static AppLayerResult TestProtocolParser(Flow *f, void *test_state, AppLayerParserState *pstate,
1893
        StreamSlice stream_slice, void *local_data)
1894
{
1895
    SCEnter();
1896
    SCReturnStruct(APP_LAYER_ERROR);
1897
}
1898
1899
/** \brief Function to allocates the Test protocol state memory
1900
 */
1901
static void *TestProtocolStateAlloc(void *orig_state, AppProto proto_orig)
1902
{
1903
    SCEnter();
1904
    void *s = SCMalloc(sizeof(TestState));
1905
    if (unlikely(s == NULL))
1906
        goto end;
1907
    memset(s, 0, sizeof(TestState));
1908
 end:
1909
    SCReturnPtr(s, "TestState");
1910
}
1911
1912
/** \brief Function to free the Test Protocol state memory
1913
 */
1914
static void TestProtocolStateFree(void *s)
1915
{
1916
    SCFree(s);
1917
}
1918
1919
static uint64_t TestGetTxCnt(void *state)
1920
{
1921
    /* single tx */
1922
    return 1;
1923
}
1924
1925
static void TestStateTransactionFree(void *state, uint64_t tx_id)
1926
{
1927
    /* do nothing */
1928
}
1929
1930
static void *TestGetTx(void *state, uint64_t tx_id)
1931
{
1932
    TestState *test_state = (TestState *)state;
1933
    return test_state;
1934
}
1935
1936
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto,
1937
                                  void (*RegisterUnittests)(void))
1938
{
1939
    SCEnter();
1940
    alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
1941
        RegisterUnittests = RegisterUnittests;
1942
    SCReturn;
1943
}
1944
1945
void AppLayerParserBackupParserTable(void)
1946
{
1947
    SCEnter();
1948
    alp_ctx_backup_unittest = alp_ctx;
1949
    memset(&alp_ctx, 0, sizeof(alp_ctx));
1950
    SCReturn;
1951
}
1952
1953
void AppLayerParserRestoreParserTable(void)
1954
{
1955
    SCEnter();
1956
    alp_ctx = alp_ctx_backup_unittest;
1957
    memset(&alp_ctx_backup_unittest, 0, sizeof(alp_ctx_backup_unittest));
1958
    SCReturn;
1959
}
1960
1961
/**
1962
 * \test Test the deallocation of app layer parser memory on occurrence of
1963
 *       error in the parsing process.
1964
 */
1965
static int AppLayerParserTest01(void)
1966
{
1967
    AppLayerParserBackupParserTable();
1968
1969
    Flow *f = NULL;
1970
    uint8_t testbuf[] = { 0x11 };
1971
    uint32_t testlen = sizeof(testbuf);
1972
    TcpSession ssn;
1973
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1974
1975
    memset(&ssn, 0, sizeof(ssn));
1976
1977
    /* Register the Test protocol state and parser functions */
1978
    AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_TEST, STREAM_TOSERVER, TestProtocolParser);
1979
    AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_TEST,
1980
                          TestProtocolStateAlloc, TestProtocolStateFree);
1981
    AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_TEST, TestStateTransactionFree);
1982
    AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_TEST, TestGetTx);
1983
    AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_TEST, TestGetTxCnt);
1984
1985
    f = UTHBuildFlow(AF_INET, "1.2.3.4", "4.3.2.1", 20, 40);
1986
    FAIL_IF_NULL(f);
1987
    f->protoctx = &ssn;
1988
    f->alproto = ALPROTO_TEST;
1989
    f->proto = IPPROTO_TCP;
1990
1991
    StreamTcpInitConfig(true);
1992
1993
    int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_TEST,
1994
                                STREAM_TOSERVER | STREAM_EOF, testbuf,
1995
                                testlen);
1996
    FAIL_IF(r != -1);
1997
1998
    FAIL_IF(!(ssn.flags & STREAMTCP_FLAG_APP_LAYER_DISABLED));
1999
2000
    AppLayerParserRestoreParserTable();
2001
    StreamTcpFreeConfig(true);
2002
    UTHFreeFlow(f);
2003
    PASS;
2004
}
2005
2006
/**
2007
 * \test Test the deallocation of app layer parser memory on occurrence of
2008
 *       error in the parsing process for UDP.
2009
 */
2010
static int AppLayerParserTest02(void)
2011
{
2012
    AppLayerParserBackupParserTable();
2013
2014
    Flow *f = NULL;
2015
    uint8_t testbuf[] = { 0x11 };
2016
    uint32_t testlen = sizeof(testbuf);
2017
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
2018
2019
    /* Register the Test protocol state and parser functions */
2020
    AppLayerParserRegisterParser(IPPROTO_UDP, ALPROTO_TEST, STREAM_TOSERVER,
2021
                      TestProtocolParser);
2022
    AppLayerParserRegisterStateFuncs(IPPROTO_UDP, ALPROTO_TEST,
2023
                          TestProtocolStateAlloc, TestProtocolStateFree);
2024
    AppLayerParserRegisterTxFreeFunc(IPPROTO_UDP, ALPROTO_TEST, TestStateTransactionFree);
2025
    AppLayerParserRegisterGetTx(IPPROTO_UDP, ALPROTO_TEST, TestGetTx);
2026
    AppLayerParserRegisterGetTxCnt(IPPROTO_UDP, ALPROTO_TEST, TestGetTxCnt);
2027
2028
    f = UTHBuildFlow(AF_INET, "1.2.3.4", "4.3.2.1", 20, 40);
2029
    FAIL_IF_NULL(f);
2030
    f->alproto = ALPROTO_TEST;
2031
    f->proto = IPPROTO_UDP;
2032
    f->protomap = FlowGetProtoMapping(f->proto);
2033
2034
    StreamTcpInitConfig(true);
2035
2036
    int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_TEST,
2037
                                STREAM_TOSERVER | STREAM_EOF, testbuf,
2038
                                testlen);
2039
    FAIL_IF(r != -1);
2040
2041
    AppLayerParserRestoreParserTable();
2042
    StreamTcpFreeConfig(true);
2043
    UTHFreeFlow(f);
2044
    PASS;
2045
}
2046
2047
2048
void AppLayerParserRegisterUnittests(void)
2049
{
2050
    SCEnter();
2051
2052
    int ip;
2053
    AppProto alproto;
2054
    AppLayerParserProtoCtx *ctx;
2055
2056
    for (ip = 0; ip < FLOW_PROTO_DEFAULT; ip++) {
2057
        for (alproto = 0; alproto < ALPROTO_MAX; alproto++) {
2058
            ctx = &alp_ctx.ctxs[ip][alproto];
2059
            if (ctx->RegisterUnittests == NULL)
2060
                continue;
2061
            ctx->RegisterUnittests();
2062
        }
2063
    }
2064
2065
    UtRegisterTest("AppLayerParserTest01", AppLayerParserTest01);
2066
    UtRegisterTest("AppLayerParserTest02", AppLayerParserTest02);
2067
2068
    SCReturn;
2069
}
2070
2071
#endif