Coverage Report

Created: 2026-05-16 07:38

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
10.5k
#define DETECT_CSUM_VALID   "valid"
43
4.93k
#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
73
{
141
73
    sigmatch_table[DETECT_IPV4_CSUM].name = "ipv4-csum";
142
73
    sigmatch_table[DETECT_IPV4_CSUM].Match = DetectIPV4CsumMatch;
143
73
    sigmatch_table[DETECT_IPV4_CSUM].Setup = DetectIPV4CsumSetup;
144
73
    sigmatch_table[DETECT_IPV4_CSUM].Free  = DetectIPV4CsumFree;
145
#ifdef UNITTESTS
146
    sigmatch_table[DETECT_IPV4_CSUM].RegisterTests = DetectCsumRegisterTests;
147
#endif
148
149
73
    sigmatch_table[DETECT_TCPV4_CSUM].name = "tcpv4-csum";
150
73
    sigmatch_table[DETECT_TCPV4_CSUM].Match = DetectTCPV4CsumMatch;
151
73
    sigmatch_table[DETECT_TCPV4_CSUM].Setup = DetectTCPV4CsumSetup;
152
73
    sigmatch_table[DETECT_TCPV4_CSUM].Free  = DetectTCPV4CsumFree;
153
154
73
    sigmatch_table[DETECT_TCPV6_CSUM].name = "tcpv6-csum";
155
73
    sigmatch_table[DETECT_TCPV6_CSUM].Match = DetectTCPV6CsumMatch;
156
73
    sigmatch_table[DETECT_TCPV6_CSUM].Setup = DetectTCPV6CsumSetup;
157
73
    sigmatch_table[DETECT_TCPV6_CSUM].Free  = DetectTCPV6CsumFree;
158
159
73
    sigmatch_table[DETECT_UDPV4_CSUM].name = "udpv4-csum";
160
73
    sigmatch_table[DETECT_UDPV4_CSUM].Match = DetectUDPV4CsumMatch;
161
73
    sigmatch_table[DETECT_UDPV4_CSUM].Setup = DetectUDPV4CsumSetup;
162
73
    sigmatch_table[DETECT_UDPV4_CSUM].Free  = DetectUDPV4CsumFree;
163
164
73
    sigmatch_table[DETECT_UDPV6_CSUM].name = "udpv6-csum";
165
73
    sigmatch_table[DETECT_UDPV6_CSUM].Match = DetectUDPV6CsumMatch;
166
73
    sigmatch_table[DETECT_UDPV6_CSUM].Setup = DetectUDPV6CsumSetup;
167
73
    sigmatch_table[DETECT_UDPV6_CSUM].Free  = DetectUDPV6CsumFree;
168
169
73
    sigmatch_table[DETECT_ICMPV4_CSUM].name = "icmpv4-csum";
170
73
    sigmatch_table[DETECT_ICMPV4_CSUM].Match = DetectICMPV4CsumMatch;
171
73
    sigmatch_table[DETECT_ICMPV4_CSUM].Setup = DetectICMPV4CsumSetup;
172
73
    sigmatch_table[DETECT_ICMPV4_CSUM].Free  = DetectICMPV4CsumFree;
173
174
73
    sigmatch_table[DETECT_ICMPV6_CSUM].name = "icmpv6-csum";
175
73
    sigmatch_table[DETECT_ICMPV6_CSUM].Match = DetectICMPV6CsumMatch;
176
73
    sigmatch_table[DETECT_ICMPV6_CSUM].Setup = DetectICMPV6CsumSetup;
177
73
    sigmatch_table[DETECT_ICMPV6_CSUM].Free  = DetectICMPV6CsumFree;
178
73
}
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.47k
{
194
5.47k
    char *str;
195
196
5.47k
    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.47k
    } else {
203
5.47k
        str = SCStrdup(key);
204
5.47k
        if (unlikely(str == NULL)) {
205
0
            goto error;
206
0
        }
207
5.47k
    }
208
209
5.47k
    if (strcasecmp(str, DETECT_CSUM_VALID) == 0 ||
210
5.06k
        strcasecmp(str, DETECT_CSUM_INVALID) == 0) {
211
5.06k
        cd->valid = (strcasecmp(key, DETECT_CSUM_VALID) == 0);
212
5.06k
        SCFree(str);
213
5.06k
        return 1;
214
5.06k
    }
