Coverage Report

Created: 2026-06-30 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/detect-csum.c
Line
Count
Source
1
/* Copyright (C) 2007-2022 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 Anoop Saldanha <anoopsaldanha@gmail.com>
22
 *
23
 * Implements checksum keyword.
24
 */
25
26
#include "suricata-common.h"
27
#include "decode.h"
28
29
#include "detect.h"
30
#include "detect-parse.h"
31
32
#include "detect-csum.h"
33
34
#include "util-unittest.h"
35
#include "util-debug.h"
36
37
#include "pkt-var.h"
38
#include "host.h"
39
#include "util-profiling.h"
40
#include "detect-engine-build.h"
41
42
11.2k
#define DETECT_CSUM_VALID   "valid"
43
5.26k
#define DETECT_CSUM_INVALID "invalid"
44
45
typedef struct DetectCsumData_ {
46
    /* Indicates if the csum-<protocol> keyword in a rule holds the
47
       keyvalue "valid" or "invalid" */
48
    int16_t valid;
49
} DetectCsumData;
50
51
/* prototypes for the "ipv4-csum" rule keyword */
52
static int DetectIPV4CsumMatch(DetectEngineThreadCtx *,
53
        Packet *, const Signature *, const SigMatchCtx *);
54
static int DetectIPV4CsumSetup(DetectEngineCtx *, Signature *, const char *);
55
static void DetectIPV4CsumFree(DetectEngineCtx *, void *);
56
57
/* prototypes for the "tcpv4-csum" rule keyword */
58
static int DetectTCPV4CsumMatch(DetectEngineThreadCtx *,
59
        Packet *, const Signature *, const SigMatchCtx *);
60
static int DetectTCPV4CsumSetup(DetectEngineCtx *, Signature *, const char *);
61
static void DetectTCPV4CsumFree(DetectEngineCtx *, void *);
62
63
/* prototypes for the "tcpv6-csum" rule keyword */
64
static int DetectTCPV6CsumMatch(DetectEngineThreadCtx *,
65
        Packet *, const Signature *, const SigMatchCtx *);
66
static int DetectTCPV6CsumSetup(DetectEngineCtx *, Signature *, const char *);
67
static void DetectTCPV6CsumFree(DetectEngineCtx *, void *);
68
69
/* prototypes for the "udpv4-csum" rule keyword */
70
static int DetectUDPV4CsumMatch(DetectEngineThreadCtx *,
71
        Packet *, const Signature *, const SigMatchCtx *);
72
static int DetectUDPV4CsumSetup(DetectEngineCtx *, Signature *, const char *);
73
static void DetectUDPV4CsumFree(DetectEngineCtx *, void *);
74
75
/* prototypes for the "udpv6-csum" rule keyword */
76
static int DetectUDPV6CsumMatch(DetectEngineThreadCtx *,
77
        Packet *, const Signature *, const SigMatchCtx *);
78
static int DetectUDPV6CsumSetup(DetectEngineCtx *, Signature *, const char *);
79
static void DetectUDPV6CsumFree(DetectEngineCtx *de_ctx, void *);
80
81
/* prototypes for the "icmpv4-csum" rule keyword */
82
static int DetectICMPV4CsumMatch(DetectEngineThreadCtx *,
83
        Packet *, const Signature *, const SigMatchCtx *);
84
static int DetectICMPV4CsumSetup(DetectEngineCtx *, Signature *, const char *);
85
static void DetectICMPV4CsumFree(DetectEngineCtx *, void *);
86
87
/* prototypes for the "icmpv6-csum" rule keyword */
88
static int DetectICMPV6CsumMatch(DetectEngineThreadCtx *,
89
        Packet *, const Signature *, const SigMatchCtx *);
90
static int DetectICMPV6CsumSetup(DetectEngineCtx *, Signature *, const char *);
91
static void DetectICMPV6CsumFree(DetectEngineCtx *, void *);
92
93
#ifdef UNITTESTS
94
static void DetectCsumRegisterTests(void);
95
#endif
96
97
/**
98
 * \brief Registers handlers for all the checksum keywords.  The checksum
99
 *        keywords that are registered are ipv4-sum, tcpv4-csum, tcpv6-csum,
100
 *        udpv4-csum, udpv6-csum, icmpv4-csum and icmpv6-csum.
101
 *
102
 *        Each of the checksum keywords implemented here takes 2 arguments -
103
 *        "valid" or "invalid".  If the rule keyword in the signature is
104
 *        specified as "valid", the Match function would return TRUE if the
105
 *        checksum for that particular packet and protocol is valid.  Similarly
106
 *        for "invalid".
107
 *
108
 *        The Setup functions takes 4 arguments -
109
 *
110
 *        DetectEngineCtx * (de_ctx) - A pointer to the detection engine context
111
 *        Signature *(s) - Pointer to signature for the current Signature being
112
 *                         parsed from the rules
113
 *        SigMatchCtx * (m) - Pointer to the head of the SigMatchs added to the
114
 *                         current Signature being parsed
115
 *        char * (csum_str) - Pointer to a string holding the keyword value
116
 *
117
 *        The Setup function returns 0 if it successfully parses the keyword
118
 *        value, and -1 otherwise.
119
 *
120
 *        The Match function takes 5 arguments -
121
 *
122
 *        ThreadVars * (t) - Pointer to the tv for the detection module instance
123
 *        DetectEngineThreadCtx * (det_ctx) - Pointer to the detection engine
124
 *                                            thread context
125
 *        Packet * (p) - Pointer to the Packet currently being handled
126
 *        Signature * (s) - Pointer to the Signature, the packet is being
127
 *                          currently matched with
128
 *        SigMatchCtx * (m) - Pointer to the keyword structure from the above
129
 *                         Signature, the Packet is being currently matched
130
 *                         with
131
 *
132
 *        The Match function returns 1 if the Packet contents match the keyword,
133
 *        and 0 otherwise
134
 *
135
 *        The Free function takes a single argument -
136
 *
137
 *        void * (ptr) - Pointer to the DetectCsumData for a keyword
138
 */
