Coverage Report

Created: 2026-03-31 07:45

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
7.58k
#define DETECT_CSUM_VALID   "valid"
43
3.29k
#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
3.89k
{
194
3.89k
    char *str;
195
196
3.89k
    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
3.89k
    } else {
203
3.89k
        str = SCStrdup(key);
204
3.89k
        if (unlikely(str == NULL)) {
205
0
            goto error;
206
0
        }
207
3.89k
    }
208
209
3.89k
    if (strcasecmp(str, DETECT_CSUM_VALID) == 0 ||
210
3.69k
        strcasecmp(str, DETECT_CSUM_INVALID) == 0) {
211
3.69k
        cd->valid = (strcasecmp(key, DETECT_CSUM_VALID) == 0);
212
3.69k
        SCFree(str);
213
3.69k
        return 1;
214
3.69k
    }
215
216
198
error:
217
198
    if (str != NULL)
218
198
        SCFree(str);
219
198
    return 0;
220
3.89k
}
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
39.8k
{
240
39.8k
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
241
242
39.8k
    if (p->ip4h == NULL || PKT_IS_PSEUDOPKT(p))
243
2.24k
        return 0;
244
245
37.6k
    if (p->flags & PKT_IGNORE_CHECKSUM) {
246
0
        return cd->valid;
247
0
    }
248
249
37.6k
    if (p->level3_comp_csum == -1)
250
37.5k
        p->level3_comp_csum = IPV4Checksum((uint16_t *)p->ip4h,
251
37.5k
                                           IPV4_GET_HLEN(p),
252
37.5k
                                           p->ip4h->ip_csum);
253
254
37.6k
    if (p->level3_comp_csum == 0 && cd->valid == 1)
255
0
        return 1;
256
37.6k
    else if (p->level3_comp_csum != 0 && cd->valid == 0)
257
24.0k
        return 1;
258
13.5k
    else
259
13.5k
        return 0;
260
37.6k
}
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
537
{
276
537
    DetectCsumData *cd = NULL;
277
537
    SigMatch *sm = NULL;
278
279
    //printf("DetectCsumSetup: \'%s\'\n", csum_str);
280
281
537
    sm = SigMatchAlloc();
282
537
    if (sm == NULL)
283
0
        goto error;
284
285
537
    sm->type = DETECT_IPV4_CSUM;
286
287
537
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
288
0
        goto error;
289
537
    memset(cd, 0, sizeof(DetectCsumData));
290
291
537
    if (DetectCsumParseArg(csum_str, cd) == 0)
292
14
        goto error;
293
294
523
    sm->ctx = (SigMatchCtx *)cd;
295
296
523
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
297
298
523
    return 0;
299
300
14
error:
301
14
    if (cd != NULL) DetectIPV4CsumFree(de_ctx, cd);
302
14
    if (sm != NULL) SCFree(sm);
303
304
14
    return -1;
305
537
}
306
307
static void DetectIPV4CsumFree(DetectEngineCtx *de_ctx, void *ptr)
308
537
{
309
537
    DetectCsumData *cd = (DetectCsumData *)ptr;
310
311
537
    if (cd != NULL)
312
537
        SCFree(cd);
313
314
537
    return;
315
537
}
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
15.8k
{
335
15.8k
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
336
337
15.8k
    if (p->ip4h == NULL || p->tcph == NULL || p->proto != IPPROTO_TCP || PKT_IS_PSEUDOPKT(p))
338
1.11k
        return 0;
339
340
14.7k
    if (p->flags & PKT_IGNORE_CHECKSUM) {
341
0
        return cd->valid;
342
0
    }
343
344
14.7k
    if (p->level4_comp_csum == -1)
345
14.7k
        p->level4_comp_csum = TCPChecksum(p->ip4h->s_ip_addrs,
346
14.7k
                                          (uint16_t *)p->tcph,
347
14.7k
                                          (p->payload_len +
348
14.7k
                                              TCP_GET_HLEN(p)),
349
14.7k
                                          p->tcph->th_sum);
350
351
14.7k
    if (p->level4_comp_csum == 0 && cd->valid == 1)
352
0
        return 1;
353
14.7k
    else if (p->level4_comp_csum != 0 && cd->valid == 0)
354
10.2k
        return 1;
355
4.49k
    else
356
4.49k
        return 0;
357
14.7k
}
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
476
{
373
476
    DetectCsumData *cd = NULL;
374
476
    SigMatch *sm = NULL;
375
376
    //printf("DetectCsumSetup: \'%s\'\n", csum_str);
377
378
476
    sm = SigMatchAlloc();
379
476
    if (sm == NULL)
380
0
        goto error;
381
382
476
    sm->type = DETECT_TCPV4_CSUM;
383
384
476
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
385
0
        goto error;
386
476
    memset(cd, 0, sizeof(DetectCsumData));
387
388
476
    if (DetectCsumParseArg(csum_str, cd) == 0)
389
39
        goto error;
390
391
437
    sm->ctx = (SigMatchCtx *)cd;
392
393
437
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
394
395
437
    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
476
}
403
404
static void DetectTCPV4CsumFree(DetectEngineCtx *de_ctx, void *ptr)
405
476
{
406
476
    DetectCsumData *cd = (DetectCsumData *)ptr;
407
408
476
    if (cd != NULL)
409
476
        SCFree(cd);
410
411
476
    return;
412
476
}
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
7.64k
{
432
7.64k
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
433
434
7.64k
    if (p->ip6h == NULL || p->tcph == NULL || p->proto != IPPROTO_TCP || PKT_IS_PSEUDOPKT(p))
435
7.45k
        return 0;
436
437
194
    if (p->flags & PKT_IGNORE_CHECKSUM) {
438
0
        return cd->valid;
439
0
    }
440
441
194
    if (p->level4_comp_csum == -1)
442
194
        p->level4_comp_csum = TCPV6Checksum(p->ip6h->s_ip6_addrs,
443
194
                                            (uint16_t *)p->tcph,
444
194
                                            (p->payload_len +
445
194
                                                TCP_GET_HLEN(p)),
446
194
                                            p->tcph->th_sum);
447
448
194
    if (p->level4_comp_csum == 0 && cd->valid == 1)
449
0
        return 1;
450
194
    else if (p->level4_comp_csum != 0 && cd->valid == 0)
451
194
        return 1;
452
0
    else
453
0
        return 0;
454
194
}
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
768
{
470
768
    DetectCsumData *cd = NULL;
471
768
    SigMatch *sm = NULL;
472
473
    //printf("DetectCsumSetup: \'%s\'\n", csum_str);
474
475
768
    sm = SigMatchAlloc();
476
768
    if (sm == NULL)
477
0
        goto error;
478
479
768
    sm->type = DETECT_TCPV6_CSUM;
480
481
768
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
482
0
        goto error;
483
768
    memset(cd, 0, sizeof(DetectCsumData));
484
485
768
    if (DetectCsumParseArg(csum_str, cd) == 0)
486
17
        goto error;
487
488
751
    sm->ctx = (SigMatchCtx *)cd;
489
490
751
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
491
492
751
    return 0;
493
494
17
error:
495
17
    if (cd != NULL) DetectTCPV6CsumFree(de_ctx, cd);
496
17
    if (sm != NULL) SCFree(sm);
497
498
17
    return -1;
499
768
}
500
501
static void DetectTCPV6CsumFree(DetectEngineCtx *de_ctx, void *ptr)
502
768
{
503
768
    DetectCsumData *cd = (DetectCsumData *)ptr;
504
505
768
    if (cd != NULL)
506
768
        SCFree(cd);
507
508
768
    return;
509
768
}
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
493
{
529
493
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
530
531
493
    if (p->ip4h == NULL || p->udph == NULL || p->proto != IPPROTO_UDP || PKT_IS_PSEUDOPKT(p) || p->udph->uh_sum == 0)
532
85
        return 0;
533
534
408
    if (p->flags & PKT_IGNORE_CHECKSUM) {
535
0
        return cd->valid;
536
0
    }
537
538
408
    if (p->level4_comp_csum == -1)
539
408
        p->level4_comp_csum = UDPV4Checksum(p->ip4h->s_ip_addrs,
540
408
                                            (uint16_t *)p->udph,
541
408
                                            (p->payload_len +
542
408
                                                UDP_HEADER_LEN),
543
408
                                            p->udph->uh_sum);
544
545
408
    if (p->level4_comp_csum == 0 && cd->valid == 1)
546
0
        return 1;
547
408
    else if (p->level4_comp_csum != 0 && cd->valid == 0)
548
203
        return 1;
549
205
    else
550
205
        return 0;
551
408
}
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
549
{
567
549
    DetectCsumData *cd = NULL;
568
549
    SigMatch *sm = NULL;
569
570
    //printf("DetectCsumSetup: \'%s\'\n", csum_str);
571
572
549
    sm = SigMatchAlloc();
573
549
    if (sm == NULL)
574
0
        goto error;
575
576
549
    sm->type = DETECT_UDPV4_CSUM;
577
578
549
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
579
0
        goto error;
580
549
    memset(cd, 0, sizeof(DetectCsumData));
581
582
549
    if (DetectCsumParseArg(csum_str, cd) == 0)
583
19
        goto error;
584
585
530
    sm->ctx = (SigMatchCtx *)cd;
586
587
530
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
588
589
530
    return 0;
590
591
19
error:
592
19
    if (cd != NULL) DetectUDPV4CsumFree(de_ctx, cd);
593
19
    if (sm != NULL) SCFree(sm);
594
595
19
    return -1;
596
549
}
597
598
static void DetectUDPV4CsumFree(DetectEngineCtx *de_ctx, void *ptr)
599
549
{
600
549
    DetectCsumData *cd = (DetectCsumData *)ptr;
601
602
549
    if (cd != NULL)
603
549
        SCFree(cd);
604
605
549
    return;
606
549
}
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
245
{
626
245
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
627
628
245
    if (p->ip6h == NULL || p->udph == NULL || p->proto != IPPROTO_UDP || PKT_IS_PSEUDOPKT(p))
629
213
        return 0;
630
631
32
    if (p->flags & PKT_IGNORE_CHECKSUM) {
632
0
        return cd->valid;
633
0
    }
634
635
32
    if (p->level4_comp_csum == -1)
636
32
        p->level4_comp_csum = UDPV6Checksum(p->ip6h->s_ip6_addrs,
637
32
                                            (uint16_t *)p->udph,
638
32
                                            (p->payload_len +
639
32
                                                UDP_HEADER_LEN),
640
32
                                            p->udph->uh_sum);
641
642
32
    if (p->level4_comp_csum == 0 && cd->valid == 1)
643
0
        return 1;
644
32
    else if (p->level4_comp_csum != 0 && cd->valid == 0)
645
0
        return 1;
646
32
    else
647
32
        return 0;
648
32
}
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
460
{
664
460
    DetectCsumData *cd = NULL;
665
460
    SigMatch *sm = NULL;
666
667
    //printf("DetectCsumSetup: \'%s\'\n", csum_str);
668
669
460
    sm = SigMatchAlloc();
670
460
    if (sm == NULL)
671
0
        goto error;
672
673
460
    sm->type = DETECT_UDPV6_CSUM;
674
675
460
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
676
0
        goto error;
677
460
    memset(cd, 0, sizeof(DetectCsumData));
678
679
460
    if (DetectCsumParseArg(csum_str, cd) == 0)
680
86
        goto error;
681
682
374
    sm->ctx = (void *)cd;
683
684
374
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
685
686
374
    return 0;
687
688
86
error:
689
86
    if (cd != NULL) DetectUDPV6CsumFree(de_ctx, cd);
690
86
    if (sm != NULL) SCFree(sm);
691
692
86
    return -1;
693
460
}
694
695
static void DetectUDPV6CsumFree(DetectEngineCtx *de_ctx, void *ptr)
696
460
{
697
460
    DetectCsumData *cd = (DetectCsumData *)ptr;
698
699
460
    if (cd != NULL)
700
460
        SCFree(cd);
701
702
460
    return;
703
460
}
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
83
{
723
83
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
724
725
83
    if (p->ip4h == NULL || p->icmpv4h == NULL || p->proto != IPPROTO_ICMP || PKT_IS_PSEUDOPKT(p))
726
80
        return 0;
727
728
3
    if (p->flags & PKT_IGNORE_CHECKSUM) {
729
0
        return cd->valid;
730
0
    }
731
732
3
    if (p->level4_comp_csum == -1)
733
3
        p->level4_comp_csum = ICMPV4CalculateChecksum((uint16_t *)p->icmpv4h,
734
3
                                                      SCNtohs(IPV4_GET_RAW_IPLEN(p->ip4h)) -
735
3
                                                      IPV4_GET_RAW_HLEN(p->ip4h) * 4);
736
737
3
    if (p->level4_comp_csum == p->icmpv4h->checksum && cd->valid == 1)
738
0
        return 1;
739
3
    else if (p->level4_comp_csum != p->icmpv4h->checksum && cd->valid == 0)
740
3
        return 1;
741
0
    else
742
0
        return 0;
743
3
}
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
495
{
759
495
    DetectCsumData *cd = NULL;
760
495
    SigMatch *sm = NULL;
761
762
    //printf("DetectCsumSetup: \'%s\'\n", csum_str);
763
764
495
    sm = SigMatchAlloc();
765
495
    if (sm == NULL)
766
0
        goto error;
767
768
495
    sm->type = DETECT_ICMPV4_CSUM;
769
770
495
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
771
0
        goto error;
772
495
    memset(cd, 0, sizeof(DetectCsumData));
773
774
495
    if (DetectCsumParseArg(csum_str, cd) == 0)
775
16
        goto error;
776
777
479
    sm->ctx = (SigMatchCtx *)cd;
778
779
479
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
780
781
479
    return 0;
782
783
16
error:
784
16
    if (cd != NULL) DetectICMPV4CsumFree(de_ctx, cd);
785
16
    if (sm != NULL) SCFree(sm);
786
787
16
    return -1;
788
495
}
789
790
static void DetectICMPV4CsumFree(DetectEngineCtx *de_ctx, void *ptr)
791
495
{
792
495
    DetectCsumData *cd = (DetectCsumData *)ptr;
793
794
495
    if (cd != NULL)
795
495
        SCFree(cd);
796
797
495
    return;
798
495
}
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
14
{
818
14
    const DetectCsumData *cd = (const DetectCsumData *)ctx;
819
820
14
    if (p->ip6h == NULL || p->icmpv6h == NULL || p->proto != IPPROTO_ICMPV6 || PKT_IS_PSEUDOPKT(p) ||
821
12
        (GET_PKT_LEN(p) - ((uint8_t *)p->icmpv6h - GET_PKT_DATA(p))) <= 0) {
822
2
        return 0;
823
2
    }
824
825
12
    if (p->flags & PKT_IGNORE_CHECKSUM) {
826
0
        return cd->valid;
827
0
    }
828
829
12
    if (p->level4_comp_csum == -1) {
830
12
        uint16_t len = IPV6_GET_RAW_PLEN(p->ip6h) -
831
12
                       (uint16_t)((uint8_t *)p->icmpv6h - (uint8_t *)p->ip6h - IPV6_HEADER_LEN);
832
12
        p->level4_comp_csum = ICMPV6CalculateChecksum(p->ip6h->s_ip6_addrs,
833
12
                                                      (uint16_t *)p->icmpv6h,
834
12
                                                      len);
835
12
    }
836
837
12
    if (p->level4_comp_csum == p->icmpv6h->csum && cd->valid == 1)
838
0
        return 1;
839
12
    else if (p->level4_comp_csum != p->icmpv6h->csum && cd->valid == 0)
840
1
        return 1;
841
11
    else
842
11
        return 0;
843
12
}
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
606
{
859
606
    DetectCsumData *cd = NULL;
860
606
    SigMatch *sm = NULL;
861
862
606
    sm = SigMatchAlloc();
863
606
    if (sm == NULL)
864
0
        goto error;
865
866
606
    sm->type = DETECT_ICMPV6_CSUM;
867
868
606
    if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL)
869
0
        goto error;
870
606
    memset(cd, 0, sizeof(DetectCsumData));
871
872
606
    if (DetectCsumParseArg(csum_str, cd) == 0)
873
7
        goto error;
874
875
599
    sm->ctx = (SigMatchCtx *)cd;
876
877
599
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
878
879
599
    return 0;
880
881
7
error:
882
7
    if (cd != NULL) DetectICMPV6CsumFree(de_ctx, cd);
883
7
    if (sm != NULL) SCFree(sm);
884
885
7
    return -1;
886
606
}
887
888
static void DetectICMPV6CsumFree(DetectEngineCtx *de_ctx, void *ptr)
889
606
{
890
606
    DetectCsumData *cd = (DetectCsumData *)ptr;
891
892
606
    if (cd != NULL)
893
606
        SCFree(cd);
894
895
606
    return;
896
606
}
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 */