• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OISF / suricata / 22712336922

05 Mar 2026 09:55AM UTC coverage: 66.796% (-12.5%) from 79.283%
22712336922

Pull #14946

github

web-flow
Merge 91559149c into 7e97dfd52
Pull Request #14946: Stack 8001 v15

14 of 19 new or added lines in 7 files covered. (73.68%)

11298 existing lines in 298 files now uncovered.

155282 of 232473 relevant lines covered (66.8%)

5923441.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.82
/src/app-layer-parser.c
1
/* Copyright (C) 2007-2026 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
#include "app-layer-events.h"
35

36
#include "stream-tcp.h"
37

38
#include "util-validate.h"
39
#include "util-config.h"
40

41
#include "app-layer.h"
42
#include "app-layer-detect-proto.h"
43

44
#include "app-layer-ftp.h"
45
#include "app-layer-smtp.h"
46

47
#include "app-layer-smb.h"
48
#include "app-layer-htp.h"
49
#include "app-layer-ssl.h"
50
#include "app-layer-ssh.h"
51
#include "app-layer-modbus.h"
52
#include "app-layer-dnp3.h"
53
#include "app-layer-nfs-tcp.h"
54
#include "app-layer-nfs-udp.h"
55
#include "app-layer-tftp.h"
56
#include "app-layer-ike.h"
57
#include "app-layer-http2.h"
58
#include "app-layer-imap.h"
59

60
struct AppLayerParserThreadCtx_ {
61
    void *(*alproto_local_storage)[FLOW_PROTO_MAX];
62
};
63

64

65
/**
66
 * \brief App layer protocol parser context.
67
 */
68
typedef struct AppLayerParserProtoCtx_
69
{
70
    /* 0 - to_server, 1 - to_client. */
71
    AppLayerParserFPtr Parser[2];
72

73
    bool logger;
74

75
    /* Indicates the direction the parser is ready to see the data
76
     * the first time for a flow.  Values accepted -
77
     * STREAM_TOSERVER, STREAM_TOCLIENT */
78
    uint8_t first_data_dir;
79

80
    uint32_t logger_bits;   /**< registered loggers for this proto */
81

82
    void *(*StateAlloc)(void *, AppProto);
83
    void (*StateFree)(void *);
84
    void (*StateTransactionFree)(void *, uint64_t);
85
    void *(*LocalStorageAlloc)(void);
86
    void (*LocalStorageFree)(void *);
87

88
    /** get FileContainer reference from the TX. MUST return a non-NULL reference if the TX
89
     *  has or may have files in the requested direction at some point. */
90
    AppLayerGetFileState (*GetTxFiles)(void *, uint8_t);
91

92
    int (*StateGetProgress)(void *alstate, uint8_t direction);
93
    uint64_t (*StateGetTxCnt)(void *alstate);
94
    void *(*StateGetTx)(void *alstate, uint64_t tx_id);
95
    AppLayerGetTxIteratorFunc StateGetTxIterator;
96
    int complete_ts;
97
    int complete_tc;
98
    int (*StateGetEventInfoById)(
99
            uint8_t event_id, const char **event_name, AppLayerEventType *event_type);
100
    int (*StateGetEventInfo)(
101
            const char *event_name, uint8_t *event_id, AppLayerEventType *event_type);
102

103
    AppLayerStateData *(*GetStateData)(void *state);
104
    AppLayerTxData *(*GetTxData)(void *tx);
105
    void (*ApplyTxConfig)(void *state, void *tx, int mode, AppLayerTxConfig);
106

107
    void (*SetStreamDepthFlag)(void *tx, uint8_t flags);
108

109
    AppLayerParserGetFrameIdByNameFn GetFrameIdByName;
110
    AppLayerParserGetFrameNameByIdFn GetFrameNameById;
111

112
    AppLayerParserGetStateIdByNameFn GetStateIdByName;
113
    AppLayerParserGetStateNameByIdFn GetStateNameById;
114

115
    /* each app-layer has its own value */
116
    uint32_t stream_depth;
117

118
    /* Option flags such as supporting gaps or not. */
119
    uint32_t option_flags;
120
    /* coccinelle: AppLayerParserProtoCtx:option_flags:APP_LAYER_PARSER_OPT_ */
121

122
    uint32_t internal_flags;
123
    /* coccinelle: AppLayerParserProtoCtx:internal_flags:APP_LAYER_PARSER_INT_ */
124

125
#ifdef UNITTESTS
126
    void (*RegisterUnittests)(void);
127
#endif
128
} AppLayerParserProtoCtx;
129

130
typedef struct AppLayerParserCtx_ {
131
    AppLayerParserProtoCtx (*ctxs)[FLOW_PROTO_MAX];
132
    size_t ctxs_len;
133
} AppLayerParserCtx;
134

135
struct AppLayerParserState_ {
136
    /* coccinelle: AppLayerParserState:flags:APP_LAYER_PARSER_ */
137
    uint16_t flags;
138

139
    /* Indicates the current transaction that is being inspected.
140
     * We have a var per direction. */
141
    uint64_t inspect_id[2];
142
    /* Indicates the current transaction being logged.  Unlike inspect_id,
143
     * we don't need a var per direction since we don't log a transaction
144
     * unless we have the entire transaction. */
145
    uint64_t log_id;
146

147
    uint64_t min_id;
148

149
    /* Used to store decoder events. */
150
    AppLayerDecoderEvents *decoder_events;
151

152
    FramesContainer *frames;
153
};
154

155
enum ExceptionPolicy g_applayerparser_error_policy = EXCEPTION_POLICY_NOT_SET;
156

157
static void AppLayerConfig(void)
158
{
2,181✔
159
    g_applayerparser_error_policy = ExceptionPolicyParse("app-layer.error-policy", true);
2,181✔
160
}
2,181✔
161

162
enum ExceptionPolicy AppLayerErrorGetExceptionPolicy(void)
163
{
622✔
164
    return g_applayerparser_error_policy;
622✔
165
}
622✔
166

167
static void AppLayerParserFramesFreeContainer(FramesContainer *frames)
168
{
47,402✔
169
    if (frames != NULL) {
47,402✔
170
        FramesFree(&frames->toserver);
27,648✔
171
        FramesFree(&frames->toclient);
27,648✔
172
        SCFree(frames);
27,648✔
173
    }
27,648✔
174
}
47,402✔
175

176
void AppLayerFramesFreeContainer(Flow *f)
177
{
1,857✔
178
    if (f == NULL || f->alparser == NULL || f->alparser->frames == NULL)
1,857✔
179
        return;
×
180
    AppLayerParserFramesFreeContainer(f->alparser->frames);
1,857✔
181
    f->alparser->frames = NULL;
1,857✔
182
}
1,857✔
183

184
FramesContainer *AppLayerFramesGetContainer(const Flow *f)
185
{
4,965,713✔
186
    if (f == NULL || f->alparser == NULL)
4,965,943✔
187
        return NULL;
189,235✔
188
    return f->alparser->frames;
4,776,478✔
189
}
4,965,713✔
190

191
FramesContainer *AppLayerFramesSetupContainer(Flow *f)
192
{
1,247,093✔
193
#ifdef UNITTESTS
194
    if (f == NULL || f->alparser == NULL || (f->proto == IPPROTO_TCP && f->protoctx == NULL))
195
        return NULL;
196
#endif
197
    DEBUG_VALIDATE_BUG_ON(f == NULL || f->alparser == NULL);
1,247,093✔
198
    if (f->alparser->frames == NULL) {
1,247,093✔
199
        f->alparser->frames = SCCalloc(1, sizeof(FramesContainer));
27,648✔
200
        if (f->alparser->frames == NULL) {
27,648✔
201
            return NULL;
×
202
        }
×
203
#ifdef DEBUG
204
        f->alparser->frames->toserver.ipproto = f->proto;
205
        f->alparser->frames->toserver.alproto = f->alproto;
206
        f->alparser->frames->toclient.ipproto = f->proto;
207
        f->alparser->frames->toclient.alproto = f->alproto;
208
#endif
209
    }
27,648✔
210
    return f->alparser->frames;
1,247,093✔
211
}
1,247,093✔
212

213
#ifdef UNITTESTS
214
void UTHAppLayerParserStateGetIds(void *ptr, uint64_t *i1, uint64_t *i2, uint64_t *log, uint64_t *min)
215
{
216
    struct AppLayerParserState_ *s = ptr;
217
    *i1 = s->inspect_id[0];
218
    *i2 = s->inspect_id[1];
219
    *log = s->log_id;
220
    *min = s->min_id;
221
}
222
#endif
223

224
/* Static global version of the parser context.
225
 * Post 2.0 let's look at changing this to move it out to app-layer.c. */
226
static AppLayerParserCtx alp_ctx;
227

228
int AppLayerParserProtoIsRegistered(uint8_t ipproto, AppProto alproto)
229
{
819,014✔
230
    uint8_t ipproto_map = FlowGetProtoMapping(ipproto);
819,014✔
231

232
    return (alp_ctx.ctxs[alproto][ipproto_map].StateAlloc != NULL) ? 1 : 0;
819,014✔
233
}
819,014✔
234

235
AppLayerParserState *AppLayerParserStateAlloc(void)
236
{
45,536✔
237
    SCEnter();
45,536✔
238

239
    AppLayerParserState *pstate = (AppLayerParserState *)SCCalloc(1, sizeof(*pstate));
45,536✔
240
    if (pstate == NULL)
45,536✔
241
        goto end;
×
242

243
 end:
45,537✔
244
    SCReturnPtr(pstate, "AppLayerParserState");
45,536✔
245
}
45,536✔
246

247
void AppLayerParserStateFree(AppLayerParserState *pstate)
248
{
45,545✔
249
    SCEnter();
45,545✔
250

251
    if (pstate->decoder_events != NULL)
45,545✔
252
        SCAppLayerDecoderEventsFreeEvents(&pstate->decoder_events);
×
253
    AppLayerParserFramesFreeContainer(pstate->frames);
45,545✔
254
    SCFree(pstate);
45,545✔
255

256
    SCReturn;
45,545✔
257
}
45,545✔
258

259
int AppLayerParserSetup(void)
260
{
2,181✔
261
    SCEnter();
2,181✔
262
    // initial allocation that will later be grown using realloc,
263
    // when new protocols register themselves and make g_alproto_max grow
264
    alp_ctx.ctxs = SCCalloc(g_alproto_max, sizeof(AppLayerParserProtoCtx[FLOW_PROTO_MAX]));
2,181✔
265
    if (unlikely(alp_ctx.ctxs == NULL)) {
2,181✔
266
        FatalError("Unable to alloc alp_ctx.ctxs.");
×
267
    }
×
268
    alp_ctx.ctxs_len = g_alproto_max;
2,181✔
269
    SCReturnInt(0);
2,181✔
270
}
2,181✔
271

272
void AppLayerParserPostStreamSetup(void)
273
{
3,554✔
274
    /* lets set a default value for stream_depth */
275
    for (int flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) {
14,216✔
276
        for (AppProto alproto = 0; alproto < g_alproto_max; alproto++) {
437,139✔
277
            if (!(alp_ctx.ctxs[alproto][flow_proto].internal_flags &
426,477✔
278
                        APP_LAYER_PARSER_INT_STREAM_DEPTH_SET)) {
426,477✔
279
                alp_ctx.ctxs[alproto][flow_proto].stream_depth = stream_config.reassembly_depth;
420,061✔
280
            }
420,061✔
281
        }
426,477✔
282
    }
10,662✔
283
}
3,554✔
284

285
int AppLayerParserDeSetup(void)
286
{
2,104✔
287
    SCEnter();
2,104✔
288

289
    SCFree(alp_ctx.ctxs);
2,104✔
290

291
    FTPParserCleanup();
2,104✔
292
    SMTPParserCleanup();
2,104✔
293

294
    SCReturnInt(0);
2,104✔
295
}
2,104✔
296