139
void DetectCsumRegister (void)
140
75
{
141
75
    sigmatch_table[DETECT_IPV4_CSUM].name = "ipv4-csum";
142
75
    sigmatch_table[DETECT_IPV4_CSUM].Match = DetectIPV4CsumMatch;
143
75
    sigmatch_table[DETECT_IPV4_CSUM].Setup = DetectIPV4CsumSetup;
144
75
    sigmatch_table[DETECT_IPV4_CSUM].Free  = DetectIPV4CsumFree;
145
#ifdef UNITTESTS
146
    sigmatch_table[DETECT_IPV4_CSUM].RegisterTests = DetectCsumRegisterTests;
147
#endif
148
149
75
    sigmatch_table[DETECT_TCPV4_CSUM].name = "tcpv4-csum";
150
75
    sigmatch_table[DETECT_TCPV4_CSUM].Match = DetectTCPV4CsumMatch;
151
75
    sigmatch_table[DETECT_TCPV4_CSUM].Setup = DetectTCPV4CsumSetup;
152
75
    sigmatch_table[DETECT_TCPV4_CSUM].Free  = DetectTCPV4CsumFree;
153
154
75
    sigmatch_table[DETECT_TCPV6_CSUM].name = "tcpv6-csum";
155
75
    sigmatch_table[DETECT_TCPV6_CSUM].Match = DetectTCPV6CsumMatch;
156
75
    sigmatch_table[DETECT_TCPV6_CSUM].Setup = DetectTCPV6CsumSetup;
157
75
    sigmatch_table[DETECT_TCPV6_CSUM].Free  = DetectTCPV6CsumFree;
158
159
75
    sigmatch_table[DETECT_UDPV4_CSUM].name = "udpv4-csum";
160
75
    sigmatch_table[DETECT_UDPV4_CSUM].Match = DetectUDPV4CsumMatch;
161
75
    sigmatch_table[DETECT_UDPV4_CSUM].Setup = DetectUDPV4CsumSetup;
162
75
    sigmatch_table[DETECT_UDPV4_CSUM].Free  = DetectUDPV4CsumFree;
163
164
75
    sigmatch_table[DETECT_UDPV6_CSUM].name = "udpv6-csum";
165
75
    sigmatch_table[DETECT_UDPV6_CSUM].Match = DetectUDPV6CsumMatch;
166
75
    sigmatch_table[DETECT_UDPV6_CSUM].Setup = DetectUDPV6CsumSetup;
167
75
    sigmatch_table[DETECT_UDPV6_CSUM].Free  = DetectUDPV6CsumFree;
168
169
75
    sigmatch_table[DETECT_ICMPV4_CSUM].name = "icmpv4-csum";
170
75
    sigmatch_table[DETECT_ICMPV4_CSUM].Match = DetectICMPV4CsumMatch;
171
75
    sigmatch_table[DETECT_ICMPV4_CSUM].Setup = DetectICMPV4CsumSetup;
172
75
    sigmatch_table[DETECT_ICMPV4_CSUM].Free  = DetectICMPV4CsumFree;
173
174
75
    sigmatch_table[DETECT_ICMPV6_CSUM].name = "icmpv6-csum";
175
75
    sigmatch_table[DETECT_ICMPV6_CSUM].Match = DetectICMPV6CsumMatch;
176
75
    sigmatch_table[DETECT_ICMPV6_CSUM].Setup = DetectICMPV6CsumSetup;
177
75
    sigmatch_table[DETECT_ICMPV6_CSUM].Free  = DetectICMPV6CsumFree;
178
75
}
179
180
/**
181
 * \brief Validates and parses the argument supplied with the checksum keyword.
182
 *        Accepts strings both with and without quotes, i.e. valid, \"valid\",
183
 *        invalid and \"invalid\"
184
 *
185
 * \param key Pointer to a const character string holding the csum keyword value
186
 * \param cd  Pointer to the DetectCsumData structure that holds the keyword
187
 *            value sent as argument
188
 *
189
 * \retval 1 the keyvalue has been parsed successfully
190
 * \retval 0 error
191
 */
192
static int DetectCsumParseArg(const char *key, DetectCsumData *cd)
193
5.86k
{
194
5.86k
    char *str;
195
196
5.86k
    if (key[0] == '\"' && key[strlen(key) - 1] == '\"') {
197
0
        str = SCStrdup(key + 1);
198
0
        if (unlikely(str == NULL)) {
199
0
            goto error;
200
0
        }
201
0
        str[strlen(key) - 2] = '\0';
202
5.86k
    } else {
203
5.86k
        str = SCStrdup(key);
204
5.86k
        if (unlikely(str == NULL)) {
205
0
            goto error;
206
0
        }
207
5.86k
    }
208
209
5.86k
    if (strcasecmp(str, DETECT_CSUM_VALID) == 0 ||
210
5.36k
        strcasecmp(str, DETECT_CSUM_INVALID) == 0) {
211
5.36k
        cd->valid = (strcasecmp(key, DETECT_CSUM_VALID) == 0);
212
5.36k
        SCFree(str);
213
5.36k
        return 1;
214
5.36k
    }
215
216
497
error:
217
497
    if (str != NULL)
218
497
        SCFree(str);
219
497
    return 0;
220
5.86k
}
221
222
/**
223
 * \brief Checks if the packet sent as the argument, has a valid or invalid
224
 *        ipv4 checksum, based on whether ipv4-csum option for this rule
225
 *        has been supplied with "valid" or "invalid" argument
226
 *
227
 * \param t       Pointer to the tv for this detection module instance
228
 * \param det_ctx Pointer to the detection engine thread context
229
 * \param p       Pointer to the Packet currently being matched
230
 * \param s       Pointer to the Signature, the packet is being currently
231
 *                matched with
232
 * \param m       Pointer to the keyword_structure(SigMatch) from the above
233
 *                Signature, the Packet is being currently matched with
234
 *
235
 * \retval 1 if the Packet contents match the keyword option; 0 otherwise
236
 */