215
216
410
error:
217
410
    if (str != NULL)
218
410
        SCFree(str);
219
410
    return 0;
220
5.47k
}
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
21.4k
{
240
21.4k
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
241
242
21.4k
    if (p->ip4h == NULL || PKT_IS_PSEUDOPKT(p))
243
2.32k
        return 0;
244
245
19.0k
    if (p->flags & PKT_IGNORE_CHECKSUM) {
246
0
        return cd->valid;
247
0
    }
248
249
19.0k
    if (p->level3_comp_csum == -1)
250
19.0k
        p->level3_comp_csum = IPV4Checksum((uint16_t *)p->ip4h,
251
19.0k
                                           IPV4_GET_HLEN(p),
252
19.0k
                                           p->ip4h->ip_csum);
253
254
19.0k
    if (p->level3_comp_csum == 0 && cd->valid == 1)
255
0
        return 1;
256
19.0k
    else if (p->level3_comp_csum != 0 && cd->valid == 0)
257
4.22k
        return 1;
258
14.8k
    else
259
14.8k
        return 0;
260
19.0k
}
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
781
{
276
781
    DetectCsumData *cd = NULL;
277
781
    SigMatch *sm = NULL;
278
279
    //printf("DetectCsumSetup: \'%s\'\n", csum_str);
280
281
781
    sm = SigMatchAlloc();
282
781
    if (sm == NULL)
283
0
        goto error;
284
285
781
    sm->type = DETECT_IPV4_CSUM;
286
287
781
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
288
0
        goto error;
289
781
    memset(cd, 0, sizeof(DetectCsumData));
290
291
781
    if (DetectCsumParseArg(csum_str, cd) == 0)
292
33
        goto error;
293
294
748
    sm->ctx = (SigMatchCtx *)cd;
295
296
748
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
297
298
748
    return 0;
299
300
33
error:
301
33
    if (cd != NULL) DetectIPV4CsumFree(de_ctx, cd);
302
33
    if (sm != NULL) SCFree(sm);
303
304
33
    return -1;
305
781
}
306
307
static void DetectIPV4CsumFree(DetectEngineCtx *de_ctx, void *ptr)
308
781
{
309
781
    DetectCsumData *cd = (DetectCsumData *)ptr;
310
311
781
    if (cd != NULL)
312
781
        SCFree(cd);
313
314
781
    return;
315
781
}
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
17.1k
{
335
17.1k
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
336
337
17.1k
    if (p->ip4h == NULL || p->tcph == NULL || p->proto != IPPROTO_TCP || PKT_IS_PSEUDOPKT(p))
338
2.22k
        return 0;
339
340
14.9k
    if (p->flags & PKT_IGNORE_CHECKSUM) {
341
0
        return cd->valid;
342
0
    }
343
344
14.9k
    if (p->level4_comp_csum == -1)
345
14.9k
        p->level4_comp_csum = TCPChecksum(p->ip4h->s_ip_addrs,
346
14.9k
                                          (uint16_t *)p->tcph,
347
14.9k
                                          (p->payload_len +
348
14.9k
                                              TCP_GET_HLEN(p)),
349
14.9k
                                          p->tcph->th_sum);
350
351
14.9k
    if (p->level4_comp_csum == 0 && cd->valid == 1)
352
0
        return 1;
353
14.9k
    else if (p->level4_comp_csum != 0 && cd->valid == 0)
354
8.57k
        return 1;
355
6.36k
    else
356
6.36k
        return 0;
357
14.9k
}
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
691
{
373
691
    DetectCsumData *cd = NULL;
374
691
    SigMatch *sm = NULL;
375
376
    //printf("DetectCsumSetup: \'%s\'\n", csum_str);
377
378
691
    sm = SigMatchAlloc();
379
691
    if (sm == NULL)
380
0
        goto error;
381
382
691
    sm->type = DETECT_TCPV4_CSUM;
383
384
691
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
385
0
        goto error;
386
691
    memset(cd, 0, sizeof(DetectCsumData));
387
388
691
    if (DetectCsumParseArg(csum_str, cd) == 0)
389
35
        goto error;
390
391
656
    sm->ctx = (SigMatchCtx *)cd;
392
393
656
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
394
395
656
    return 0;
396
397
35
error:
398
35
    if (cd != NULL) DetectTCPV4CsumFree(de_ctx, cd);
399
35
    if (sm != NULL) SCFree(sm);
400
401
35
    return -1;
402
691
}
403
404
static void DetectTCPV4CsumFree(DetectEngineCtx *de_ctx, void *ptr)
405
691
{
406
691
    DetectCsumData *cd = (DetectCsumData *)ptr;
407
408
691
    if (cd != NULL)
409
691
        SCFree(cd);
410
411
691
    return;
412
691
}
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
12.4k
{
432
12.4k
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
433
434
12.4k
    if (p->ip6h == NULL || p->tcph == NULL || p->proto != IPPROTO_TCP || PKT_IS_PSEUDOPKT(p))
435
11.7k
        return 0;
436
437
641
    if (p->flags & PKT_IGNORE_CHECKSUM) {
438
0
        return cd->valid;
439
0
    }
440
441
641
    if (p->level4_comp_csum == -1)
442
637
        p->level4_comp_csum = TCPV6Checksum(p->ip6h->s_ip6_addrs,
443
637
                                            (uint16_t *)p->tcph,
444
637
                                            (p->payload_len +
445
637
                                                TCP_GET_HLEN(p)),
446
637
                                            p->tcph->th_sum);
447
448
641
    if (p->level4_comp_csum == 0 && cd->valid == 1)
449
0
        return 1;
450
641
    else if (p->level4_comp_csum != 0 && cd->valid == 0)
451
641
        return 1;
452
0
    else
453
0
        return 0;
454
641
}
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.02k
{
470
1.02k
    DetectCsumData *cd = NULL;
471
1.02k
    SigMatch *sm = NULL;
472
473
    //printf("DetectCsumSetup: \'%s\'\n", csum_str);
474
475
1.02k
    sm = SigMatchAlloc();
476
1.02k
    if (sm == NULL)
477
0
        goto error;
478
479
1.02k
    sm->type = DETECT_TCPV6_CSUM;
480
481
1.02k
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
482
0
        goto error;
483
1.02k
    memset(cd, 0, sizeof(DetectCsumData));
484
485
1.02k
    if (DetectCsumParseArg(csum_str, cd) == 0)
486
44
        goto error;
487
488
981
    sm->ctx = (SigMatchCtx *)cd;
489
490
981
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
491
492
981
    return 0;
493
494
44
error:
495
44
    if (cd != NULL) DetectTCPV6CsumFree(de_ctx, cd);
496
44
    if (sm != NULL) SCFree(sm);
497
498
44
    return -1;
499
1.02k
}
500
501
static void DetectTCPV6CsumFree(DetectEngineCtx *de_ctx, void *ptr)
502
1.02k
{
503
1.02k
    DetectCsumData *cd = (DetectCsumData *)ptr;
504
505
1.02k
    if (cd != NULL)
506
1.02k
        SCFree(cd);
507
508
1.02k
    return;
509
1.02k
}
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
3.95k
{
529
3.95k
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
530
531
3.95k
    if (p->ip4h == NULL || p->udph == NULL || p->proto != IPPROTO_UDP || PKT_IS_PSEUDOPKT(p) || p->udph->uh_sum == 0)
532
322
        return 0;
533
534
3.63k
    if (p->flags & PKT_IGNORE_CHECKSUM) {
535
0
        return cd->valid;
536
0
    }
537
538
3.63k
    if (p->level4_comp_csum == -1)
539
3.63k
        p->level4_comp_csum = UDPV4Checksum(p->ip4h->s_ip_addrs,
540
3.63k
                                            (uint16_t *)p->udph,
541
3.63k
                                            (p->payload_len +
542
3.63k
                                                UDP_HEADER_LEN),
543
3.63k
                                            p->udph->uh_sum);
544
545
3.63k
    if (p->level4_comp_csum == 0 && cd->valid == 1)
546
0
        return 1;
547
3.63k
    else if (p->level4_comp_csum != 0 && cd->valid == 0)
548
1.84k
        return 1;
549
1.79k
    else
550
1.79k
        return 0;
551
3.63k
}
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
778
{
567
778
    DetectCsumData *cd = NULL;
568
778
    SigMatch *sm = NULL;
569
570
    //printf("DetectCsumSetup: \'%s\'\n", csum_str);
571
572
778
    sm = SigMatchAlloc();
573
778
    if (sm == NULL)
574
0
        goto error;
575
576
778
    sm->type = DETECT_UDPV4_CSUM;
577
578
778
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
579
0
        goto error;
580
778
    memset(cd, 0, sizeof(DetectCsumData));
581
582
778
    if (DetectCsumParseArg(csum_str, cd) == 0)
583
35
        goto error;
584
585
743
    sm->ctx = (SigMatchCtx *)cd;
586
587
743
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
588
589
743
    return 0;
590
591
35
error:
592
35
    if (cd != NULL) DetectUDPV4CsumFree(de_ctx, cd);
593
35
    if (sm != NULL) SCFree(sm);
594
595
35
    return -1;
596
778
}
597
598
static void DetectUDPV4CsumFree(DetectEngineCtx *de_ctx, void *ptr)
599
778
{
600
778
    DetectCsumData *cd = (DetectCsumData *)ptr;
601
602
778
    if (cd != NULL)
603
778
        SCFree(cd);
604
605
778
    return;
606
778
}
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
3.94k
{
626
3.94k
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
627
628
3.94k
    if (p->ip6h == NULL || p->udph == NULL || p->proto != IPPROTO_UDP || PKT_IS_PSEUDOPKT(p))
629
3.87k
        return 0;
630
631
70
    if (p->flags & PKT_IGNORE_CHECKSUM) {
632
0
        return cd->valid;
633
0
    }
634
635
70
    if (p->level4_comp_csum == -1)
636
70
        p->level4_comp_csum = UDPV6Checksum(p->ip6h->s_ip6_addrs,
637
70
                                            (uint16_t *)p->udph,
638
70
                                            (p->payload_len +
639
70
                                                UDP_HEADER_LEN),
640
70
                                            p->udph->uh_sum);
641
642
70
    if (p->level4_comp_csum == 0 && cd->valid == 1)
643
0
        return 1;
644
70
    else if (p->level4_comp_csum != 0 && cd->valid == 0)
645
6
        return 1;
646
64
    else
647
64
        return 0;
648
70
}
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
700
{
664
700
    DetectCsumData *cd = NULL;
665
700
    SigMatch *sm = NULL;
666
667
    //printf("DetectCsumSetup: \'%s\'\n", csum_str);
668
669
700
    sm = SigMatchAlloc();
670
700
    if (sm == NULL)
671
0
        goto error;
672
673
700
    sm->type = DETECT_UDPV6_CSUM;
674
675
700
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
676
0
        goto error;
677
700
    memset(cd, 0, sizeof(DetectCsumData));
678
679
700
    if (DetectCsumParseArg(csum_str, cd) == 0)
680
163
        goto error;
681
682
537
    sm->ctx = (void *)cd;
683
684
537
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
685
686
537
    return 0;
687
688
163
error:
689
163
    if (cd != NULL) DetectUDPV6CsumFree(de_ctx, cd);
690
163
    if (sm != NULL) SCFree(sm);
691
692
163
    return -1;
693
700
}
694
695
static void DetectUDPV6CsumFree(DetectEngineCtx *de_ctx, void *ptr)
696
700
{
697
700
    DetectCsumData *cd = (DetectCsumData *)ptr;
698
699
700
    if (cd != NULL)
700
700
        SCFree(cd);
701
702
700
    return;
703
700
}
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
569
{
723
569
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
724
725
569
    if (p->ip4h == NULL || p->icmpv4h == NULL || p->proto != IPPROTO_ICMP || PKT_IS_PSEUDOPKT(p))
726
567
        return 0;
727
728
2
    if (p->flags & PKT_IGNORE_CHECKSUM) {
729
0
        return cd->valid;
730
0
    }
731
732
2
    if (p->level4_comp_csum == -1)
733
2
        p->level4_comp_csum = ICMPV4CalculateChecksum((uint16_t *)p->icmpv4h,
734
2
                                                      SCNtohs(IPV4_GET_RAW_IPLEN(p->ip4h)) -
735
2
                                                      IPV4_GET_RAW_HLEN(p->ip4h) * 4);
736
737
2
    if (p->level4_comp_csum == p->icmpv4h->checksum && cd->valid == 1)
738
0
        return 1;
739
2
    else if (p->level4_comp_csum != p->icmpv4h->checksum && cd->valid == 0)
740
2
        return 1;
741
0
    else
742
0
        return 0;
743
2
}
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
686
{
759
686
    DetectCsumData *cd = NULL;
760
686
    SigMatch *sm = NULL;
761
762
    //printf("DetectCsumSetup: \'%s\'\n", csum_str);
763
764
686
    sm = SigMatchAlloc();
765
686
    if (sm == NULL)
766
0
        goto error;
767
768
686
    sm->type = DETECT_ICMPV4_CSUM;
769
770
686
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
771
0
        goto error;
772
686
    memset(cd, 0, sizeof(DetectCsumData));
773
774
686
    if (DetectCsumParseArg(csum_str, cd) == 0)
775
30
        goto error;
776
777
656
    sm->ctx = (SigMatchCtx *)cd;
778
779
656
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
780
781
656
    return 0;
782
783
30
error:
784
30
    if (cd != NULL) DetectICMPV4CsumFree(de_ctx, cd);
785
30
    if (sm != NULL) SCFree(sm);
786
787
30
    return -1;
788
686
}
789
790
static void DetectICMPV4CsumFree(DetectEngineCtx *de_ctx, void *ptr)
791
686
{
792
686
    DetectCsumData *cd = (DetectCsumData *)ptr;
793
794
686
    if (cd != NULL)
795
686
        SCFree(cd);
796
797
686
    return;
798
686
}
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
369
{
818
369
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
819
820
369
    if (p->ip6h == NULL || p->icmpv6h == NULL || p->proto != IPPROTO_ICMPV6 || PKT_IS_PSEUDOPKT(p) ||
821
368
        (GET_PKT_LEN(p) - ((uint8_t *)p->icmpv6h - GET_PKT_DATA(p))) <= 0) {
822
1
        return 0;
823
1
    }
824
825
368
    if (p->flags & PKT_IGNORE_CHECKSUM) {
826
0
        return cd->valid;
827
0
    }
828
829
368
    if (p->level4_comp_csum == -1) {
830
368
        uint16_t len = IPV6_GET_RAW_PLEN(p->ip6h) -
831
368
                       (uint16_t)((uint8_t *)p->icmpv6h - (uint8_t *)p->ip6h - IPV6_HEADER_LEN);
832
368
        p->level4_comp_csum = ICMPV6CalculateChecksum(p->ip6h->s_ip6_addrs,
833
368
                                                      (uint16_t *)p->icmpv6h,
834
368
                                                      len);
835
368
    }
836
837
368
    if (p->level4_comp_csum == p->icmpv6h->csum && cd->valid == 1)
838
0
        return 1;
839
368
    else if (p->level4_comp_csum != p->icmpv6h->csum && cd->valid == 0)
840
287
        return 1;
841
81
    else
842
81
        return 0;
843
368
}
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
818
{
859
818
    DetectCsumData *cd = NULL;
860
818
    SigMatch *sm = NULL;
861
862
818
    sm = SigMatchAlloc();
863
818
    if (sm == NULL)
864
0
        goto error;
865
866
818
    sm->type = DETECT_ICMPV6_CSUM;
867
868
818
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
869
0
        goto error;
870
818
    memset(cd, 0, sizeof(DetectCsumData));
871
872
818
    if (DetectCsumParseArg(csum_str, cd) == 0)
873
70
        goto error;
874
875
748
    sm->ctx = (SigMatchCtx *)cd;
876
877
748
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
878
879
748
    return 0;
880
881
70
error:
882
70
    if (cd != NULL) DetectICMPV6CsumFree(de_ctx, cd);
883
70
    if (sm != NULL) SCFree(sm);
884
885
70
    return -1;
886
818
}
887
888
static void DetectICMPV6CsumFree(DetectEngineCtx *de_ctx, void *ptr)
889
818
{
890
818
    DetectCsumData *cd = (DetectCsumData *)ptr;
891
892
818
    if (cd != NULL)
893
818
        SCFree(cd);
894
895
818
    return;
896
818
}
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 */