297
AppLayerParserThreadCtx *AppLayerParserThreadCtxAlloc(void)
298
{
30,385✔
299
    SCEnter();
30,385✔
300

301
    AppLayerParserThreadCtx *tctx = SCCalloc(1, sizeof(*tctx));
30,385✔
302
    if (tctx == NULL)
30,385✔
303
        goto end;
×
304

305
    tctx->alproto_local_storage = SCCalloc(g_alproto_max, sizeof(void *[FLOW_PROTO_MAX]));
30,385✔
306
    if (unlikely(tctx->alproto_local_storage == NULL)) {
30,385✔
307
        SCFree(tctx);
×
308
        tctx = NULL;
×
309
        goto end;
×
310
    }
×
311
    for (uint8_t flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) {
121,540✔
312
        for (AppProto alproto = 0; alproto < g_alproto_max; alproto++) {
3,737,328✔
313
            uint8_t ipproto = FlowGetReverseProtoMapping(flow_proto);
3,646,173✔
314

315
            tctx->alproto_local_storage[alproto][flow_proto] =
3,646,173✔
316
                    AppLayerParserGetProtocolParserLocalStorage(ipproto, alproto);
3,646,173✔
317
        }
3,646,173✔
318
    }
91,155✔
319

320
 end:
30,385✔
321
    SCReturnPtr(tctx, "void *");
30,385✔
322
}
30,385✔
323

324
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
325
{
30,381✔
326
    SCEnter();
30,381✔
327

328
    for (uint8_t flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) {
121,524✔
329
        for (AppProto alproto = 0; alproto < g_alproto_max; alproto++) {
3,736,836✔
330
            uint8_t ipproto = FlowGetReverseProtoMapping(flow_proto);
3,645,693✔
331

332
            AppLayerParserDestroyProtocolParserLocalStorage(
3,645,693✔
333
                    ipproto, alproto, tctx->alproto_local_storage[alproto][flow_proto]);
3,645,693✔
334
        }
3,645,693✔
335
    }
91,143✔
336

337
    SCFree(tctx->alproto_local_storage);
30,381✔
338
    SCFree(tctx);
30,381✔
339
    SCReturn;
30,381✔
340
}
30,381✔
341

342
/** \brief check if a parser is enabled in the config
343
 *  Returns enabled always if: were running unittests
344
 */
345
int SCAppLayerParserConfParserEnabled(const char *ipproto, const char *alproto_name)
346
{
80,580✔
347
    SCEnter();
80,580✔
348

349
    char param[100];
80,580✔
350
    SCConfNode *g_proto, *i_proto;
80,580✔
351
    bool g_enabled = false;
80,580✔
352
    bool i_enabled = false;
80,580✔
353
    int r;
80,580✔
354

355
    if (RunmodeIsUnittests())
80,580✔
UNCOV
356
        SCReturnInt(1);
×
357

358
    r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.", alproto_name, ".",
80,580✔
359
            ipproto, ".enabled");
80,580✔
360
    if (r < 0) {
80,580✔
361
        FatalError("snprintf failure.");
×
362
    } else if (r > (int)sizeof(param)) {
80,580✔
363
        FatalError("buffer not big enough to write param.");
×
364
    }
×
365
    SCLogDebug("Looking for %s", param);
80,580✔
366

367
    i_proto = SCConfGetNode(param);
80,580✔
368
    if (i_proto && i_proto->val) {
80,580✔
369
        if (SCConfValIsTrue(i_proto->val)) {
5,920✔
370
            i_enabled = true;
5,920✔
371
        } else if (SCConfValIsFalse(i_proto->val)) {
5,920✔
372
            i_enabled = false;
×
373
        } else if (strcasecmp(i_proto->val, "detection-only") == 0) {
×
374
            i_enabled = false;
×
375
        } else {
×
376
            FatalError("Invalid value found for %s.", param);
×
377
        }
×
378
    }
5,920✔
379

380
    r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.", alproto_name, ".enabled");
80,580✔
381
    if (r < 0) {
80,580✔
382
        FatalError("snprintf failure.");
×
383
    } else if (r > (int)sizeof(param)) {
80,580✔
384
        FatalError("buffer not big enough to write param.");
×
385
    }
×
386

387
    SCLogDebug("Looking for %s", param);
80,580✔
388
    g_proto = SCConfGetNode(param);
80,580✔
389
    if (g_proto && g_proto->val) {
80,580✔
390
        if (SCConfValIsTrue(g_proto->val)) {
41,466✔
391
            g_enabled = true;
41,458✔
392
        } else if (SCConfValIsFalse(g_proto->val)) {
41,458✔
393
            g_enabled = false;
4✔
394
        } else if (strcasecmp(g_proto->val, "detection-only") == 0) {
4✔
395
            g_enabled = false;
4✔
396
        } else {
4✔
397
            FatalError("Invalid value found for %s", param);
×
398
        }
×
399
    }
41,466✔
400

401
    if ((i_proto && g_proto) && (i_enabled ^ g_enabled)) {
80,580✔
402
        /* these checks are also performed for detection-only, no need to issue double warning */
403
        SCLogDebug("Inconsistent global (%s) and respective ipproto (%s) settings found for "
4✔
404
                   "alproto %s and ipproto %s",
4✔
405
                g_enabled ? "TRUE" : "FALSE", i_enabled ? "TRUE" : "FALSE", alproto_name, ipproto);
4✔
406
    }
4✔
407

408
    if (i_proto) {
80,580✔
409
        SCReturnInt(i_enabled);
5,920✔
410
    }
5,920✔
411
    if (g_proto) {
74,660✔
412
        SCReturnInt(g_enabled);
41,458✔
413
    }
41,458✔
414

415
    SCReturnInt(1);
74,660✔
416
}
74,660✔
417

418
/***** Parser related registration *****/
419

420
int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto,
421
                      uint8_t direction,
422
                      AppLayerParserFPtr Parser)
423
{
161,306✔
424
    SCEnter();
161,306✔
425

426
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)]
161,306✔
427
            .Parser[(direction & STREAM_TOSERVER) ? 0 : 1] = Parser;
161,306✔
428

429
    SCReturnInt(0);
161,306✔
430
}
161,306✔
431

432
void SCAppLayerParserRegisterParserAcceptableDataDirection(
433
        uint8_t ipproto, AppProto alproto, uint8_t direction)
434
{
10,144✔
435
    SCEnter();
10,144✔
436

437
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].first_data_dir |=
10,144✔
438
            (direction & (STREAM_TOSERVER | STREAM_TOCLIENT));
10,144✔
439

440
    SCReturn;
10,144✔
441
}
10,144✔
442

443
void AppLayerParserRegisterOptionFlags(uint8_t ipproto, AppProto alproto,
444
        uint32_t flags)
445
{
18,862✔
446
    SCEnter();
18,862✔
447

448
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].option_flags |= flags;
18,862✔
449

450
    SCReturn;
18,862✔
451
}
18,862✔
452

453
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto,
454
        void *(*StateAlloc)(void *, AppProto), void (*StateFree)(void *))
455
{
80,653✔
456
    SCEnter();
80,653✔
457

458
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateAlloc = StateAlloc;
80,653✔
459
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateFree = StateFree;
80,653✔
460

461
    SCReturn;
80,653✔
462
}
80,653✔
463

464
void AppLayerParserRegisterLocalStorageFunc(uint8_t ipproto, AppProto alproto,
465
                                 void *(*LocalStorageAlloc)(void),
466
                                 void (*LocalStorageFree)(void *))
467
{
4,362✔
468
    SCEnter();
4,362✔
469

470
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].LocalStorageAlloc = LocalStorageAlloc;
4,362✔
471
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].LocalStorageFree = LocalStorageFree;
4,362✔
472

473
    SCReturn;
4,362✔
474
}
4,362✔
475

476
void AppLayerParserRegisterGetTxFilesFunc(
477
        uint8_t ipproto, AppProto alproto, AppLayerGetFileState (*GetTxFiles)(void *, uint8_t))
478
{
17,421✔
479
    SCEnter();
17,421✔
480

481
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetTxFiles = GetTxFiles;
17,421✔
482

483
    SCReturn;
17,421✔
484
}
17,421✔
485

486
void AppLayerParserRegisterLoggerBits(uint8_t ipproto, AppProto alproto, LoggerId bits)
487
{
162,452✔
488
    SCEnter();
162,452✔
489

490
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].logger_bits = bits;
162,452✔
491

492
    SCReturn;
162,452✔
493
}
162,452✔
494

495
void SCAppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto)
496
{
92,139✔
497
    SCEnter();
92,139✔
498

499
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].logger = true;
92,139✔
500

501
    SCReturn;
92,139✔
502
}
92,139✔
503

504
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto,
505
    int (*StateGetProgress)(void *alstate, uint8_t direction))
506
{
80,653✔
507
    SCEnter();
80,653✔
508

509
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateGetProgress = StateGetProgress;
80,653✔
510

511
    SCReturn;
80,653✔
512
}
80,653✔
513

514
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto,
515
                           void (*StateTransactionFree)(void *, uint64_t))
516
{
80,653✔
517
    SCEnter();
80,653✔
518

519
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateTransactionFree = StateTransactionFree;
80,653✔
520

521
    SCReturn;
80,653✔
522
}
80,653✔
523

524
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto,
525
                         uint64_t (*StateGetTxCnt)(void *alstate))
526
{
80,653✔
527
    SCEnter();
80,653✔
528

529
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateGetTxCnt = StateGetTxCnt;
80,653✔
530

531
    SCReturn;
80,653✔
532
}
80,653✔
533

534
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto,
535
                      void *(StateGetTx)(void *alstate, uint64_t tx_id))
536
{
80,653✔
537
    SCEnter();
80,653✔
538

539
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateGetTx = StateGetTx;
80,653✔
540

541
    SCReturn;
80,653✔
542
}
80,653✔
543

544
void AppLayerParserRegisterGetTxIterator(uint8_t ipproto, AppProto alproto,
545
                      AppLayerGetTxIteratorFunc Func)
546
{
71,929✔
547
    SCEnter();
71,929✔
548
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateGetTxIterator = Func;
71,929✔
549
    SCReturn;
71,929✔
550
}
71,929✔
551

552
void AppLayerParserRegisterStateProgressCompletionStatus(
553
        AppProto alproto, const int ts, const int tc)
554
{
80,653✔
555
    BUG_ON(ts == 0);
80,653✔
556
    BUG_ON(tc == 0);
80,653✔
557
    BUG_ON(!AppProtoIsValid(alproto));
80,653✔
558
    BUG_ON(alp_ctx.ctxs[alproto][FLOW_PROTO_DEFAULT].complete_ts != 0 &&
80,653✔
559
            alp_ctx.ctxs[alproto][FLOW_PROTO_DEFAULT].complete_ts != ts);
80,653✔
560
    BUG_ON(alp_ctx.ctxs[alproto][FLOW_PROTO_DEFAULT].complete_tc != 0 &&
80,653✔
561
            alp_ctx.ctxs[alproto][FLOW_PROTO_DEFAULT].complete_tc != tc);
80,653✔
562

563
    alp_ctx.ctxs[alproto][FLOW_PROTO_DEFAULT].complete_ts = ts;
80,653✔
564
    alp_ctx.ctxs[alproto][FLOW_PROTO_DEFAULT].complete_tc = tc;
80,653✔
565
}
80,653✔
566

567
void AppLayerParserRegisterGetEventInfoById(uint8_t ipproto, AppProto alproto,
568
        int (*StateGetEventInfoById)(
569
                uint8_t event_id, const char **event_name, AppLayerEventType *event_type))
570
{
69,748✔
571
    SCEnter();
69,748✔
572

573
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateGetEventInfoById =
69,748✔
574
            StateGetEventInfoById;
69,748✔
575

576
    SCReturn;
69,748✔
577
}
69,748✔
578