237
static int DetectIPV4CsumMatch(DetectEngineThreadCtx *det_ctx,
238
        Packet *p, const Signature *s, const SigMatchCtx *ctx)
239
27.6k
{
240
27.6k
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
241
242
27.6k
    if (p->ip4h == NULL || PKT_IS_PSEUDOPKT(p))
243
6.54k
        return 0;
244
245
21.1k
    if (p->flags & PKT_IGNORE_CHECKSUM) {
246
0
        return cd->valid;
247
0
    }
248
249
21.1k
    if (p->level3_comp_csum == -1)
250
20.8k
        p->level3_comp_csum = IPV4Checksum((uint16_t *)p->ip4h,
251
20.8k
                                           IPV4_GET_HLEN(p),
252
20.8k
                                           p->ip4h->ip_csum);
253
254
21.1k
    if (p->level3_comp_csum == 0 && cd->valid == 1)
255
0
        return 1;
256
21.1k
    else if (p->level3_comp_csum != 0 && cd->valid == 0)
257
3.50k
        return 1;
258
17.6k
    else
259
17.6k
        return 0;
260
21.1k
}
261
262
/**
263
 * \brief Creates a SigMatch for the ipv4-csum keyword being sent as argument,
264
 *        and appends it to the Signature(s).  Accepts 2 values for the
265
 *        keyword - "valid" and "invalid", both with and without quotes
266
 *
267
 * \param de_ctx    Pointer to the detection engine context
268
 * \param s         Pointer to signature for the current Signature being parsed
269
 *                  from the rules
270
 * \param csum_str  Pointer to the string holding the keyword value
271
 *
272
 * \retval 0 on success, -1 on failure
273
 */
274
static int DetectIPV4CsumSetup(DetectEngineCtx *de_ctx, Signature *s, const char *csum_str)
275
791
{
276
791
    DetectCsumData *cd = NULL;
277
791
    SigMatch *sm = NULL;
278
279
    //printf("DetectCsumSetup: \'%s\'\n", csum_str);
280
281
791
    sm = SigMatchAlloc();
282
791
    if (sm == NULL)
283
0
        goto error;
284
285
791
    sm->type = DETECT_IPV4_CSUM;
286
287
791
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
288
0
        goto error;
289
791
    memset(cd, 0, sizeof(DetectCsumData));
290
291
791
    if (DetectCsumParseArg(csum_str, cd) == 0)
292
39
        goto error;
293
294
752
    sm->ctx = (SigMatchCtx *)cd;
295
296
752
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
297
298
752
    return 0;
299
300
39
error:
301
39
    if (cd != NULL) DetectIPV4CsumFree(de_ctx, cd);
302
39
    if (sm != NULL) SCFree(sm);
303
304
39
    return -1;
305
791
}
306
307
static void DetectIPV4CsumFree(DetectEngineCtx *de_ctx, void *ptr)
308
791
{
309
791
    DetectCsumData *cd = (DetectCsumData *)ptr;
310
311
791
    if (cd != NULL)
312
791
        SCFree(cd);
313
314
791
    return;
315
791
}
316
317
/**
318
 * \brief Checks if the packet sent as the argument, has a valid or invalid
319
 *        tcpv4 checksum, based on whether tcpv4-csum option for this rule
320
 *        has been supplied with "valid" or "invalid" argument
321
 *
322
 * \param t       Pointer to the tv for this detection module instance
323
 * \param det_ctx Pointer to the detection engine thread context
324
 * \param p       Pointer to the Packet currently being matched
325
 * \param s       Pointer to the Signature, the packet is being currently
326
 *                matched with
327
 * \param m       Pointer to the keyword_structure(SigMatch) from the above
328
 *                Signature, the Packet is being currently matched with
329
 *
330
 * \retval 1 if the Packet contents match the keyword option; 0 otherwise
331
 */
332
static int DetectTCPV4CsumMatch(DetectEngineThreadCtx *det_ctx,
333
        Packet *p, const Signature *s, const SigMatchCtx *ctx)
334
16.9k
{
335
16.9k
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
336
337
16.9k
    if (p->ip4h == NULL || p->tcph == NULL || p->proto != IPPROTO_TCP || PKT_IS_PSEUDOPKT(p))
338
1.57k
        return 0;
339
340
15.3k
    if (p->flags & PKT_IGNORE_CHECKSUM) {
341
0
        return cd->valid;
342
0
    }
343
344
15.3k
    if (p->level4_comp_csum == -1)
345
15.3k
        p->level4_comp_csum = TCPChecksum(p->ip4h->s_ip_addrs,
346
15.3k
                                          (uint16_t *)p->tcph,
347
15.3k
                                          (p->payload_len +
348
15.3k
                                              TCP_GET_HLEN(p)),
349
15.3k
                                          p->tcph->th_sum);
350
351
15.3k
    if (p->level4_comp_csum == 0 && cd->valid == 1)
352
0
        return 1;
353
15.3k
    else if (p->level4_comp_csum != 0 && cd->valid == 0)
354
9.54k
        return 1;
355
5.82k
    else
356
5.82k
        return 0;
357
15.3k
}
358
359
/**
360
 * \brief Creates a SigMatch for the tcpv4-csum keyword being sent as argument,
361
 *        and appends it to the Signature(s).  Accepts 2 values for the
362
 *        keyword - "valid" and "invalid", both with and without quotes
363
 *
364
 * \param de_ctx    Pointer to the detection engine context
365
 * \param s         Pointer to signature for the current Signature being parsed
366
 *                  from the rules
367
 * \param csum_str  Pointer to the string holding the keyword value
368
 *
369
 * \retval 0 on success, -1 on failure
370
 */