579
void AppLayerParserRegisterGetStateFuncs(uint8_t ipproto, AppProto alproto,
580
        AppLayerParserGetStateIdByNameFn GetIdByNameFunc,
581
        AppLayerParserGetStateNameByIdFn GetNameByIdFunc)
582
{
6,543✔
583
    SCEnter();
6,543✔
584
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetStateIdByName = GetIdByNameFunc;
6,543✔
585
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetStateNameById = GetNameByIdFunc;
6,543✔
586
    SCReturn;
6,543✔
587
}
6,543✔
588

589
void AppLayerParserRegisterGetFrameFuncs(uint8_t ipproto, AppProto alproto,
590
        AppLayerParserGetFrameIdByNameFn GetIdByNameFunc,
591
        AppLayerParserGetFrameNameByIdFn GetNameByIdFunc)
592
{
47,183✔
593
    SCEnter();
47,183✔
594
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetFrameIdByName = GetIdByNameFunc;
47,183✔
595
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetFrameNameById = GetNameByIdFunc;
47,183✔
596
    SCReturn;
47,183✔
597
}
47,183✔
598

599
void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto,
600
        int (*StateGetEventInfo)(
601
                const char *event_name, uint8_t *event_id, AppLayerEventType *event_type))
602
{
71,929✔
603
    SCEnter();
71,929✔
604

605
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateGetEventInfo = StateGetEventInfo;
71,929✔
606

607
    SCReturn;
71,929✔
608
}
71,929✔
609

610
void AppLayerParserRegisterTxDataFunc(uint8_t ipproto, AppProto alproto,
611
        AppLayerTxData *(*GetTxData)(void *tx))
612
{
80,653✔
613
    SCEnter();
80,653✔
614

615
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetTxData = GetTxData;
80,653✔
616

617
    SCReturn;
80,653✔
618
}
80,653✔
619

620
void AppLayerParserRegisterStateDataFunc(
621
        uint8_t ipproto, AppProto alproto, AppLayerStateData *(*GetStateData)(void *state))
622
{
80,653✔
623
    SCEnter();
80,653✔
624

625
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetStateData = GetStateData;
80,653✔
626

627
    SCReturn;
80,653✔
628
}
80,653✔
629

630
void AppLayerParserRegisterApplyTxConfigFunc(uint8_t ipproto, AppProto alproto,
631
        void (*ApplyTxConfig)(void *state, void *tx, int mode, AppLayerTxConfig))
632
{
4,353✔
633
    SCEnter();
4,353✔
634

635
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].ApplyTxConfig = ApplyTxConfig;
4,353✔
636

637
    SCReturn;
4,353✔
638
}
4,353✔
639

640
void AppLayerParserRegisterSetStreamDepthFlag(uint8_t ipproto, AppProto alproto,
641
        void (*SetStreamDepthFlag)(void *tx, uint8_t flags))
642
{
2,181✔
643
    SCEnter();
2,181✔
644

645
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].SetStreamDepthFlag = SetStreamDepthFlag;
2,181✔
646

647
    SCReturn;
2,181✔
648
}
2,181✔
649

650
/***** Get and transaction functions *****/
651

652
void *AppLayerParserGetProtocolParserLocalStorage(uint8_t ipproto, AppProto alproto)
653
{
3,646,173✔
654
    SCEnter();
3,646,173✔
655
    void * r = NULL;
3,646,173✔
656

657
    if (alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].LocalStorageAlloc != NULL) {
3,646,173✔
658
        r = alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].LocalStorageAlloc();
60,770✔
659
    }
60,770✔
660

661
    SCReturnPtr(r, "void *");
3,646,173✔
662
}
3,646,173✔
663

664
void AppLayerParserDestroyProtocolParserLocalStorage(uint8_t ipproto, AppProto alproto,
665
                                          void *local_data)
666
{
3,645,693✔
667
    SCEnter();
3,645,693✔
668

669
    if (alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].LocalStorageFree != NULL) {
3,645,693✔
670
        alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].LocalStorageFree(local_data);
60,762✔
671
    }
60,762✔
672

673
    SCReturn;
3,645,693✔
674
}
3,645,693✔
675

676
/** \brief default tx iterator
677
 *
678
 *  Used if the app layer parser doesn't register its own iterator.
679
 *  Simply walks the tx_id space until it finds a tx. Uses 'state' to
680
 *  keep track of where it left off.
681
 *
682
 *  \retval txptr or NULL if no more txs in list
683
 */
684
static AppLayerGetTxIterTuple AppLayerDefaultGetTxIterator(
685
        const uint8_t ipproto, const AppProto alproto,
686
        void *alstate, uint64_t min_tx_id, uint64_t max_tx_id,
687
        AppLayerGetTxIterState *state)
688
{
454,721✔
689
    uint64_t ustate = *(uint64_t *)state;
454,721✔
690
    uint64_t tx_id = MAX(min_tx_id, ustate);
454,721✔
691
    for ( ; tx_id < max_tx_id; tx_id++) {
2,147,865,693✔
692
        void *tx_ptr = AppLayerParserGetTx(ipproto, alproto, alstate, tx_id);
376,461✔
693
        if (tx_ptr != NULL) {
376,468✔
694
            ustate = tx_id + 1;
376,440✔
695
            *state = *(AppLayerGetTxIterState *)&ustate;
376,440✔
696
            AppLayerGetTxIterTuple tuple = {
376,440✔
697
                .tx_ptr = tx_ptr,
376,440✔
698
                .tx_id = tx_id,
376,440✔
699
                .has_next = (tx_id + 1 < max_tx_id),
376,440✔
700
            };
376,440✔
701
            SCLogDebug("tuple: %p/%"PRIu64"/%s", tuple.tx_ptr, tuple.tx_id,
376,440✔
702
                    tuple.has_next ? "true" : "false");
376,440✔
703
            return tuple;
376,440✔
704
        }
376,440✔
705
    }
376,461✔
706

707
    AppLayerGetTxIterTuple no_tuple = { NULL, 0, false };
78,281✔
708
    return no_tuple;
78,281✔
709
}
454,721✔
710

711
AppLayerGetTxIteratorFunc AppLayerGetTxIterator(const uint8_t ipproto,
712
        const AppProto alproto)
713
{
3,506,004✔
714
    AppLayerGetTxIteratorFunc Func =
3,506,004✔
715
            alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateGetTxIterator;
3,506,004✔
716
    return Func ? Func : AppLayerDefaultGetTxIterator;
3,506,004✔
717
}
3,506,004✔
718

719
uint64_t AppLayerParserGetTransactionLogId(AppLayerParserState *pstate)
720
{
970,132✔
721
    SCEnter();
970,132✔
722

723
    SCReturnCT((pstate == NULL) ? 0 : pstate->log_id, "uint64_t");
970,132✔
724
}
970,132✔
725

726
uint64_t AppLayerParserGetMinId(AppLayerParserState *pstate)
727
{
8,959✔
728
    SCEnter();
8,959✔
729

730
    SCReturnCT((pstate == NULL) ? 0 : pstate->min_id, "uint64_t");
8,959✔
731
}
8,959✔
732

733
void AppLayerParserSetTransactionLogId(AppLayerParserState *pstate, uint64_t tx_id)
734
{
122,587✔
735
    SCEnter();
122,587✔
736

737
    if (pstate != NULL)
122,587✔
738
        pstate->log_id = tx_id;
122,587✔
739

740
    SCReturn;
122,587✔
741
}
122,587✔
742

743
uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction)
744
{
2,431,661✔
745
    SCEnter();
2,431,661✔
746

747
    if (pstate != NULL)
2,431,661✔
748
        SCReturnCT(pstate->inspect_id[(direction & STREAM_TOSERVER) ? 0 : 1], "uint64_t");
2,431,690✔
749

750
    DEBUG_VALIDATE_BUG_ON(1);
4,294,967,294✔
751
    SCReturnCT(0ULL, "uint64_t");
4,294,967,294✔
752
}
2,431,661✔
753

754
inline uint8_t AppLayerParserGetTxDetectProgress(AppLayerTxData *txd, const uint8_t dir)
755
{
×
756
    uint8_t p = (dir & STREAM_TOSERVER) ? txd->detect_progress_ts : txd->detect_progress_tc;
×
757
    return p;
×
758
}
×
759

760
static inline uint32_t GetTxLogged(AppLayerTxData *txd)
761
{
387,526✔
762
    return txd->logged;
387,526✔
763
}
387,526✔
764

765
void SCAppLayerTxDataCleanup(AppLayerTxData *txd)
766
{
368,931✔
767
    if (txd->de_state) {
368,931✔
768
        SCDetectEngineStateFree(txd->de_state);
19,244✔
769
    }
19,244✔
770
    if (txd->events) {
368,931✔
771
        SCAppLayerDecoderEventsFreeEvents(&txd->events);
16,695✔
772
    }
16,695✔
773
    if (txd->txbits) {
368,931✔
774
        SCGenericVarFree(txd->txbits);
8✔
775
    }
8✔
776
}
368,931✔
777

778
void AppLayerParserSetTransactionInspectId(const Flow *f, AppLayerParserState *pstate,
779
                                           void *alstate, const uint8_t flags,
780
                                           bool tag_txs_as_inspected)
781
{
719,210✔
782
    SCEnter();
719,210✔
783

784
    const int direction = (flags & STREAM_TOSERVER) ? 0 : 1;
719,210✔
785
    const uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
719,210✔
786
    uint64_t idx = AppLayerParserGetTransactionInspectId(pstate, flags);
719,210✔
787
    const int state_done_progress = AppLayerParserGetStateProgressCompletionStatus(f->alproto, flags);
719,210✔
788
    const uint8_t ipproto = f->proto;
719,210✔
789
    const AppProto alproto = f->alproto;
719,210✔
790

791
    AppLayerGetTxIteratorFunc IterFunc = AppLayerGetTxIterator(ipproto, alproto);
719,210✔
792
    AppLayerGetTxIterState state = { 0 };
719,210✔
793

794
    SCLogDebug("called: %s, tag_txs_as_inspected %s",direction==0?"toserver":"toclient",
719,210✔
795
            tag_txs_as_inspected?"true":"false");
719,210✔
796

797
    /* mark all txs as inspected if the applayer progress is
798
     * at the 'end state'. */
799
    while (1) {
778,335✔
800
        AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, idx, total_txs, &state);
778,335✔
801
        if (ires.tx_ptr == NULL)
778,335✔
802
            break;
112,453✔
803

804
        void *tx = ires.tx_ptr;
665,882✔
805
        idx = ires.tx_id;
665,882✔
806

807
        int state_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx, flags);
665,882✔
808
        if (state_progress < state_done_progress)
665,882✔
809
            break;
493,455✔
810

811
        AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
172,427✔
812
        if (tag_txs_as_inspected) {
172,427✔
813
            const uint8_t inspected_flag = (flags & STREAM_TOSERVER) ? APP_LAYER_TX_INSPECTED_TS
2,484✔
814
                                                                     : APP_LAYER_TX_INSPECTED_TC;
2,484✔
815
            if (txd->flags & inspected_flag) {
2,484✔
816
                txd->flags |= inspected_flag;
×
817
                SCLogDebug("%p/%" PRIu64 " in-order tx is done for direction %s. Flags %02x", tx,
×
818
                        idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", txd->flags);
×
819
            }
×
820
        }
2,484✔
821
        idx++;
172,427✔
822
        if (!ires.has_next)
172,427✔
823
            break;
113,365✔
824
    }
172,427✔
825
    pstate->inspect_id[direction] = idx;
719,210✔
826
    SCLogDebug("inspect_id now %"PRIu64, pstate->inspect_id[direction]);
719,210✔
827

828
    /* if necessary we flag all txs that are complete as 'inspected'
829
     * also move inspect_id forward. */