371
static int DetectTCPV4CsumSetup(DetectEngineCtx *de_ctx, Signature *s, const char *csum_str)
372
783
{
373
783
    DetectCsumData *cd = NULL;
374
783
    SigMatch *sm = NULL;
375
376
    //printf("DetectCsumSetup: \'%s\'\n", csum_str);
377
378
783
    sm = SigMatchAlloc();
379
783
    if (sm == NULL)
380
0
        goto error;
381
382
783
    sm->type = DETECT_TCPV4_CSUM;
383
384
783
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
385
0
        goto error;
386
783
    memset(cd, 0, sizeof(DetectCsumData));
387
388
783
    if (DetectCsumParseArg(csum_str, cd) == 0)
389
39
        goto error;
390
391
744
    sm->ctx = (SigMatchCtx *)cd;
392
393
744
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
394
395
744
    return 0;
396
397
39
error:
398
39
    if (cd != NULL) DetectTCPV4CsumFree(de_ctx, cd);
399
39
    if (sm != NULL) SCFree(sm);
400
401
39
    return -1;
402
783
}
403
404
static void DetectTCPV4CsumFree(DetectEngineCtx *de_ctx, void *ptr)
405
783
{
406
783
    DetectCsumData *cd = (DetectCsumData *)ptr;
407
408
783
    if (cd != NULL)
409
783
        SCFree(cd);
410
411
783
    return;
412
783
}
413
414
/**
415
 * \brief Checks if the packet sent as the argument, has a valid or invalid
416
 *        tcpv6 checksum, based on whether tcpv6-csum option for this rule
417
 *        has been supplied with "valid" or "invalid" argument
418
 *
419
 * \param t       Pointer to the tv for this detection module instance
420
 * \param det_ctx Pointer to the detection engine thread context
421
 * \param p       Pointer to the Packet currently being matched
422
 * \param s       Pointer to the Signature, the packet is being currently
423
 *                matched with
424
 * \param m       Pointer to the keyword_structure(SigMatch) from the above
425
 *                Signature, the Packet is being currently matched with
426
 *
427
 * \retval 1 if the Packet contents match the keyword option; 0 otherwise
428
 */
429
static int DetectTCPV6CsumMatch(DetectEngineThreadCtx *det_ctx,
430
        Packet *p, const Signature *s, const SigMatchCtx *ctx)
431
3.13k
{
432
3.13k
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
433
434
3.13k
    if (p->ip6h == NULL || p->tcph == NULL || p->proto != IPPROTO_TCP || PKT_IS_PSEUDOPKT(p))
435
2.60k
        return 0;
436
437
539
    if (p->flags & PKT_IGNORE_CHECKSUM) {
438
0
        return cd->valid;
439
0
    }
440
441
539
    if (p->level4_comp_csum == -1)
442
539
        p->level4_comp_csum = TCPV6Checksum(p->ip6h->s_ip6_addrs,
443
539
                                            (uint16_t *)p->tcph,
444
539
                                            (p->payload_len +
445
539
                                                TCP_GET_HLEN(p)),
446
539
                                            p->tcph->th_sum);
447
448
539
    if (p->level4_comp_csum == 0 && cd->valid == 1)
449
0
        return 1;
450
539
    else if (p->level4_comp_csum != 0 && cd->valid == 0)
451
539
        return 1;
452
0
    else
453
0
        return 0;
454
539
}
455
456
/**
457
 * \brief Creates a SigMatch for the tcpv6-csum keyword being sent as argument,
458
 *        and appends it to the Signature(s).  Accepts 2 values for the
459
 *        keyword - "valid" and "invalid", both with and without quotes
460
 *
461
 * \param de_ctx    Pointer to the detection engine context
462
 * \param s         Pointer to signature for the current Signature being parsed
463
 *                  from the rules
464
 * \param csum_str  Pointer to the string holding the keyword value
465
 *
466
 * \retval 0 on success, -1 on failure
467
 */
468
static int DetectTCPV6CsumSetup(DetectEngineCtx *de_ctx, Signature *s, const char *csum_str)
469
1.29k
{
470
1.29k
    DetectCsumData *cd = NULL;
471
1.29k
    SigMatch *sm = NULL;
472
473
    //printf("DetectCsumSetup: \'%s\'\n", csum_str);
474
475
1.29k
    sm = SigMatchAlloc();
476
1.29k
    if (sm == NULL)
477
0
        goto error;
478
479
1.29k
    sm->type = DETECT_TCPV6_CSUM;
480
481
1.29k
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
482
0
        goto error;
483
1.29k
    memset(cd, 0, sizeof(DetectCsumData));
484
485
1.29k
    if (DetectCsumParseArg(csum_str, cd) == 0)
486
128
        goto error;
487
488
1.16k
    sm->ctx = (SigMatchCtx *)cd;
489
490
1.16k
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
491
492
1.16k
    return 0;
493
494
128
error:
495
128
    if (cd != NULL) DetectTCPV6CsumFree(de_ctx, cd);
496
128
    if (sm != NULL) SCFree(sm);
497
498
128
    return -1;
499
1.29k
}
500
501
static void DetectTCPV6CsumFree(DetectEngineCtx *de_ctx, void *ptr)
502
1.29k
{
503
1.29k
    DetectCsumData *cd = (DetectCsumData *)ptr;
504
505
1.29k
    if (cd != NULL)
506
1.29k
        SCFree(cd);
507
508
1.29k
    return;
509
1.29k
}
510
511
/**
512
 * \brief Checks if the packet sent as the argument, has a valid or invalid
513
 *        udpv4 checksum, based on whether udpv4-csum option for this rule
514
 *        has been supplied with "valid" or "invalid" argument
515
 *
516
 * \param t       Pointer to the tv for this detection module instance
517
 * \param det_ctx Pointer to the detection engine thread context
518
 * \param p       Pointer to the Packet currently being matched
519
 * \param s       Pointer to the Signature, the packet is being currently
520
 *                matched with
521
 * \param m       Pointer to the keyword_structure(SigMatch) from the above
522
 *                Signature, the Packet is being currently matched with
523
 *
524
 * \retval 1 if the Packet contents match the keyword option; 0 otherwise
525
 */
526
static int DetectUDPV4CsumMatch(DetectEngineThreadCtx *det_ctx,
527
        Packet *p, const Signature *s, const SigMatchCtx *ctx)
528
628
{
529
628
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
530
531
628
    if (p->ip4h == NULL || p->udph == NULL || p->proto != IPPROTO_UDP || PKT_IS_PSEUDOPKT(p) || p->udph->uh_sum == 0)
532
208
        return 0;
533
534
420
    if (p->flags & PKT_IGNORE_CHECKSUM) {
535
0
        return cd->valid;
536
0
    }
537
538
420
    if (p->level4_comp_csum == -1)
539
419
        p->level4_comp_csum = UDPV4Checksum(p->ip4h->s_ip_addrs,
540
419
                                            (uint16_t *)p->udph,
541
419
                                            (p->payload_len +
542
419
                                                UDP_HEADER_LEN),
543
419
                                            p->udph->uh_sum);
544
545
420
    if (p->level4_comp_csum == 0 && cd->valid == 1)
546
0
        return 1;
547
420
    else if (p->level4_comp_csum != 0 && cd->valid == 0)
548
46
        return 1;
549
374
    else
550
374
        return 0;
551
420
}
552
553
/**
554
 * \brief Creates a SigMatch for the udpv4-csum keyword being sent as argument,
555
 *        and appends it to the Signature(s).  Accepts 2 values for the
556
 *        keyword - "valid" and "invalid", both with and without quotes
557
 *
558
 * \param de_ctx    Pointer to the detection engine context
559
 * \param s         Pointer to signature for the current Signature being parsed
560
 *                  from the rules
561
 * \param csum_str  Pointer to the string holding the keyword value
562
 *
563
 * \retval 0 on success, -1 on failure
564
 */
565
static int DetectUDPV4CsumSetup(DetectEngineCtx *de_ctx, Signature *s, const char *csum_str)
566
649
{
567
649
    DetectCsumData *cd = NULL;
568
649
    SigMatch *sm = NULL;
569
570
    //printf("DetectCsumSetup: \'%s\'\n", csum_str);
571
572
649
    sm = SigMatchAlloc();
573
649
    if (sm == NULL)
574
0
        goto error;
575
576
649
    sm->type = DETECT_UDPV4_CSUM;
577
578
649
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
579
0
        goto error;
580
649
    memset(cd, 0, sizeof(DetectCsumData));
581
582
649
    if (DetectCsumParseArg(csum_str, cd) == 0)
583
22
        goto error;
584
585
627
    sm->ctx = (SigMatchCtx *)cd;
586
587
627
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
588
589
627
    return 0;
590
591
22
error:
592
22
    if (cd != NULL) DetectUDPV4CsumFree(de_ctx, cd);
593
22
    if (sm != NULL) SCFree(sm);
594
595
22
    return -1;
596
649
}
597
598
static void DetectUDPV4CsumFree(DetectEngineCtx *de_ctx, void *ptr)
599
649
{
600
649
    DetectCsumData *cd = (DetectCsumData *)ptr;
601
602
649
    if (cd != NULL)
603
649
        SCFree(cd);
604
605
649
    return;
606
649
}
607
608
/**
609
 * \brief Checks if the packet sent as the argument, has a valid or invalid
610
 *        udpv6 checksum, based on whether udpv6-csum option for this rule
611
 *        has been supplied with "valid" or "invalid" argument
612
 *
613
 * \param t       Pointer to the tv for this detection module instance
614
 * \param det_ctx Pointer to the detection engine thread context
615
 * \param p       Pointer to the Packet currently being matched
616
 * \param s       Pointer to the Signature, the packet is being currently
617
 *                matched with
618
 * \param m       Pointer to the keyword_structure(SigMatch) from the above
619
 *                Signature, the Packet is being currently matched with
620
 *
621
 * \retval 1 if the Packet contents match the keyword option; 0 otherwise
622
 */
623
static int DetectUDPV6CsumMatch(DetectEngineThreadCtx *det_ctx,
624
        Packet *p, const Signature *s, const SigMatchCtx *ctx)
625
575
{
626
575
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
627
628
575
    if (p->ip6h == NULL || p->udph == NULL || p->proto != IPPROTO_UDP || PKT_IS_PSEUDOPKT(p))
629
507
        return 0;
630
631
68
    if (p->flags & PKT_IGNORE_CHECKSUM) {
632
0
        return cd->valid;
633
0
    }
634
635
68
    if (p->level4_comp_csum == -1)
636
68
        p->level4_comp_csum = UDPV6Checksum(p->ip6h->s_ip6_addrs,
637
68
                                            (uint16_t *)p->udph,
638
68
                                            (p->payload_len +
639
68
                                                UDP_HEADER_LEN),
640
68
                                            p->udph->uh_sum);
641
642
68
    if (p->level4_comp_csum == 0 && cd->valid == 1)
643
0
        return 1;
644
68
    else if (p->level4_comp_csum != 0 && cd->valid == 0)
645
2
        return 1;
646
66
    else
647
66
        return 0;
648
68
}
649
650
/**
651
 * \brief Creates a SigMatch for the udpv6-csum keyword being sent as argument,
652
 *        and appends it to the Signature(s).  Accepts 2 values for the
653
 *        keyword - "valid" and "invalid", both with and without quotes
654
 *
655
 * \param de_ctx    Pointer to the detection engine context
656
 * \param s         Pointer to signature for the current Signature being parsed
657
 *                  from the rules
658
 * \param csum_str  Pointer to the string holding the keyword value
659
 *
660
 * \retval 0 on success, -1 on failure
661
 */