830
    if (tag_txs_as_inspected) {
719,210✔
831
        /* continue at idx */
832
        while (1) {
10,775✔
833
            AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, idx, total_txs, &state);
10,775✔
834
            if (ires.tx_ptr == NULL)
10,775✔
835
                break;
7,857✔
836

837
            void *tx = ires.tx_ptr;
2,918✔
838
            /* if we got a higher id than the minimum we requested, we
839
             * skipped a bunch of 'null-txs'. Lets see if we can up the
840
             * inspect tracker */
841
            if (ires.tx_id > idx && pstate->inspect_id[direction] == idx) {
2,918✔
842
                pstate->inspect_id[direction] = ires.tx_id;
3✔
843
            }
3✔
844
            idx = ires.tx_id;
2,918✔
845

846
            const int state_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx, flags);
2,918✔
847
            if (state_progress < state_done_progress)
2,918✔
848
                break;
2,914✔
849

850
            /* txd can be NULL for HTTP sessions where the user data alloc failed */
851
            AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
4✔
852
            const uint8_t inspected_flag = (flags & STREAM_TOSERVER) ? APP_LAYER_TX_INSPECTED_TS
4✔
853
                                                                     : APP_LAYER_TX_INSPECTED_TC;
4✔
854
            if (txd->flags & inspected_flag) {
4✔
855
                txd->flags |= inspected_flag;
×
856
                SCLogDebug("%p/%" PRIu64 " out of order tx is done for direction %s. Flag %02x", tx,
×
857
                        idx, flags & STREAM_TOSERVER ? "toserver" : "toclient", txd->flags);
×
858

859
                SCLogDebug("%p/%" PRIu64 " out of order tx. Update inspect_id? %" PRIu64, tx, idx,
×
860
                        pstate->inspect_id[direction]);
×
861
                if (pstate->inspect_id[direction] + 1 == idx)
×
862
                    pstate->inspect_id[direction] = idx;
×
863
            }
×
864
            if (!ires.has_next)
4✔
865
                break;
2✔
866
            idx++;
2✔
867
        }
2✔
868
    }
10,773✔
869

870
    SCReturn;
719,210✔
871
}
719,210✔
872

873
AppLayerDecoderEvents *AppLayerParserGetDecoderEvents(AppLayerParserState *pstate)
874
{
4,814,447✔
875
    SCEnter();
4,814,447✔
876

877
    SCReturnPtr(pstate->decoder_events,
4,814,447✔
878
                "AppLayerDecoderEvents *");
4,814,447✔
879
}
4,814,447✔
880

881
AppLayerDecoderEvents *AppLayerParserGetEventsByTx(uint8_t ipproto, AppProto alproto,
882
                                        void *tx)
883
{
2,391,821✔
884
    SCEnter();
2,391,821✔
885

886
    AppLayerDecoderEvents *ptr = NULL;
2,391,821✔
887

888
    /* Access events via the tx_data. */
889
    AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
2,391,821✔
890
    if (txd->events != NULL) {
2,391,821✔
891
        ptr = txd->events;
150,163✔
892
    }
150,163✔
893

894
    SCReturnPtr(ptr, "AppLayerDecoderEvents *");
2,391,821✔
895
}
2,391,821✔
896

897
AppLayerGetFileState AppLayerParserGetTxFiles(const Flow *f, void *tx, const uint8_t direction)
898
{
1,521,808✔
899
    SCEnter();
1,521,808✔
900

901
    if (alp_ctx.ctxs[f->alproto][f->protomap].GetTxFiles != NULL) {
1,521,808✔
902
        return alp_ctx.ctxs[f->alproto][f->protomap].GetTxFiles(tx, direction);
1,501,804✔
903
    }
1,501,804✔
904

905
    AppLayerGetFileState files = { .fc = NULL, .cfg = NULL };
20,004✔
906
    return files;
20,004✔
907
}
1,521,808✔
908

909
static void AppLayerParserFileTxHousekeeping(
910
        const Flow *f, void *tx, const uint8_t pkt_dir, const bool trunc)
911
{
264,892✔
912
    AppLayerGetFileState files = AppLayerParserGetTxFiles(f, tx, pkt_dir);
264,892✔
913
    if (files.fc) {
264,898✔
914
        FilesPrune(files.fc, files.cfg, trunc);
264,894✔
915
    }
264,894✔
916
}
264,892✔
917

918
#define IS_DISRUPTED(flags) ((flags) & (STREAM_DEPTH | STREAM_GAP))
407,763,428✔
919

920
extern int g_detect_disabled;
921
extern bool g_file_logger_enabled;
922
extern bool g_filedata_logger_enabled;
923

924
/**
925
 * \brief remove obsolete (inspected and logged) transactions
926
 */
927
void AppLayerParserTransactionsCleanup(Flow *f, const uint8_t pkt_dir)
928
{
1,118,661✔
929
    SCEnter();
1,118,661✔
930
    DEBUG_ASSERT_FLOW_LOCKED(f);
1,118,661✔
931

932
    AppLayerParserProtoCtx *p = &alp_ctx.ctxs[f->alproto][f->protomap];
1,118,661✔
933
    if (unlikely(p->StateTransactionFree == NULL))
1,118,661✔
934
        SCReturn;
19,009✔
935

936
    const bool has_tx_detect_flags = !g_detect_disabled;
1,099,652✔
937
    const uint8_t ipproto = f->proto;
1,099,652✔
938
    const AppProto alproto = f->alproto;
1,099,652✔
939
    void * const alstate = f->alstate;
1,099,652✔
940
    AppLayerParserState * const alparser = f->alparser;
1,099,652✔
941

942
    if (alstate == NULL || alparser == NULL)
1,099,664✔
943
        SCReturn;
10✔
944

945
    const uint64_t min = alparser->min_id;
1,099,642✔
946
    const uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
1,099,642✔
947
    const LoggerId logger_expectation = AppLayerParserProtocolGetLoggerBits(ipproto, alproto);
1,099,642✔
948
    const int tx_end_state_ts = AppLayerParserGetStateProgressCompletionStatus(alproto, STREAM_TOSERVER);
1,099,642✔
949
    const int tx_end_state_tc = AppLayerParserGetStateProgressCompletionStatus(alproto, STREAM_TOCLIENT);
1,099,642✔
950
    const uint8_t ts_disrupt_flags = FlowGetDisruptionFlags(f, STREAM_TOSERVER);
1,099,642✔
951
    const uint8_t tc_disrupt_flags = FlowGetDisruptionFlags(f, STREAM_TOCLIENT);
1,099,642✔
952

953
    int pkt_dir_trunc = -1;
1,099,642✔
954

955
    AppLayerGetTxIteratorFunc IterFunc = AppLayerGetTxIterator(ipproto, alproto);
1,099,642✔
956
    AppLayerGetTxIterState state;
1,099,642✔
957
    memset(&state, 0, sizeof(state));
1,099,642✔
958
    uint64_t i = min;
1,099,642✔
959
    uint64_t new_min = min;
1,099,642✔
960
    SCLogDebug("start min %"PRIu64, min);
1,099,642✔
961
    bool skipped = false;
1,099,642✔
962
    // const bool support_files = AppLayerParserSupportsFiles(f->proto, f->alproto);
963

964
    while (1) {
105,470,050✔
965
        AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, i, total_txs, &state);
105,470,050✔
966
        if (ires.tx_ptr == NULL)
105,470,050✔
967
            break;
365,046✔
968

969
        bool tx_skipped = false;
105,470,050✔
970
        void *tx = ires.tx_ptr;
105,105,004✔
971
        i = ires.tx_id; // actual tx id for the tx the IterFunc returned
105,105,004✔
972

973
        SCLogDebug("%p/%"PRIu64" checking", tx, i);
105,105,004✔
974
        AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx);
105,105,004✔
975
        if (AppLayerParserHasFilesInDir(txd, pkt_dir)) {
105,105,004✔
976
            if (pkt_dir_trunc == -1)
264,893✔
977
                pkt_dir_trunc = IS_DISRUPTED(
157,708✔
978
                        (pkt_dir == STREAM_TOSERVER) ? ts_disrupt_flags : tc_disrupt_flags);
264,893✔
979
            AppLayerParserFileTxHousekeeping(f, tx, pkt_dir, (bool)pkt_dir_trunc);
264,893✔
980
        }
264,893✔
981
        // should be reset by parser next time it updates the tx
982
        if (pkt_dir & STREAM_TOSERVER) {
105,105,004✔
983
            txd->updated_ts = false;
103,165,849✔
984
        } else {
103,165,849✔
985
            txd->updated_tc = false;
1,939,155✔
986
        }
1,939,155✔
987
        const int tx_progress_tc =
105,105,004✔
988
                AppLayerParserGetStateProgress(ipproto, alproto, tx, tc_disrupt_flags);
105,105,004✔
989
        if (tx_progress_tc < tx_end_state_tc) {
105,105,004✔
990
            SCLogDebug("%p/%"PRIu64" skipping: tc parser not done", tx, i);
2,603,022✔
991
            skipped = true;
2,603,022✔
992
            goto next;
2,603,022✔
993
        }
2,603,022✔
994
        const int tx_progress_ts =
102,501,982✔
995
                AppLayerParserGetStateProgress(ipproto, alproto, tx, ts_disrupt_flags);
102,501,982✔
996
        if (tx_progress_ts < tx_end_state_ts) {
102,501,982✔
997
            SCLogDebug("%p/%"PRIu64" skipping: ts parser not done", tx, i);
592,857✔
998
            skipped = true;
592,857✔
999
            goto next;
592,857✔
1000
        }
592,857✔
1001

1002
        if (has_tx_detect_flags) {
101,909,154✔
1003
            if (!IS_DISRUPTED(ts_disrupt_flags) &&
101,901,430✔
1004
                    (f->sgh_toserver != NULL || (f->flags & FLOW_SGH_TOSERVER) == 0)) {
101,901,430✔
1005
                if ((txd->flags & (APP_LAYER_TX_INSPECTED_TS | APP_LAYER_TX_SKIP_INSPECT_TS)) ==
101,799,989✔
1006
                        0) {
101,799,989✔
1007
                    SCLogDebug("%p/%" PRIu64 " skipping: TS inspect not done: ts:%02x", tx, i,
82,244✔
1008
                            txd->flags);
82,244✔
1009
                    tx_skipped = true;
82,244✔
1010
                }
82,244✔
1011
            }
101,799,989✔
1012
            if (!IS_DISRUPTED(tc_disrupt_flags) &&
101,901,430✔
1013
                    (f->sgh_toclient != NULL || (f->flags & FLOW_SGH_TOCLIENT) == 0)) {
101,901,430✔
1014
                if ((txd->flags & (APP_LAYER_TX_INSPECTED_TC | APP_LAYER_TX_SKIP_INSPECT_TC)) ==
101,775,971✔
1015
                        0) {
101,775,971✔
1016
                    SCLogDebug("%p/%" PRIu64 " skipping: TC inspect not done: ts:%02x", tx, i,
101,487,692✔
1017
                            txd->flags);
101,487,692✔
1018
                    tx_skipped = true;
101,487,692✔
1019
                }
101,487,692✔
1020
            }
101,775,971✔
1021
        }
101,901,430✔
1022

1023
        if (tx_skipped) {
101,909,125✔
1024
            SCLogDebug("%p/%" PRIu64 " tx_skipped", tx, i);
101,500,723✔
1025
            skipped = true;
101,500,723✔
1026
            goto next;
101,500,723✔
1027
        }
101,500,723✔
1028

1029
        if (logger_expectation != 0) {
408,429✔
1030
            LoggerId tx_logged = GetTxLogged(txd);
387,526✔
1031
            if (tx_logged != logger_expectation) {
387,526✔
1032
                SCLogDebug("%p/%"PRIu64" skipping: logging not done: want:%"PRIx32", have:%"PRIx32,
4,725✔
1033
                        tx, i, logger_expectation, tx_logged);
4,725✔
1034
                skipped = true;
4,725✔
1035
                goto next;
4,725✔
1036
            }
4,725✔
1037
        }
387,526✔
1038

1039
        /* if file logging is enabled, we keep a tx active while some of the files aren't
1040
         * logged yet. */