662
static int DetectUDPV6CsumSetup(DetectEngineCtx *de_ctx, Signature *s, const char *csum_str)
663
602
{
664
602
    DetectCsumData *cd = NULL;
665
602
    SigMatch *sm = NULL;
666
667
    //printf("DetectCsumSetup: \'%s\'\n", csum_str);
668
669
602
    sm = SigMatchAlloc();
670
602
    if (sm == NULL)
671
0
        goto error;
672
673
602
    sm->type = DETECT_UDPV6_CSUM;
674
675
602
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
676
0
        goto error;
677
602
    memset(cd, 0, sizeof(DetectCsumData));
678
679
602
    if (DetectCsumParseArg(csum_str, cd) == 0)
680
131
        goto error;
681
682
471
    sm->ctx = (void *)cd;
683
684
471
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
685
686
471
    return 0;
687
688
131
error:
689
131
    if (cd != NULL) DetectUDPV6CsumFree(de_ctx, cd);
690
131
    if (sm != NULL) SCFree(sm);
691
692
131
    return -1;
693
602
}
694
695
static void DetectUDPV6CsumFree(DetectEngineCtx *de_ctx, void *ptr)
696
602
{
697
602
    DetectCsumData *cd = (DetectCsumData *)ptr;
698
699
602
    if (cd != NULL)
700
602
        SCFree(cd);
701
702
602
    return;
703
602
}
704
705
/**
706
 * \brief Checks if the packet sent as the argument, has a valid or invalid
707
 *        icmpv4 checksum, based on whether icmpv4-csum option for this rule
708
 *        has been supplied with "valid" or "invalid" argument
709
 *
710
 * \param t       Pointer to the tv for this detection module instance
711
 * \param det_ctx Pointer to the detection engine thread context
712
 * \param p       Pointer to the Packet currently being matched
713
 * \param s       Pointer to the Signature, the packet is being currently
714
 *                matched with
715
 * \param m       Pointer to the keyword_structure(SigMatch) from the above
716
 *                Signature, the Packet is being currently matched with
717
 *
718
 * \retval 1 if the Packet contents match the keyword option; 0 otherwise
719
 */
720
static int DetectICMPV4CsumMatch(DetectEngineThreadCtx *det_ctx,
721
        Packet *p, const Signature *s, const SigMatchCtx *ctx)
722
1.04k
{
723
1.04k
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
724
725
1.04k
    if (p->ip4h == NULL || p->icmpv4h == NULL || p->proto != IPPROTO_ICMP || PKT_IS_PSEUDOPKT(p))
726
1.03k
        return 0;
727
728
6
    if (p->flags & PKT_IGNORE_CHECKSUM) {
729
0
        return cd->valid;
730
0
    }
731
732
6
    if (p->level4_comp_csum == -1)
733
6
        p->level4_comp_csum = ICMPV4CalculateChecksum((uint16_t *)p->icmpv4h,
734
6
                                                      SCNtohs(IPV4_GET_RAW_IPLEN(p->ip4h)) -
735
6
                                                      IPV4_GET_RAW_HLEN(p->ip4h) * 4);
736
737
6
    if (p->level4_comp_csum == p->icmpv4h->checksum && cd->valid == 1)
738
0
        return 1;
739
6
    else if (p->level4_comp_csum != p->icmpv4h->checksum && cd->valid == 0)
740
6
        return 1;
741
0
    else
742
0
        return 0;
743
6
}
744
745
/**
746
 * \brief Creates a SigMatch for the icmpv4-csum keyword being sent as argument,
747
 *        and appends it to the Signature(s).  Accepts 2 values for the
748
 *        keyword - "valid" and "invalid", both with and without quotes
749
 *
750
 * \param de_ctx    Pointer to the detection engine context
751
 * \param s         Pointer to signature for the current Signature being parsed
752
 *                  from the rules
753
 * \param csum_str  Pointer to the string holding the keyword value
754
 *
755
 * \retval 0 on success, -1 on failure
756
 */
757
static int DetectICMPV4CsumSetup(DetectEngineCtx *de_ctx, Signature *s, const char *csum_str)
758
759
{
759
759
    DetectCsumData *cd = NULL;
760
759
    SigMatch *sm = NULL;
761
762
    //printf("DetectCsumSetup: \'%s\'\n", csum_str);
763
764
759
    sm = SigMatchAlloc();
765
759
    if (sm == NULL)
766
0
        goto error;
767
768
759
    sm->type = DETECT_ICMPV4_CSUM;
769
770
759
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
771
0
        goto error;
772
759
    memset(cd, 0, sizeof(DetectCsumData));
773
774
759
    if (DetectCsumParseArg(csum_str, cd) == 0)
775
62
        goto error;
776
777
697
    sm->ctx = (SigMatchCtx *)cd;
778
779
697
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
780
781
697
    return 0;
782
783
62
error:
784
62
    if (cd != NULL) DetectICMPV4CsumFree(de_ctx, cd);
785
62
    if (sm != NULL) SCFree(sm);
786
787
62
    return -1;
788
759
}
789
790
static void DetectICMPV4CsumFree(DetectEngineCtx *de_ctx, void *ptr)
791
759
{
792
759
    DetectCsumData *cd = (DetectCsumData *)ptr;
793
794
759
    if (cd != NULL)
795
759
        SCFree(cd);
796
797
759
    return;
798
759
}
799
800
/**
801
 * \brief Checks if the packet sent as the argument, has a valid or invalid
802
 *        icmpv6 checksum, based on whether icmpv6-csum option for this rule
803
 *        has been supplied with "valid" or "invalid" argument
804
 *
805
 * \param t       Pointer to the tv for this detection module instance
806
 * \param det_ctx Pointer to the detection engine thread context
807
 * \param p       Pointer to the Packet currently being matched
808
 * \param s       Pointer to the Signature, the packet is being currently
809
 *                matched with
810
 * \param m       Pointer to the keyword_structure(SigMatch) from the above
811
 *                Signature, the Packet is being currently matched with
812
 *
813
 * \retval 1 if the Packet contents match the keyword option; 0 otherwise
814
 */
815
static int DetectICMPV6CsumMatch(DetectEngineThreadCtx *det_ctx,
816
        Packet *p, const Signature *s, const SigMatchCtx *ctx)
817
967
{
818
967
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
819
820
967
    if (p->ip6h == NULL || p->icmpv6h == NULL || p->proto != IPPROTO_ICMPV6 || PKT_IS_PSEUDOPKT(p) ||
821
838
        (GET_PKT_LEN(p) - ((uint8_t *)p->icmpv6h - GET_PKT_DATA(p))) <= 0) {
822
129
        return 0;
823
129
    }
824
825
838
    if (p->flags & PKT_IGNORE_CHECKSUM) {
826
0
        return cd->valid;
827
0
    }
828
829
838
    if (p->level4_comp_csum == -1) {
830
838
        uint16_t len = IPV6_GET_RAW_PLEN(p->ip6h) -
831
838
                       (uint16_t)((uint8_t *)p->icmpv6h - (uint8_t *)p->ip6h - IPV6_HEADER_LEN);
832
838
        p->level4_comp_csum = ICMPV6CalculateChecksum(p->ip6h->s_ip6_addrs,
833
838
                                                      (uint16_t *)p->icmpv6h,
834
838
                                                      len);
835
838
    }
836
837
838
    if (p->level4_comp_csum == p->icmpv6h->csum && cd->valid == 1)
838
0
        return 1;
839
838
    else if (p->level4_comp_csum != p->icmpv6h->csum && cd->valid == 0)
840
747
        return 1;
841
91
    else
842
91
        return 0;
843
838
}
844
845
/**
846
 * \brief Creates a SigMatch for the icmpv6-csum keyword being sent as argument,
847
 *        and appends it to the Signature(s).  Accepts 2 values for the
848
 *        keyword - "valid" and "invalid", both with and without quotes
849
 *
850
 * \param de_ctx    Pointer to the detection engine context
851
 * \param s         Pointer to signature for the current Signature being parsed
852
 *                  from the rules
853
 * \param csum_str  Pointer to the string holding the keyword value
854
 *
855
 * \retval 0 on success, -1 on failure
856
 */
857
static int DetectICMPV6CsumSetup(DetectEngineCtx *de_ctx, Signature *s, const char *csum_str)
858
988
{
859
988
    DetectCsumData *cd = NULL;
860
988
    SigMatch *sm = NULL;
861
862
988
    sm = SigMatchAlloc();
863
988
    if (sm == NULL)
864
0
        goto error;
865
866
988
    sm->type = DETECT_ICMPV6_CSUM;
867
868
988
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
869
0
        goto error;
870
988
    memset(cd, 0, sizeof(DetectCsumData));
871
872
988
    if (DetectCsumParseArg(csum_str, cd) == 0)
873
76
        goto error;
874
875
912
    sm->ctx = (SigMatchCtx *)cd;
876
877
912
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
878
879
912
    return 0;
880
881
76
error:
882
76
    if (cd != NULL) DetectICMPV6CsumFree(de_ctx, cd);
883
76
    if (sm != NULL) SCFree(sm);
884
885
76
    return -1;
886
988
}
887
888
static void DetectICMPV6CsumFree(DetectEngineCtx *de_ctx, void *ptr)
889
988
{
890
988
    DetectCsumData *cd = (DetectCsumData *)ptr;
891
892
988
    if (cd != NULL)
893
988
        SCFree(cd);
894
895
988
    return;
896
988
}
897
898
/* ---------------------------------- Unit Tests --------------------------- */
899
900
#ifdef UNITTESTS
901
#include "util-unittest-helper.h"
902
#include "detect-engine.h"
903
#include "detect-engine-alert.h"
904
#include "packet.h"
905
906
#define mystr(s) #s
907
#define TEST1(kwstr) {\
908
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();\
909
    FAIL_IF_NULL(de_ctx);\
910
    de_ctx->flags = DE_QUIET;\
911
    \
912
    Signature *s = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any ("mystr(kwstr)"-csum:valid; sid:1;)");\
913
    FAIL_IF_NULL(s);\
914
    s = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any ("mystr(kwstr)"-csum:invalid; sid:2;)");\
915
    FAIL_IF_NULL(s);\
916
    s = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any ("mystr(kwstr)"-csum:vaLid; sid:3;)");\
917
    FAIL_IF_NULL(s);\
918
    s = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any ("mystr(kwstr)"-csum:VALID; sid:4;)");\
919
    FAIL_IF_NULL(s);\
920
    s = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any ("mystr(kwstr)"-csum:iNvaLid; sid:5;)");\
921
    FAIL_IF_NULL(s);\
922
    DetectEngineCtxFree(de_ctx);\
923
}
924
925
926
static int DetectCsumValidArgsTestParse01(void)
927
{
928
    TEST1(ipv4);
929
    TEST1(tcpv4);
930
    TEST1(tcpv6);
931
    TEST1(udpv4);
932
    TEST1(udpv6);
933
    TEST1(icmpv4);
934
    TEST1(icmpv6);
935
    PASS;
936
}
937
#undef TEST1
938
939
#define TEST2(kwstr)                                                                               \
940
    {                                                                                              \
941
        DetectEngineCtx *de_ctx = DetectEngineCtxInit();                                           \
942
        FAIL_IF_NULL(de_ctx);                                                                      \
943
        Signature *s = DetectEngineAppendSig(                                                      \
944
                de_ctx, "alert ip any any -> any any (" mystr(kwstr) "-csum:xxxx; sid:1;)");       \
945
        FAIL_IF(s);                                                                                \
946
        s = DetectEngineAppendSig(                                                                 \
947
                de_ctx, "alert ip any any -> any any (" mystr(kwstr) "-csum:xxxxxxxx; sid:2;)");   \
948
        FAIL_IF(s);                                                                                \
949
        s = DetectEngineAppendSig(                                                                 \
950
                de_ctx, "alert ip any any -> any any (" mystr(kwstr) "-csum:xxxxxx; sid:3;)");     \
951
        FAIL_IF(s);                                                                                \
952
        s = DetectEngineAppendSig(                                                                 \
953
                de_ctx, "alert ip any any -> any any (" mystr(kwstr) "-csum:XXXXXX; sid:4;)");     \
954
        FAIL_IF(s);                                                                                \
955
        s = DetectEngineAppendSig(                                                                 \
956
                de_ctx, "alert ip any any -> any any (" mystr(kwstr) "-csum:XxXxXxX; sid:5;)");    \
957
        FAIL_IF(s);                                                                                \
958
        DetectEngineCtxFree(de_ctx);                                                               \
959
    }