1041
        SCLogDebug("files_opened %u files_logged %u files_stored %u", txd->files_opened,
403,677✔
1042
                txd->files_logged, txd->files_stored);
403,677✔
1043

1044
        if (txd->files_opened) {
403,677✔
1045
            if (g_file_logger_enabled && txd->files_opened != txd->files_logged) {
189,158✔
1046
                skipped = true;
166✔
1047
                goto next;
166✔
1048
            }
166✔
1049
            if (g_filedata_logger_enabled && txd->files_opened != txd->files_stored) {
188,992✔
1050
                skipped = true;
172,815✔
1051
                goto next;
172,815✔
1052
            }
172,815✔
1053
        }
188,992✔
1054

1055
        /* if we are here, the tx can be freed. */
1056
        p->StateTransactionFree(alstate, i);
230,696✔
1057
        SCLogDebug("%p/%"PRIu64" freed", tx, i);
230,696✔
1058

1059
        /* if we didn't skip any tx so far, up the minimum */
1060
        SCLogDebug("skipped? %s i %"PRIu64", new_min %"PRIu64, skipped ? "true" : "false", i, new_min);
230,696✔
1061
        if (!skipped)
230,696✔
1062
            new_min = i + 1;
121,385✔
1063
        SCLogDebug("final i %"PRIu64", new_min %"PRIu64, i, new_min);
230,696✔
1064

1065
next:
105,104,979✔
1066
        if (!ires.has_next) {
105,104,979✔
1067
            /* this was the last tx. See if we skipped any. If not
1068
             * we removed all and can update the minimum to the max
1069
             * id. */
1070
            SCLogDebug("no next: cur tx i %"PRIu64", total %"PRIu64, i, total_txs);
734,606✔
1071
            if (!skipped) {
734,606✔
1072
                new_min = total_txs;
78,214✔
1073
                SCLogDebug("no next: cur tx i %"PRIu64", total %"PRIu64": "
78,214✔
1074
                        "new_min updated to %"PRIu64, i, total_txs, new_min);
78,214✔
1075
            }
78,214✔
1076
            break;
734,606✔
1077
        }
734,606✔
1078
        i++;
104,370,373✔
1079
    }
104,370,373✔
1080

1081
    /* see if we need to bring all trackers up to date. */
1082
    SCLogDebug("update f->alparser->min_id? %"PRIu64" vs %"PRIu64, new_min, alparser->min_id);
1,099,617✔
1083
    if (new_min > alparser->min_id) {
1,099,617✔
1084
        const uint64_t next_id = new_min;
113,531✔
1085
        alparser->min_id = next_id;
113,531✔
1086
        alparser->inspect_id[0] = MAX(alparser->inspect_id[0], next_id);
113,531✔
1087
        alparser->inspect_id[1] = MAX(alparser->inspect_id[1], next_id);
113,531✔
1088
        alparser->log_id = MAX(alparser->log_id, next_id);
113,531✔
1089
        SCLogDebug("updated f->alparser->min_id %"PRIu64, alparser->min_id);
113,531✔
1090
    }
113,531✔
1091
    SCReturn;
1,099,617✔
1092
}
1,099,642✔
1093

1094
static inline int StateGetProgressCompletionStatus(const AppProto alproto, const uint8_t flags)
1095
{
5,995,557✔
1096
    if (flags & STREAM_TOSERVER) {
5,995,557✔
1097
        return alp_ctx.ctxs[alproto][FLOW_PROTO_DEFAULT].complete_ts;
3,034,021✔
1098
    } else if (flags & STREAM_TOCLIENT) {
3,034,021✔
1099
        return alp_ctx.ctxs[alproto][FLOW_PROTO_DEFAULT].complete_tc;
2,962,101✔
1100
    } else {
4,296,906,871✔
1101
        DEBUG_VALIDATE_BUG_ON(1);
4,294,967,294✔
1102
        return 0;
4,294,967,294✔
1103
    }
4,294,967,294✔
1104
}
5,995,557✔
1105

1106
/**
1107
 *  \brief get the progress value for a tx/protocol
1108
 *
1109
 *  If the stream is disrupted, we return the 'completion' value.
1110
 */
1111
int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto,
1112
                        void *alstate, uint8_t flags)
1113
{
232,047,360✔
1114
    SCEnter();
232,047,360✔
1115
    int r;
232,047,360✔
1116
    if (unlikely(IS_DISRUPTED(flags))) {
232,047,360✔
1117
        r = StateGetProgressCompletionStatus(alproto, flags);
84,219✔
1118
    } else {
231,963,141✔
1119
        uint8_t direction = flags & (STREAM_TOCLIENT | STREAM_TOSERVER);
231,963,141✔
1120
        r = alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateGetProgress(
231,963,141✔
1121
                alstate, direction);
231,963,141✔
1122
    }
231,963,141✔
1123
    SCReturnInt(r);
232,047,360✔
1124
}
232,047,360✔
1125

1126
uint64_t AppLayerParserGetTxCnt(const Flow *f, void *alstate)
1127
{
5,127,205✔
1128
    SCEnter();
5,127,205✔
1129
    uint64_t r = alp_ctx.ctxs[f->alproto][f->protomap].StateGetTxCnt(alstate);
5,127,205✔
1130
    SCReturnCT(r, "uint64_t");
5,127,205✔
1131
}
5,127,205✔
1132

1133
void *AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
1134
{
525,569✔
1135
    SCEnter();
525,569✔
1136
    void *r = alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateGetTx(alstate, tx_id);
525,569✔
1137
    SCReturnPtr(r, "void *");
525,569✔
1138
}
525,569✔
1139

1140
int AppLayerParserGetStateProgressCompletionStatus(AppProto alproto,
1141
                                                   uint8_t direction)
1142
{
5,911,392✔
1143
    SCEnter();
5,911,392✔
1144
    int r = StateGetProgressCompletionStatus(alproto, direction);
5,911,392✔
1145
    SCReturnInt(r);
5,911,392✔
1146
}
5,911,392✔
1147

1148
int AppLayerParserGetEventInfo(uint8_t ipproto, AppProto alproto, const char *event_name,
1149
        uint8_t *event_id, AppLayerEventType *event_type)
1150
{
91,749✔
1151
    SCEnter();
91,749✔
1152
    const int ipproto_map = FlowGetProtoMapping(ipproto);
91,749✔
1153
    int r = (alp_ctx.ctxs[alproto][ipproto_map].StateGetEventInfo == NULL)
91,749✔
1154
                    ? -1
91,749✔
1155
                    : alp_ctx.ctxs[alproto][ipproto_map].StateGetEventInfo(
91,749✔
1156
                              event_name, event_id, event_type);
90,799✔
1157
    SCReturnInt(r);
91,749✔
1158
}
91,749✔
1159

1160
int AppLayerParserGetEventInfoById(uint8_t ipproto, AppProto alproto, uint8_t event_id,
1161
        const char **event_name, AppLayerEventType *event_type)
1162
{
33,609✔
1163
    SCEnter();
33,609✔
1164
    const int ipproto_map = FlowGetProtoMapping(ipproto);
33,609✔
1165
    *event_name = (const char *)NULL;
33,609✔
1166
    int r = (alp_ctx.ctxs[alproto][ipproto_map].StateGetEventInfoById == NULL)
33,609✔
1167
                    ? -1
33,609✔
1168
                    : alp_ctx.ctxs[alproto][ipproto_map].StateGetEventInfoById(
33,609✔
1169
                              event_id, event_name, event_type);
33,609✔
1170
    SCReturnInt(r);
33,609✔
1171
}
33,609✔
1172

1173
uint8_t AppLayerParserGetFirstDataDir(uint8_t ipproto, AppProto alproto)
1174
{
35,891✔
1175
    SCEnter();
35,891✔
1176
    uint8_t r = alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].first_data_dir;
35,891✔
1177
    SCReturnCT(r, "uint8_t");
35,891✔
1178
}
35,891✔
1179

1180
uint64_t AppLayerParserGetTransactionActive(const Flow *f,
1181
        AppLayerParserState *pstate, uint8_t direction)
1182
{
28,618✔
1183
    SCEnter();
28,618✔
1184

1185
    uint64_t active_id;
28,618✔
1186
    uint64_t log_id = pstate->log_id;
28,618✔
1187
    uint64_t inspect_id = pstate->inspect_id[(direction & STREAM_TOSERVER) ? 0 : 1];
28,618✔
1188
    if (alp_ctx.ctxs[f->alproto][f->protomap].logger) {
28,618✔
1189
        active_id = MIN(log_id, inspect_id);
23,166✔
1190
    } else {
23,166✔
1191
        active_id = inspect_id;
5,452✔
1192
    }
5,452✔
1193

1194
    SCReturnCT(active_id, "uint64_t");
28,618✔
1195
}
28,618✔
1196

1197
bool AppLayerParserSupportsFiles(uint8_t ipproto, AppProto alproto)
1198
{
1,320,612✔
1199
    // Custom case for only signature-only protocol so far
1200
    if (alproto == ALPROTO_HTTP) {
1,320,612✔
1201
        return AppLayerParserSupportsFiles(ipproto, ALPROTO_HTTP1) ||
32,802✔
1202
               AppLayerParserSupportsFiles(ipproto, ALPROTO_HTTP2);
32,802✔
1203
    }
32,802✔
1204
    return alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetTxFiles != NULL;
1,287,810✔
1205
}
1,320,612✔
1206

1207
AppLayerTxData *AppLayerParserGetTxData(uint8_t ipproto, AppProto alproto, void *tx)
1208
{
128,442,884✔
1209
    SCEnter();
128,442,884✔
1210
    AppLayerTxData *d = alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetTxData(tx);
128,442,884✔
1211
    SCReturnPtr(d, "AppLayerTxData");
128,442,884✔
1212
}
128,442,884✔
1213

1214
AppLayerStateData *AppLayerParserGetStateData(uint8_t ipproto, AppProto alproto, void *state)
1215
{
56,652✔
1216
    SCEnter();
56,652✔
1217
    if (alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetStateData) {
56,655✔
1218
        AppLayerStateData *d =
56,653✔
1219
                alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetStateData(state);
56,653✔
1220
        SCReturnPtr(d, "AppLayerStateData");
56,653✔
1221
    }
56,653✔
1222
    SCReturnPtr(NULL, "AppLayerStateData");
2,147,530,889✔
1223
}
56,652✔
1224

1225
void AppLayerParserApplyTxConfig(uint8_t ipproto, AppProto alproto,
1226
        void *state, void *tx, enum ConfigAction mode, AppLayerTxConfig config)
1227
{
5✔
1228
    SCEnter();
5✔
1229
    const int ipproto_map = FlowGetProtoMapping(ipproto);
5✔
1230
    if (alp_ctx.ctxs[alproto][ipproto_map].ApplyTxConfig) {
5✔
1231
        alp_ctx.ctxs[alproto][ipproto_map].ApplyTxConfig(state, tx, mode, config);
5✔
1232
    }
5✔
1233
    SCReturn;
5✔
1234
}
5✔
1235

1236
/***** General *****/
1237

1238
static inline void SetEOFFlags(AppLayerParserState *pstate, const uint8_t flags)
1239
{
785,177✔
1240
    if ((flags & (STREAM_EOF|STREAM_TOSERVER)) == (STREAM_EOF|STREAM_TOSERVER)) {
785,177✔
1241
        SCLogDebug("setting APP_LAYER_PARSER_EOF_TS");
14,628✔
1242
        SCAppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_EOF_TS);
14,628✔
1243
    } else if ((flags & (STREAM_EOF|STREAM_TOCLIENT)) == (STREAM_EOF|STREAM_TOCLIENT)) {
770,549✔
1244
        SCLogDebug("setting APP_LAYER_PARSER_EOF_TC");
14,051✔
1245
        SCAppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_EOF_TC);
14,051✔
1246
    }
14,051✔
1247
}
785,177✔
1248

1249
/** \internal
1250
 *  \brief create/close stream frames
1251
 *  On first invocation of TCP parser in a direction, create a <alproto>.stream frame.
1252
 *  On STREAM_EOF, set the final length. */
1253
static void HandleStreamFrames(Flow *f, StreamSlice stream_slice, const uint8_t *input,
1254
        const uint32_t input_len, const uint8_t flags)
1255
{
785,090✔
1256
    const uint8_t direction = (flags & STREAM_TOSERVER) ? 0 : 1;
785,090✔
1257
    AppLayerParserState *pstate = f->alparser;
785,090✔
1258

1259
    /* setup the generic stream frame */
1260
    if (((direction == 0 && (pstate->flags & APP_LAYER_PARSER_SFRAME_TS) == 0) ||
785,090✔
1261
                (direction == 1 && (pstate->flags & APP_LAYER_PARSER_SFRAME_TC) == 0)) &&
785,090✔
1262
            input != NULL && f->proto == IPPROTO_TCP) {
785,090✔
1263
        Frame *frame = AppLayerFrameGetLastOpenByType(f, direction, FRAME_STREAM_TYPE);
59,954✔
1264
        if (frame == NULL) {
59,956✔
1265
            int64_t frame_len = -1;
59,954✔
1266
            if (flags & STREAM_EOF)
59,954✔
1267
                frame_len = input_len;
1,654✔
1268

1269
            frame = AppLayerFrameNewByAbsoluteOffset(
59,954✔
1270
                    f, &stream_slice, stream_slice.offset, frame_len, direction, FRAME_STREAM_TYPE);
59,954✔
1271
            if (frame) {
59,954✔
1272
                SCLogDebug("opened: frame %p id %" PRIi64, frame, frame->id);
20,176✔
1273
                frame->flags = FRAME_FLAG_ENDS_AT_EOF; // TODO logic is not yet implemented
20,176✔
1274
                DEBUG_VALIDATE_BUG_ON(
20,176✔
1275
                        frame->id != 1); // should always be the first frame that is created
20,176✔
1276
            }
20,176✔
1277
            if (direction == 0) {
59,954✔
1278
                pstate->flags |= APP_LAYER_PARSER_SFRAME_TS;
31,706✔
1279
            } else {
31,706✔
1280
                pstate->flags |= APP_LAYER_PARSER_SFRAME_TC;
28,248✔
1281
            }
28,248✔
1282
        }
59,954✔
1283
    } else if (flags & STREAM_EOF) {
725,136✔
1284
        Frame *frame = AppLayerFrameGetLastOpenByType(f, direction, FRAME_STREAM_TYPE);
27,025✔
1285
        SCLogDebug("EOF closing: frame %p", frame);
27,025✔
1286
        if (frame) {
27,025✔
1287
            /* calculate final frame length */
1288
            int64_t slice_o = (int64_t)stream_slice.offset - (int64_t)frame->offset;
7,419✔
1289
            int64_t frame_len = slice_o + (int64_t)input_len;
7,419✔
1290
            SCLogDebug("%s: EOF frame->offset %" PRIu64 " -> %" PRIi64 ": o %" PRIi64,
7,419✔
1291
                    AppProtoToString(f->alproto), frame->offset, frame_len, slice_o);
7,419✔
1292
            frame->len = frame_len;
7,419✔
1293
        }
7,419✔
1294
    }
27,025✔
1295
}
785,090✔
1296

1297
static void Setup(Flow *f, const uint8_t direction, const uint8_t *input, uint32_t input_len,
1298
        const uint8_t flags, StreamSlice *as)
1299
{
785,035✔
1300
    memset(as, 0, sizeof(*as));
785,035✔
1301
    as->input = input;
785,035✔
1302
    as->input_len = input_len;
785,035✔
1303
    as->flags = flags;
785,035✔
1304

1305
    if (f->proto == IPPROTO_TCP && f->protoctx != NULL) {
785,035✔
1306
        TcpSession *ssn = f->protoctx;
702,288✔
1307
        TcpStream *stream = (direction & STREAM_TOSERVER) ? &ssn->client : &ssn->server;
702,288✔
1308
        as->offset = STREAM_APP_PROGRESS(stream);
702,288✔
1309
    }
702,288✔
1310
}
785,035✔
1311

1312
/** \retval int -1 in case of unrecoverable error. App-layer tracking stops for this flow.
1313
 *  \retval int 0 ok: we did not update app_progress
1314
 *  \retval int 1 ok: we updated app_progress */
1315
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto,
1316
                        uint8_t flags, const uint8_t *input, uint32_t input_len)
1317
{
800,709✔
1318
    SCEnter();
800,709✔
1319
#ifdef DEBUG_VALIDATION
1320
    BUG_ON(f->protomap != FlowGetProtoMapping(f->proto));
1321
#endif
1322
    AppLayerParserState *pstate = f->alparser;
800,709✔
1323
    AppLayerParserProtoCtx *p = &alp_ctx.ctxs[alproto][f->protomap];
800,709✔
1324
    StreamSlice stream_slice;
800,709✔
1325
    void *alstate = NULL;
800,709✔
1326
    uint64_t p_tx_cnt = 0;
800,709✔
1327
    uint32_t consumed = input_len;
800,709✔
1328
    const uint8_t direction = (flags & STREAM_TOSERVER) ? 0 : 1;
800,709✔
1329

1330
    /* we don't have the parser registered for this protocol */
1331
    if (p->StateAlloc == NULL) {
800,709✔
1332
        if (f->proto == IPPROTO_TCP) {
14,254✔
1333
            StreamTcpDisableAppLayer(f);
8✔
1334
        }
8✔
1335
        goto end;
14,254✔
1336
    }
14,254✔
1337

1338
    if (flags & STREAM_GAP) {
786,455✔
1339
        if (!(p->option_flags & APP_LAYER_PARSER_OPT_ACCEPT_GAPS)) {
9,878✔
1340
            SCLogDebug("app-layer parser does not accept gaps");
1,281✔
1341
            if (f->alstate != NULL && !FlowChangeProto(f)) {
1,281✔
1342
                SCAppLayerParserTriggerRawStreamInspection(f, direction);
1,274✔
1343
            }
1,274✔
1344
            AppLayerIncGapErrorCounter(tv, f);
1,281✔
1345
            goto error;
1,281✔
1346
        }
1,281✔
1347
    }
9,878✔
1348

1349
    /* Get the parser state (if any) */
1350
    if (pstate == NULL) {
785,174✔
1351
        f->alparser = pstate = AppLayerParserStateAlloc();
45,542✔
1352
        if (pstate == NULL) {
45,542✔
1353
            AppLayerIncAllocErrorCounter(tv, f);
×
1354
            goto error;
×
1355
        }
×
1356
    }
45,542✔
1357

1358
    SetEOFFlags(pstate, flags);
785,174✔
1359

1360
    alstate = f->alstate;
785,174✔
1361
    if (alstate == NULL || FlowChangeProto(f)) {
785,174✔
1362
        f->alstate = alstate = p->StateAlloc(alstate, f->alproto_orig);
45,533✔
1363
        if (alstate == NULL) {
45,533✔
1364
            AppLayerIncAllocErrorCounter(tv, f);
×
1365
            goto error;
×
1366
        }
×
1367
        SCLogDebug("alloced new app layer state %p (name %s)",
45,533✔
1368
                   alstate, AppLayerGetProtoName(f->alproto));
45,533✔
1369

1370
        /* set flow flags to state */
1371
        if (f->file_flags != 0) {
45,533✔
1372
            AppLayerStateData *sd = AppLayerParserGetStateData(f->proto, f->alproto, f->alstate);
33,377✔
1373
            if (sd != NULL) {
33,379✔
1374
                if ((sd->file_flags & f->file_flags) != f->file_flags) {
33,376✔
1375
                    SCLogDebug("state data: updating file_flags %04x with flow file_flags %04x",
33,376✔
1376
                            sd->file_flags, f->file_flags);
33,376✔
1377
                    sd->file_flags |= f->file_flags;
33,376✔
1378
                }
33,376✔
1379
            }
33,376✔
1380
        }
33,377✔
1381
    } else {
739,641✔
1382
        SCLogDebug("using existing app layer state %p (name %s))",
739,641✔
1383
                   alstate, AppLayerGetProtoName(f->alproto));
739,641✔
1384
    }
739,641✔
1385

1386
    p_tx_cnt = AppLayerParserGetTxCnt(f, f->alstate);
785,174✔
1387

1388
    /* invoke the recursive parser, but only on data. We may get empty msgs on EOF */
1389
    if (input_len > 0 || (flags & STREAM_EOF)) {
785,174✔
1390
        Setup(f, flags & (STREAM_TOSERVER | STREAM_TOCLIENT), input, input_len, flags,
785,056✔
1391
                &stream_slice);
785,056✔
1392
        HandleStreamFrames(f, stream_slice, input, input_len, flags);
785,056✔
1393

1394
#ifdef QA_SIMULATION
1395
        if (((stream_slice.flags & STREAM_TOSERVER) &&
1396
                    stream_slice.offset >= g_eps_applayer_error_offset_ts)) {
1397
            SCLogNotice("putting parser %s into an error state from toserver offset %" PRIu64,
1398
                    AppProtoToString(alproto), g_eps_applayer_error_offset_ts);
1399
            AppLayerIncParserErrorCounter(tv, f);
1400
            goto error;
1401
        }
1402
        if (((stream_slice.flags & STREAM_TOCLIENT) &&
1403
                    stream_slice.offset >= g_eps_applayer_error_offset_tc)) {
1404
            SCLogNotice("putting parser %s into an error state from toclient offset %" PRIu64,
1405
                    AppProtoToString(alproto), g_eps_applayer_error_offset_tc);
1406
            AppLayerIncParserErrorCounter(tv, f);
1407
            goto error;
1408
        }
1409
#endif
1410
        /* invoke the parser */
1411
        AppLayerResult res = p->Parser[direction](f, alstate, pstate, stream_slice,
785,056✔
1412
                alp_tctx->alproto_local_storage[alproto][f->protomap]);
785,056✔
1413
        if (res.status < 0) {
785,056✔
1414
            AppLayerIncParserErrorCounter(tv, f);
4,795✔
1415
            goto error;
4,795✔
1416
        } else if (res.status > 0) {
780,261✔
1417
            DEBUG_VALIDATE_BUG_ON(res.consumed > input_len);
12,409✔
1418
            DEBUG_VALIDATE_BUG_ON(res.needed + res.consumed < input_len);
12,409✔
1419
            DEBUG_VALIDATE_BUG_ON(res.needed == 0);
12,409✔
1420
            /* incomplete is only supported for TCP */
1421
            DEBUG_VALIDATE_BUG_ON(f->proto != IPPROTO_TCP);
12,409✔
1422

1423
            /* put protocol in error state on improper use of the
1424
             * return codes. */
1425
            if (res.consumed > input_len || res.needed + res.consumed < input_len) {
12,409✔
1426
                AppLayerIncInternalErrorCounter(tv, f);
×
1427
                goto error;
×
1428
            }
×
1429

1430
            if (f->proto == IPPROTO_TCP && f->protoctx != NULL) {
12,409✔
1431
                TcpSession *ssn = f->protoctx;
12,409✔
1432
                SCLogDebug("direction %d/%s", direction,
12,409✔
1433
                        (flags & STREAM_TOSERVER) ? "toserver" : "toclient");
12,409✔
1434
                if (direction == 0) {
12,409✔
1435
                    /* parser told us how much data it needs on top of what it
1436
                     * consumed. So we need tell stream engine how much we need
1437
                     * before the next call */
1438
                    ssn->client.data_required = res.needed;
4,227✔
1439
                    SCLogDebug("setting data_required %u", ssn->client.data_required);
4,227✔
1440
                } else {
8,182✔
1441
                    /* parser told us how much data it needs on top of what it
1442
                     * consumed. So we need tell stream engine how much we need
1443
                     * before the next call */
1444
                    ssn->server.data_required = res.needed;
8,182✔
1445
                    SCLogDebug("setting data_required %u", ssn->server.data_required);
8,182✔
1446
                }
8,182✔
1447
            }
12,409✔
1448
            consumed = res.consumed;
12,409✔
1449
        }
12,409✔
1450
    }
785,056✔
1451

1452
    /* set the packets to no inspection and reassembly if required */
1453
    if (pstate->flags & APP_LAYER_PARSER_NO_INSPECTION) {
780,379✔
1454
        AppLayerParserSetEOF(pstate);
1,473✔
1455

1456
        if (f->proto == IPPROTO_TCP) {
1,473✔
1457
            StreamTcpDisableAppLayer(f);
67✔
1458

1459
            /* Set the no reassembly flag for both the stream in this TcpSession */
1460
            if (pstate->flags & APP_LAYER_PARSER_NO_REASSEMBLY) {
67✔
1461
                /* Used only if it's TCP */
1462
                TcpSession *ssn = f->protoctx;
5✔
1463
                if (ssn != NULL) {
5✔
1464
                    StreamTcpSetSessionNoReassemblyFlag(ssn, 0);
5✔
1465
                    StreamTcpSetSessionNoReassemblyFlag(ssn, 1);
5✔
1466
                }
5✔
1467
            }
5✔
1468
            /* Set the bypass flag for both the stream in this TcpSession */
1469
            if (pstate->flags & APP_LAYER_PARSER_BYPASS_READY) {
67✔
1470
                /* Used only if it's TCP */
1471
                TcpSession *ssn = f->protoctx;
5✔
1472
                if (ssn != NULL) {
5✔
1473
                    StreamTcpSetSessionBypassFlag(ssn);
5✔
1474
                }
5✔
1475
            }
5✔
1476
        } else {
1,406✔
1477
            // for TCP, this is set after flushing
1478
            FlowSetNoPayloadInspectionFlag(f);
1,406✔
1479
        }
1,406✔
1480
    }
1,473✔
1481

1482
    /* In cases like HeartBleed for TLS we need to inspect AppLayer but not Payload */
1483
    if (!(f->flags & FLOW_NOPAYLOAD_INSPECTION) && pstate->flags & APP_LAYER_PARSER_NO_INSPECTION_PAYLOAD) {
780,379✔
1484
        FlowSetNoPayloadInspectionFlag(f);
3,647✔
1485
        /* Set the no reassembly flag for both the stream in this TcpSession */
1486
        if (f->proto == IPPROTO_TCP) {
3,647✔
1487
            /* Used only if it's TCP */
1488
            TcpSession *ssn = f->protoctx;
3,647✔
1489
            if (ssn != NULL) {
3,647✔
1490
                StreamTcpSetDisableRawReassemblyFlag(ssn, 0);
3,647✔
1491
                StreamTcpSetDisableRawReassemblyFlag(ssn, 1);
3,647✔
1492
            }
3,647✔
1493
        }
3,647✔
1494
    }
3,647✔
1495

1496
    /* get the diff in tx cnt for stats keeping */
1497
    uint64_t cur_tx_cnt = AppLayerParserGetTxCnt(f, f->alstate);
780,379✔
1498
    if (cur_tx_cnt > p_tx_cnt && tv) {
780,379✔
1499
        AppLayerIncTxCounter(tv, f, cur_tx_cnt - p_tx_cnt);
249,471✔
1500
    }
249,471✔
1501

1502
 end:
794,669✔
1503
    /* update app progress */
1504
    if (consumed != input_len && f->proto == IPPROTO_TCP && f->protoctx != NULL) {
794,669✔
1505
        TcpSession *ssn = f->protoctx;
12,378✔
1506
        StreamTcpUpdateAppLayerProgress(ssn, direction, consumed);
12,378✔
1507
        SCReturnInt(1);
12,378✔
1508
    }
12,378✔
1509

1510
    SCReturnInt(0);
794,669✔
1511
 error:
6,076✔
1512
    /* Set the no app layer inspection flag for both
1513
     * the stream in this Flow */
1514
    if (f->proto == IPPROTO_TCP) {
6,076✔
1515
        StreamTcpDisableAppLayer(f);
3,140✔
1516
    }
3,140✔
1517
    AppLayerParserSetEOF(pstate);
6,076✔
1518
    SCReturnInt(-1);
6,076✔
1519
}
794,669✔
1520