960
961
static int DetectCsumInvalidArgsTestParse02(void)
962
{
963
    TEST2(ipv4);
964
    TEST2(tcpv4);
965
    TEST2(tcpv6);
966
    TEST2(udpv4);
967
    TEST2(udpv6);
968
    TEST2(icmpv4);
969
    TEST2(icmpv6);
970
    PASS;
971
}
972
#undef TEST2
973
974
#define TEST3(kwstr, kwtype) { \
975
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();\
976
    FAIL_IF_NULL(de_ctx);\
977
    Signature *s = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any ("mystr(kwstr)"-csum:valid; sid:1;)");\
978
    FAIL_IF_NULL(s);\
979
    SigMatch *sm = DetectGetLastSMFromLists(s, (kwtype), -1);\
980
    FAIL_IF_NULL(sm);\
981
    FAIL_IF_NULL(sm->ctx);\
982
    FAIL_IF_NOT(((DetectCsumData *)sm->ctx)->valid == 1);\
983
    s = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any ("mystr(kwstr)"-csum:INVALID; sid:2;)");\
984
    FAIL_IF_NULL(s);\
985
    sm = DetectGetLastSMFromLists(s, (kwtype), -1);\
986
    FAIL_IF_NULL(sm);\
987
    FAIL_IF_NULL(sm->ctx);\
988
    FAIL_IF_NOT(((DetectCsumData *)sm->ctx)->valid == 0);\
989
    DetectEngineCtxFree(de_ctx);\
990
}
991
992
static int DetectCsumValidArgsTestParse03(void)
993
{
994
    TEST3(ipv4, DETECT_IPV4_CSUM);
995
    TEST3(tcpv4, DETECT_TCPV4_CSUM);
996
    TEST3(tcpv6, DETECT_TCPV6_CSUM);
997
    TEST3(udpv4, DETECT_UDPV4_CSUM);
998
    TEST3(udpv6, DETECT_UDPV6_CSUM);
999
    TEST3(icmpv4, DETECT_ICMPV4_CSUM);
1000
    TEST3(icmpv6, DETECT_ICMPV6_CSUM);
1001
    PASS;
1002
}
1003
#undef TEST3
1004
#undef mystr
1005
1006
#include "stream-tcp.h"
1007
1008
static int DetectCsumICMPV6Test01(void)
1009
{
1010
    DetectEngineCtx *de_ctx = NULL;
1011
    Signature *s = NULL;
1012
    ThreadVars tv;
1013
    DetectEngineThreadCtx *det_ctx = NULL;
1014
    DecodeThreadVars dtv;
1015
1016
    Packet *p = PacketGetFromAlloc();
1017
    FAIL_IF_NULL(p);
1018
1019
    uint8_t pkt[] = {
1020
        0x00, 0x30, 0x18, 0xa8, 0x7c, 0x23, 0x2c, 0x41,
1021
        0x38, 0xa7, 0xea, 0xeb, 0x86, 0xdd, 0x60, 0x00,
1022
        0x00, 0x00, 0x00, 0x40, 0x3c, 0x40, 0xad, 0xa1,
1023
        0x09, 0x80, 0x00, 0x01, 0xd6, 0xf3, 0x20, 0x01,
1024
        0xf4, 0xbe, 0xea, 0x3c, 0x00, 0x01, 0x00, 0x00,
1025
        0x00, 0x00, 0x32, 0xb2, 0x00, 0x01, 0x32, 0xb2,
1026
        0x09, 0x80, 0x20, 0x01, 0x00, 0x00, 0x3c, 0x00,
1027
        0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00,
1028
        0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00,
1029
        0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00,
1030
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00,
1031
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00,
1032
        0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00,
1033
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
1034
        0x63, 0xc2, 0x00, 0x00, 0x00, 0x00 };
1035
1036
    PacketCopyData(p, pkt, sizeof(pkt));
1037
1038
    memset(&tv, 0, sizeof(tv));
1039
    memset(&dtv, 0, sizeof(dtv));
1040
1041
    StreamTcpInitConfig(true);
1042
    FlowInitConfig(FLOW_QUIET);
1043
1044
    de_ctx = DetectEngineCtxInit();
1045
    FAIL_IF_NULL(de_ctx);
1046
    de_ctx->mpm_matcher = mpm_default_matcher;
1047
    de_ctx->flags |= DE_QUIET;
1048
1049
    s = de_ctx->sig_list = SigInit(de_ctx, "alert ip any any -> any any "
1050
                                   "(icmpv6-csum:valid; sid:1;)");
1051
    FAIL_IF_NULL(s);
1052
    SigGroupBuild(de_ctx);
1053
1054
    DecodeEthernet(&tv, &dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p));
1055
1056
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
1057
1058
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
1059
1060
    FAIL_IF(!PacketAlertCheck(p, 1));
1061
1062
    DetectEngineThreadCtxDeinit(&tv, det_ctx);
1063
    DetectEngineCtxFree(de_ctx);
1064
1065
    StreamTcpFreeConfig(true);
1066
    PacketRecycle(p);
1067
    FlowShutdown();
1068
    SCFree(p);
1069
    PASS;
1070
}
1071
1072
static void DetectCsumRegisterTests(void)
1073
{
1074
    UtRegisterTest("DetectCsumValidArgsTestParse01",
1075
                   DetectCsumValidArgsTestParse01);
1076
    UtRegisterTest("DetectCsumInvalidArgsTestParse02",
1077
                   DetectCsumInvalidArgsTestParse02);
1078
    UtRegisterTest("DetectCsumValidArgsTestParse03",
1079
                   DetectCsumValidArgsTestParse03);
1080
1081
    UtRegisterTest("DetectCsumICMPV6Test01",
1082
            DetectCsumICMPV6Test01);
1083
}
1084
#endif /* UNITTESTS */