1521
void AppLayerParserSetEOF(AppLayerParserState *pstate)
1522
{
7,549✔
1523
    SCEnter();
7,549✔
1524

1525
    if (pstate == NULL)
7,549✔
1526
        goto end;
7✔
1527

1528
    SCLogDebug("setting APP_LAYER_PARSER_EOF_TC and APP_LAYER_PARSER_EOF_TS");
7,542✔
1529
    SCAppLayerParserStateSetFlag(pstate, (APP_LAYER_PARSER_EOF_TS | APP_LAYER_PARSER_EOF_TC));
7,542✔
1530

1531
 end:
7,549✔
1532
    SCReturn;
7,549✔
1533
}
7,542✔
1534

1535
/* return true if there are app parser decoder events. These are
1536
 * only the ones that are set during protocol detection. */
1537
bool AppLayerParserHasDecoderEvents(AppLayerParserState *pstate)
1538
{
6,020,770✔
1539
    SCEnter();
6,020,770✔
1540

1541
    if (pstate == NULL)
6,020,770✔
1542
        return false;
1,206,435✔
1543

1544
    const AppLayerDecoderEvents *decoder_events = AppLayerParserGetDecoderEvents(pstate);
4,814,335✔
1545
    if (decoder_events && decoder_events->cnt)
4,814,335✔
1546
        return true;
×
1547

1548
    /* if we have reached here, we don't have events */
1549
    return false;
4,814,335✔
1550
}
4,814,335✔
1551

1552
/** \brief simple way to globally test if a alproto is registered
1553
 *         and fully enabled in the configuration.
1554
 */
1555
int AppLayerParserIsEnabled(AppProto alproto)
1556
{
77,820✔
1557
    for (int i = 0; i < FLOW_PROTO_APPLAYER_MAX; i++) {
97,856✔
1558
        if (alp_ctx.ctxs[alproto][i].StateGetProgress != NULL) {
97,853✔
1559
            return 1;
77,817✔
1560
        }
77,817✔
1561
    }
97,853✔
1562
    return 0;
3✔
1563
}
77,820✔
1564

1565
int AppLayerParserProtocolHasLogger(uint8_t ipproto, AppProto alproto)
1566
{
183,005✔
1567
    SCEnter();
183,005✔
1568
    int ipproto_map = FlowGetProtoMapping(ipproto);
183,005✔
1569
    int r = (!alp_ctx.ctxs[alproto][ipproto_map].logger) ? 0 : 1;
183,005✔
1570
    SCReturnInt(r);
183,005✔
1571
}
183,005✔
1572

1573
LoggerId AppLayerParserProtocolGetLoggerBits(uint8_t ipproto, AppProto alproto)
1574
{
2,116,107✔
1575
    SCEnter();
2,116,107✔
1576
    const int ipproto_map = FlowGetProtoMapping(ipproto);
2,116,107✔
1577
    LoggerId r = alp_ctx.ctxs[alproto][ipproto_map].logger_bits;
2,116,107✔
1578
    SCReturnUInt(r);
2,116,107✔
1579
}
2,116,107✔
1580

1581
void SCAppLayerParserTriggerRawStreamInspection(Flow *f, int direction)
1582
{
271,783✔
1583
    SCEnter();
271,783✔
1584

1585
    SCLogDebug("f %p tcp %p direction %d", f, f ? f->protoctx : NULL, direction);
271,783✔
1586
    if (f != NULL && f->protoctx != NULL)
271,925✔
1587
        StreamTcpReassembleTriggerRawInspection(f->protoctx, direction);
267,416✔
1588

1589
    SCReturn;
271,783✔
1590
}
271,783✔
1591

1592
void SCAppLayerParserSetStreamDepth(uint8_t ipproto, AppProto alproto, uint32_t stream_depth)
1593
{
3,653✔
1594
    SCEnter();
3,653✔
1595

1596
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].stream_depth = stream_depth;
3,653✔
1597
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].internal_flags |=
3,653✔
1598
            APP_LAYER_PARSER_INT_STREAM_DEPTH_SET;
3,653✔
1599

1600
    SCReturn;
3,653✔
1601
}
3,653✔
1602

1603
uint32_t AppLayerParserGetStreamDepth(const Flow *f)
1604
{
58,889✔
1605
    SCReturnInt(alp_ctx.ctxs[f->alproto][f->protomap].stream_depth);
58,889✔
1606
}
58,889✔
1607

1608
void AppLayerParserSetStreamDepthFlag(uint8_t ipproto, AppProto alproto, void *state, uint64_t tx_id, uint8_t flags)
1609
{
745✔
1610
    SCEnter();
745✔
1611
    void *tx = NULL;
745✔
1612
    if (state != NULL) {
745✔
1613
        if ((tx = AppLayerParserGetTx(ipproto, alproto, state, tx_id)) != NULL) {
745✔
1614
            if (alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].SetStreamDepthFlag != NULL) {
745✔
1615
                alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].SetStreamDepthFlag(tx, flags);
171✔
1616
            }
171✔
1617
        }
745✔
1618
    }
745✔
1619
    SCReturn;
745✔
1620
}
745✔
1621

1622
/**
1623
 *  \param id progress value id to get the name for
1624
 *  \param direction STREAM_TOSERVER/STREAM_TOCLIENT
1625
 */
1626
int AppLayerParserGetStateIdByName(
1627
        uint8_t ipproto, AppProto alproto, const char *name, const uint8_t direction)
1628
{
665✔
1629
    if (alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetStateIdByName != NULL) {
665✔
1630
        return alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetStateIdByName(
573✔
1631
                name, direction);
573✔
1632
    } else {
573✔
1633
        return -1;
92✔
1634
    }
92✔
1635
}
665✔
1636

1637
/**
1638
 *  \param id progress value id to get the name for
1639
 *  \param direction STREAM_TOSERVER/STREAM_TOCLIENT
1640
 */
1641
const char *AppLayerParserGetStateNameById(
1642
        uint8_t ipproto, AppProto alproto, const int id, const uint8_t direction)
1643
{
468,327✔
1644
    if (alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetStateNameById != NULL) {
468,327✔
1645
        return alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetStateNameById(id, direction);
80,022✔
1646
    } else {
388,476✔
1647
        return NULL;
388,305✔
1648
    }
388,305✔
1649
}
468,327✔
1650

1651
int AppLayerParserGetFrameIdByName(uint8_t ipproto, AppProto alproto, const char *name)
1652
{
42,833✔
1653
    if (alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetFrameIdByName != NULL) {
42,833✔
1654
        return alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetFrameIdByName(name);
42,211✔
1655
    } else {
42,211✔
1656
        return -1;
622✔
1657
    }
622✔
1658
}
42,833✔
1659

1660
const char *AppLayerParserGetFrameNameById(uint8_t ipproto, AppProto alproto, const uint8_t id)
1661
{
3,225✔
1662
    if (alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetFrameNameById != NULL) {
3,225✔
1663
        return alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].GetFrameNameById(id);
3,186✔
1664
    } else {
3,186✔
1665
        return NULL;
39✔
1666
    }
39✔
1667
}
3,225✔
1668

1669
/***** Cleanup *****/
1670

1671
void AppLayerParserStateProtoCleanup(
1672
        uint8_t protomap, AppProto alproto, void *alstate, AppLayerParserState *pstate)
1673
{
93,537✔
1674
    SCEnter();
93,537✔
1675

1676
    AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[alproto][protomap];
93,537✔
1677

1678
    if (ctx->StateFree != NULL && alstate != NULL)
93,537✔
1679
        ctx->StateFree(alstate);
45,547✔
1680

1681
    /* free the app layer parser api state */
1682
    if (pstate != NULL)
93,537✔
1683
        AppLayerParserStateFree(pstate);
45,545✔
1684

1685
    SCReturn;
93,537✔
1686
}
93,537✔
1687

1688
void AppLayerParserStateCleanup(const Flow *f, void *alstate, AppLayerParserState *pstate)
1689
{
90,859✔
1690
    AppLayerParserStateProtoCleanup(f->protomap, f->alproto, alstate, pstate);
90,859✔
1691
}
90,859✔
1692

1693
static void ValidateParserProtoDump(AppProto alproto, uint8_t ipproto)
1694
{
×
1695
    uint8_t map = FlowGetProtoMapping(ipproto);
×
1696
    const AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[alproto][map];
×
1697
    printf("ERROR: incomplete app-layer registration\n");
×
1698
    printf("AppLayer protocol %s ipproto %u\n", AppProtoToString(alproto), ipproto);
×
1699
    printf("- option flags %"PRIx32"\n", ctx->option_flags);
×
1700
    printf("- first_data_dir %"PRIx8"\n", ctx->first_data_dir);
×
1701
    printf("Mandatory:\n");
×
1702
    printf("- Parser[0] %p Parser[1] %p\n", ctx->Parser[0], ctx->Parser[1]);
×
1703
    printf("- StateAlloc %p StateFree %p\n", ctx->StateAlloc, ctx->StateFree);
×
1704
    printf("- StateGetTx %p StateGetTxCnt %p StateTransactionFree %p\n",
×
1705
            ctx->StateGetTx, ctx->StateGetTxCnt, ctx->StateTransactionFree);
×
1706
    printf("- GetTxData %p\n", ctx->GetTxData);
×
1707
    printf("- GetStateData %p\n", ctx->GetStateData);
×
1708
    printf("- StateGetProgress %p\n", ctx->StateGetProgress);
×
1709
    printf("Optional:\n");
×
1710
    printf("- LocalStorageAlloc %p LocalStorageFree %p\n", ctx->LocalStorageAlloc, ctx->LocalStorageFree);
×
1711
    printf("- StateGetEventInfo %p StateGetEventInfoById %p\n", ctx->StateGetEventInfo,
×
1712
            ctx->StateGetEventInfoById);
×
1713
}
×
1714

1715
#define BOTH_SET(a, b) ((a) != NULL && (b) != NULL)
156,948✔
1716
#define BOTH_SET_OR_BOTH_UNSET(a, b) (((a) == NULL && (b) == NULL) || ((a) != NULL && (b) != NULL))
78,474✔
1717
#define THREE_SET(a, b, c) ((a) != NULL && (b) != NULL && (c) != NULL)
78,474✔
1718

1719
static void ValidateParserProto(AppProto alproto, uint8_t ipproto)
1720
{
174,478✔
1721
    uint8_t map = FlowGetProtoMapping(ipproto);
174,478✔
1722
    const AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[alproto][map];
174,478✔
1723

1724
    if (ctx->Parser[0] == NULL && ctx->Parser[1] == NULL)
174,478✔
1725
        return;
96,004✔
1726

1727
    if (!(BOTH_SET(ctx->Parser[0], ctx->Parser[1]))) {
78,474✔
1728
        goto bad;
×
1729
    }
×
1730
    if (!(BOTH_SET(ctx->StateFree, ctx->StateAlloc))) {
78,474✔
1731
        goto bad;
×
1732
    }
×
1733
    if (!(THREE_SET(ctx->StateGetTx, ctx->StateGetTxCnt, ctx->StateTransactionFree))) {
78,474✔
1734
        goto bad;
×
1735
    }
×
1736
    if (ctx->StateGetProgress == NULL) {
78,474✔
1737
        goto bad;
×
1738
    }
×
1739
    /* local storage is optional, but needs both set if used */
1740
    if (!(BOTH_SET_OR_BOTH_UNSET(ctx->LocalStorageAlloc, ctx->LocalStorageFree))) {
78,474✔
1741
        goto bad;
×
1742
    }
×
1743
    if (ctx->GetTxData == NULL) {
78,474✔
1744
        goto bad;
×
1745
    }
×
1746
    if (ctx->GetStateData == NULL) {
78,474✔
1747
        goto bad;
×
1748
    }
×
1749
    return;
78,474✔
1750
bad:
78,474✔
1751
    ValidateParserProtoDump(alproto, ipproto);
×
1752
    exit(EXIT_FAILURE);
×
1753
}
78,474✔
1754
#undef BOTH_SET
1755
#undef BOTH_SET_OR_BOTH_UNSET
1756
#undef THREE_SET
1757

1758
static void ValidateParser(AppProto alproto)
1759
{
87,239✔
1760
    ValidateParserProto(alproto, IPPROTO_TCP);
87,239✔
1761
    ValidateParserProto(alproto, IPPROTO_UDP);
87,239✔
1762
}
87,239✔
1763

1764
static void ValidateParsers(void)
1765
{
2,181✔
1766
    AppProto p = 0;
2,181✔
1767
    for (; p < g_alproto_max; p++) {
89,420✔
1768
        ValidateParser(p);
87,239✔
1769
    }
87,239✔
1770
}
2,181✔
1771

1772
#define ARRAY_CAP_STEP 16
4,360✔
1773
static void (**PreRegisteredCallbacks)(void) = NULL;
1774
static size_t preregistered_callbacks_nb = 0;
1775
static size_t preregistered_callbacks_cap = 0;
1776

1777
int SCAppLayerParserReallocCtx(AppProto alproto)
1778
{
2,180✔
1779
    if (alp_ctx.ctxs_len <= alproto && alproto < g_alproto_max) {
2,180✔
1780
        /* Realloc alp_ctx.ctxs, so that dynamic alproto can be treated as real/normal ones.
1781
         * In case we need to turn off dynamic alproto. */
1782
        void *tmp = SCRealloc(alp_ctx.ctxs, sizeof(AppLayerParserProtoCtx[FLOW_PROTO_MAX]) *
2,180✔
1783
                                                    (alp_ctx.ctxs_len + ARRAY_CAP_STEP));
2,180✔
1784
        if (unlikely(tmp == NULL)) {
2,180✔
1785
            FatalError("Unable to realloc alp_ctx.ctxs.");
×
1786
        }
×
1787
        alp_ctx.ctxs = tmp;
2,180✔
1788
        memset(&alp_ctx.ctxs[alp_ctx.ctxs_len], 0,
2,180✔
1789
                sizeof(AppLayerParserProtoCtx[FLOW_PROTO_MAX]) * ARRAY_CAP_STEP);
2,180✔
1790
        alp_ctx.ctxs_len += ARRAY_CAP_STEP;
2,180✔
1791
    }
2,180✔
1792
    return 0;
2,180✔
1793
}
2,180✔
1794

1795
int AppLayerParserPreRegister(void (*Register)(void))
1796
{
×
1797
    if (preregistered_callbacks_nb == preregistered_callbacks_cap) {
×
1798
        void *tmp = SCRealloc(PreRegisteredCallbacks,
×
1799
                sizeof(void *) * (preregistered_callbacks_cap + ARRAY_CAP_STEP));
×
1800
        if (tmp == NULL) {
×
1801
            return 1;
×
1802
        }
×
1803
        preregistered_callbacks_cap += ARRAY_CAP_STEP;
×
1804
        PreRegisteredCallbacks = tmp;
×
1805
    }
×
1806
    PreRegisteredCallbacks[preregistered_callbacks_nb] = Register;
×
1807
    preregistered_callbacks_nb++;
×
1808
    return 0;
×
1809
}
×
1810

1811
void AppLayerParserRegisterProtocolParsers(void)
1812
{
2,181✔
1813
    SCEnter();
2,181✔
1814

1815
    AppLayerConfig();
2,181✔
1816

1817
    RegisterHTPParsers();
2,181✔
1818
    RegisterSSLParsers();
2,181✔
1819
    SCRegisterDcerpcParser();
2,181✔
1820
    SCRegisterDcerpcUdpParser();
2,181✔
1821
    RegisterSMBParsers();
2,181✔
1822
    RegisterFTPParsers();
2,181✔
1823
    RegisterSSHParsers();
2,181✔
1824
    RegisterSMTPParsers();
2,181✔
1825
    SCRegisterDnsUdpParser();
2,181✔
1826
    SCRegisterDnsTcpParser();
2,181✔
1827
    SCRegisterBittorrentDhtUdpParser();
2,181✔
1828
    RegisterModbusParsers();
2,181✔
1829
    SCEnipRegisterParsers();
2,181✔
1830
    RegisterDNP3Parsers();
2,181✔
1831
    RegisterNFSTCPParsers();
2,181✔
1832
    RegisterNFSUDPParsers();
2,181✔
1833
    SCRegisterNtpParser();
2,181✔
1834
    RegisterTFTPParsers();
2,181✔
1835
    RegisterIKEParsers();
2,181✔
1836
    SCRegisterKrb5Parser();
2,181✔
1837
    SCRegisterDhcpParser();
2,181✔
1838
    SCRegisterSnmpParser();
2,181✔
1839
    SCRegisterSipParser();
2,181✔
1840
    SCRegisterQuicParser();
2,181✔
1841
    SCRegisterWebSocketParser();
2,181✔
1842
    SCRegisterLdapTcpParser();
2,181✔
1843
    SCRegisterLdapUdpParser();
2,181✔
1844
    SCRegisterMdnsParser();
2,181✔
1845
    SCRegisterTemplateParser();
2,181✔
1846
    SCRfbRegisterParser();
2,181✔
1847
    SCMqttRegisterParser();
2,181✔
1848
    SCRegisterPgsqlParser();
2,181✔
1849
    SCRegisterPop3Parser();
2,181✔
1850
    SCRegisterRdpParser();
2,181✔
1851
    RegisterHTTP2Parsers();
2,181✔
1852
    SCRegisterTelnetParser();
2,181✔
1853
    RegisterIMAPParsers();
2,181✔
1854

1855
    for (size_t i = 0; i < preregistered_callbacks_nb; i++) {
2,181✔
1856
        PreRegisteredCallbacks[i]();
×
1857
    }
×
1858

1859
    ValidateParsers();
2,181✔
1860
}
2,181✔
1861

1862
/* coccinelle: SCAppLayerParserStateSetFlag():2,2:APP_LAYER_PARSER_ */
1863
void SCAppLayerParserStateSetFlag(AppLayerParserState *pstate, uint16_t flag)
1864
{
165,569✔
1865
    SCEnter();
165,569✔
1866
    pstate->flags |= flag;
165,569✔
1867
    SCReturn;
165,569✔
1868
}
165,569✔
1869

1870
/* coccinelle: SCAppLayerParserStateIssetFlag():2,2:APP_LAYER_PARSER_ */
1871
uint16_t SCAppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint16_t flag)
1872
{
6,898,398✔
1873
    SCEnter();
6,898,398✔
1874
    SCReturnUInt(pstate->flags & flag);
6,898,398✔
1875
}
6,898,398✔
1876

1877
/***** Unittests *****/
1878

1879
#ifdef UNITTESTS
1880
#include "util-unittest-helper.h"
1881

1882
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto,
1883
                                  void (*RegisterUnittests)(void))
1884
{
1885
    SCEnter();
1886
    alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].RegisterUnittests = RegisterUnittests;
1887
    SCReturn;
1888
}
1889

1890
void AppLayerParserRegisterUnittests(void)
1891
{
1892
    SCEnter();
1893

1894
    int ip;
1895
    AppProto alproto;
1896
    AppLayerParserProtoCtx *ctx;
1897

1898
    for (ip = 0; ip < FLOW_PROTO_DEFAULT; ip++) {
1899
        for (alproto = 0; alproto < g_alproto_max; alproto++) {
1900
            ctx = &alp_ctx.ctxs[alproto][ip];
1901
            if (ctx->RegisterUnittests == NULL)
1902
                continue;
1903
            ctx->RegisterUnittests();
1904
        }
1905
    }
1906

1907
    SCReturn;
1908
}
1909

1910
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc