Coverage Report

Created: 2026-06-07 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/datasets.c
Line
Count
Source
1
/* Copyright (C) 2017-2020 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17
18
/**
19
 * \file
20
 *
21
 * \author Victor Julien <victor@inliniac.net>
22
 */
23
24
#include "suricata-common.h"
25
#include "suricata.h"
26
#include "conf.h"
27
#include "datasets.h"
28
#include "datasets-string.h"
29
#include "datasets-ipv4.h"
30
#include "datasets-ipv6.h"
31
#include "datasets-md5.h"
32
#include "datasets-sha256.h"
33
#include "datasets-reputation.h"
34
#include "util-conf.h"
35
#include "util-thash.h"
36
#include "util-print.h"
37
#include "util-base64.h"    // decode base64
38
#include "util-byte.h"
39
#include "util-misc.h"
40
#include "util-path.h"
41
#include "util-debug.h"
42
#include "util-validate.h"
43
44
SCMutex sets_lock = SCMUTEX_INITIALIZER;
45
static Dataset *sets = NULL;
46
static uint32_t set_ids = 0;
47
48
/* 4x what we set in master to allow a smoother upgrade path */
49
uint32_t dataset_max_one_hashsize = 262144;
50
uint32_t dataset_max_total_hashsize = 67108864;
51
uint32_t dataset_used_hashsize = 0;
52
53
static int DatasetAddwRep(Dataset *set, const uint8_t *data, const uint32_t data_len,
54
        DataRepType *rep);
55
56
static inline void DatasetUnlockData(THashData *d)
57
87.7k
{
58
87.7k
    (void) THashDecrUsecnt(d);
59
87.7k
    THashDataUnlock(d);
60
87.7k
}
61
static bool DatasetIsStatic(const char *save, const char *load);
62
static void GetDefaultMemcap(uint64_t *memcap, uint32_t *hashsize);
63
64
enum DatasetTypes DatasetGetTypeFromString(const char *s)
65
0
{
66
0
    if (strcasecmp("md5", s) == 0)
67
0
        return DATASET_TYPE_MD5;
68
0
    if (strcasecmp("sha256", s) == 0)
69
0
        return DATASET_TYPE_SHA256;
70
0
    if (strcasecmp("string", s) == 0)
71
0
        return DATASET_TYPE_STRING;
72
0
    if (strcasecmp("ipv4", s) == 0)
73
0
        return DATASET_TYPE_IPV4;
74
0
    if (strcasecmp("ip", s) == 0)
75
0
        return DATASET_TYPE_IPV6;
76
0
    return DATASET_TYPE_NOTSET;
77
0
}
78
79
static Dataset *DatasetAlloc(const char *name)
80
12.8k
{
81
12.8k
    Dataset *set = SCCalloc(1, sizeof(*set));
82
12.8k
    if (set) {
83
12.8k
        set->id = set_ids++;
84
12.8k
    }
85
12.8k
    return set;
86
12.8k
}
87
88
static Dataset *DatasetSearchByName(const char *name)
89
59.1k
{
90
59.1k
    Dataset *set = sets;
91
6.06M
    while (set) {
92
6.05M
        if (strcasecmp(name, set->name) == 0 && set->hidden == false) {
93
41.4k
            return set;
94
41.4k
        }
95
6.01M
        set = set->next;
96
6.01M
    }
97
17.6k
    return NULL;
98
59.1k
}
99
100
static int HexToRaw(const uint8_t *in, size_t ins, uint8_t *out, size_t outs)
101
0
{
102
0
    if (ins < 2)
103
0
        return -1;
104
0
    if (ins % 2 != 0)
105
0
        return -1;
106
0
    if (outs != ins / 2)
107
0
        return -1;
108
109
0
    uint8_t hash[outs];
110
0
    memset(hash, 0, outs);
111
0
    size_t i, x;
112
0
    for (x = 0, i = 0; i < ins; i+=2, x++) {
113
0
        char buf[3] = { 0, 0, 0 };
114
0
        buf[0] = in[i];
115
0
        buf[1] = in[i+1];
116
117
0
        long value = strtol(buf, NULL, 16);
118
0
        if (value >= 0 && value <= 255)
119
0
            hash[x] = (uint8_t)value;
120
0
        else {
121
0
            SCLogError("hash byte out of range %ld", value);
122
0
            return -1;
123
0
        }
124
0
    }
125
126
0
    memcpy(out, hash, outs);
127
0
    return 0;
128
0
}
129
130
static int ParseRepLine(const char *in, size_t ins, DataRepType *rep_out)
131
0
{
132
0
    SCLogDebug("in '%s'", in);
133
0
    char raw[ins + 1];
134
0
    memcpy(raw, in, ins);
135
0
    raw[ins] = '\0';
136
0
    char *line = raw;
137
138
0
    char *ptrs[1] = {NULL};
139
0
    int idx = 0;
140
141
0
    size_t i = 0;
142
0
    while (i < ins + 1) {
143
0
        if (line[i] == ',' || line[i] == '\n' || line[i] == '\0') {
144
0
            line[i] = '\0';
145
0
            SCLogDebug("line '%s'", line);
146
147
0
            ptrs[idx] = line;
148
0
            idx++;
149
150
0
            if (idx == 1)
151
0
                break;
152
0
        } else {
153
0
            i++;
154
0
        }
155
0
    }
156
157
0
    if (idx != 1) {
158
0
        SCLogDebug("idx %d", idx);
159
0
        return -1;
160
0
    }
161
162
0
    uint16_t v = 0;
163
0
    int r = StringParseU16RangeCheck(&v, 10, strlen(ptrs[0]), ptrs[0], 0, USHRT_MAX);
164
0
    if (r != (int)strlen(ptrs[0])) {
165
0
        SCLogError("'%s' is not a valid reputation value (0-65535)", ptrs[0]);
166
0
        return -1;
167
0
    }
168
0
    SCLogDebug("v %"PRIu16" raw %s", v, ptrs[0]);
169
170
0
    rep_out->value = v;
171
0
    return 0;
172
0
}
173
174
static int DatasetLoadIPv4(Dataset *set)
175
192
{
176
192
    if (strlen(set->load) == 0)
177
58
        return 0;
178
179
134
    SCLogConfig("dataset: %s loading from '%s'", set->name, set->load);
180
134
    const char *fopen_mode = "r";
181
134
    if (strlen(set->save) > 0 && strcmp(set->save, set->load) == 0) {
182
2
        fopen_mode = "a+";
183
2
    }
184
185
134
    FILE *fp = fopen(set->load, fopen_mode);
186
134
    if (fp == NULL) {
187
124
        SCLogError("fopen '%s' failed: %s", set->load, strerror(errno));
188
124
        return -1;
189
124
    }
190
191
10
    uint32_t cnt = 0;
192
10
    char line[1024];
193
10
    while (fgets(line, (int)sizeof(line), fp) != NULL) {
194
0
        char *r = strchr(line, ',');
195
0
        if (r == NULL) {
196
0
            line[strlen(line) - 1] = '\0';
197
0
            SCLogDebug("line: '%s'", line);
198
199
0
            struct in_addr in;
200
0
            if (inet_pton(AF_INET, line, &in) != 1) {
201
0
                FatalErrorOnInit("dataset data parse failed %s/%s: %s", set->name, set->load, line);
202
0
                continue;
203
0
            }
204
205
0
            if (DatasetAdd(set, (const uint8_t *)&in.s_addr, 4) < 0) {
206
0
                FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
207
0
                continue;
208
0
            }
209
0
            cnt++;
210
211
            /* list with rep data */
212
0
        } else {
213
0
            line[strlen(line) - 1] = '\0';
214
0
            SCLogDebug("IPv4 with REP line: '%s'", line);
215
216
0
            *r = '\0';
217
218
0
            struct in_addr in;
219
0
            if (inet_pton(AF_INET, line, &in) != 1) {
220
0
                FatalErrorOnInit("dataset data parse failed %s/%s: %s", set->name, set->load, line);
221
0
                continue;
222
0
            }
223
224
0
            r++;
225
226
0
            DataRepType rep = { .value = 0 };
227
0
            if (ParseRepLine(r, strlen(r), &rep) < 0) {
228
0
                FatalErrorOnInit("bad rep for dataset %s/%s", set->name, set->load);
229
0
                continue;
230
0
            }
231
232
0
            SCLogDebug("rep v:%u", rep.value);
233
0
            if (DatasetAddwRep(set, (const uint8_t *)&in.s_addr, 4, &rep) < 0) {
234
0
                FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
235
0
                continue;
236
0
            }
237
238
0
            cnt++;
239
0
        }
240
0
    }
241
10
    THashConsolidateMemcap(set->hash);
242
243
10
    fclose(fp);
244
10
    SCLogConfig("dataset: %s loaded %u records", set->name, cnt);
245
10
    return 0;
246
10
}
247
248
static int ParseIpv6String(Dataset *set, const char *line, struct in6_addr *in6)
249
0
{
250
    /* Checking IPv6 case */
251
0
    const char *got_colon = strchr(line, ':');
252
0
    if (got_colon) {
253
0
        uint32_t ip6addr[4];
254
0
        if (inet_pton(AF_INET6, line, in6) != 1) {
255
0
            FatalErrorOnInit("dataset data parse failed %s/%s: %s", set->name, set->load, line);
256
0
            return -1;
257
0
        }
258
0
        memcpy(&ip6addr, in6->s6_addr, sizeof(ip6addr));
259
        /* IPv4 in IPv6 notation needs transformation to internal Suricata storage */
260
0
        if (ip6addr[0] == 0 && ip6addr[1] == 0 && ip6addr[2] == 0xFFFF0000) {
261
0
            ip6addr[0] = ip6addr[3];
262
0
            ip6addr[2] = 0;
263
0
            ip6addr[3] = 0;
264
0
            memcpy(in6, ip6addr, sizeof(struct in6_addr));
265
0
        }
266
0
    } else {
267
        /* IPv4 case */
268
0
        struct in_addr in;
269
0
        if (inet_pton(AF_INET, line, &in) != 1) {
270
0
            FatalErrorOnInit("dataset data parse failed %s/%s: %s", set->name, set->load, line);
271
0
            return -1;
272
0
        }
273
0
        memset(in6, 0, sizeof(struct in6_addr));
274
0
        memcpy(in6, &in, sizeof(struct in_addr));
275
0
    }
276
0
    return 0;
277
0
}
278
279
static int DatasetLoadIPv6(Dataset *set)
280
285
{
281
285
    if (strlen(set->load) == 0)
282
162
        return 0;
283
284
123
    SCLogConfig("dataset: %s loading from '%s'", set->name, set->load);
285
123
    const char *fopen_mode = "r";
286
123
    if (strlen(set->save) > 0 && strcmp(set->save, set->load) == 0) {
287
3
        fopen_mode = "a+";
288
3
    }
289
290
123
    FILE *fp = fopen(set->load, fopen_mode);
291
123
    if (fp == NULL) {
292
110
        SCLogError("fopen '%s' failed: %s", set->load, strerror(errno));
293
110
        return -1;
294
110
    }
295
296
13
    uint32_t cnt = 0;
297
13
    char line[1024];
298
13
    while (fgets(line, (int)sizeof(line), fp) != NULL) {
299
0
        char *r = strchr(line, ',');
300
0
        if (r == NULL) {
301
0
            line[strlen(line) - 1] = '\0';
302
0
            SCLogDebug("line: '%s'", line);
303
304
0
            struct in6_addr in6;
305
0
            int ret = ParseIpv6String(set, line, &in6);
306
0
            if (ret < 0) {
307
0
                FatalErrorOnInit("unable to parse IP address");
308
0
                continue;
309
0
            }
310
311
0
            if (DatasetAdd(set, (const uint8_t *)&in6.s6_addr, 16) < 0) {
312
0
                FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
313
0
                continue;
314
0
            }
315
0
            cnt++;
316
317
            /* list with rep data */
318
0
        } else {
319
0
            line[strlen(line) - 1] = '\0';
320
0
            SCLogDebug("IPv6 with REP line: '%s'", line);
321
322
0
            *r = '\0';
323
324
0
            struct in6_addr in6;
325
0
            int ret = ParseIpv6String(set, line, &in6);
326
0
            if (ret < 0) {
327
0
                FatalErrorOnInit("unable to parse IP address");
328
0
                continue;
329
0
            }
330
331
0
            r++;
332
333
0
            DataRepType rep = { .value = 0 };
334
0
            if (ParseRepLine(r, strlen(r), &rep) < 0) {
335
0
                FatalErrorOnInit("bad rep for dataset %s/%s", set->name, set->load);
336
0
                continue;
337
0
            }
338
339
0
            SCLogDebug("rep v:%u", rep.value);
340
0
            if (DatasetAddwRep(set, (const uint8_t *)&in6.s6_addr, 16, &rep) < 0) {
341
0
                FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
342
0
                continue;
343
0
            }
344
345
0
            cnt++;
346
0
        }
347
0
    }
348
13
    THashConsolidateMemcap(set->hash);
349
350
13
    fclose(fp);
351
13
    SCLogConfig("dataset: %s loaded %u records", set->name, cnt);
352
13
    return 0;
353
13
}
354
355
static int DatasetLoadMd5(Dataset *set)
356
8.77k
{
357
8.77k
    if (strlen(set->load) == 0)
358
150
        return 0;
359
360
8.62k
    SCLogConfig("dataset: %s loading from '%s'", set->name, set->load);
361
8.62k
    const char *fopen_mode = "r";
362
8.62k
    if (strlen(set->save) > 0 && strcmp(set->save, set->load) == 0) {
363
1.26k
        fopen_mode = "a+";
364
1.26k
    }
365
366
8.62k
    FILE *fp = fopen(set->load, fopen_mode);
367
8.62k
    if (fp == NULL) {
368
8.50k
        SCLogError("fopen '%s' failed: %s", set->load, strerror(errno));
369
8.50k
        return -1;
370
8.50k
    }
371
372
120
    uint32_t cnt = 0;
373
120
    char line[1024];
374
120
    while (fgets(line, (int)sizeof(line), fp) != NULL) {
375
        /* straight black/white list */
376
0
        if (strlen(line) == 33) {
377
0
            line[strlen(line) - 1] = '\0';
378
0
            SCLogDebug("line: '%s'", line);
379
380
0
            uint8_t hash[16];
381
0
            if (HexToRaw((const uint8_t *)line, 32, hash, sizeof(hash)) < 0) {
382
0
                FatalErrorOnInit("bad hash for dataset %s/%s", set->name, set->load);
383
0
                continue;
384
0
            }
385
386
0
            if (DatasetAdd(set, (const uint8_t *)hash, 16) < 0) {
387
0
                FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
388
0
                continue;
389
0
            }
390
0
            cnt++;
391
392
        /* list with rep data */
393
0
        } else if (strlen(line) > 33 && line[32] == ',') {
394
0
            line[strlen(line) - 1] = '\0';
395
0
            SCLogDebug("MD5 with REP line: '%s'", line);
396
397
0
            uint8_t hash[16];
398
0
            if (HexToRaw((const uint8_t *)line, 32, hash, sizeof(hash)) < 0) {
399
0
                FatalErrorOnInit("bad hash for dataset %s/%s", set->name, set->load);
400
0
                continue;
401
0
            }
402
403
0
            DataRepType rep = { .value = 0};
404
0
            if (ParseRepLine(line + 33, strlen(line) - 33, &rep) < 0) {
405
0
                FatalErrorOnInit("bad rep for dataset %s/%s", set->name, set->load);
406
0
                continue;
407
0
            }
408
409
0
            SCLogDebug("rep v:%u", rep.value);
410
0
            if (DatasetAddwRep(set, hash, 16, &rep) < 0) {
411
0
                FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
412
0
                continue;
413
0
            }
414
415
0
            cnt++;
416
0
        }
417
0
        else {
418
0
            FatalErrorOnInit("MD5 bad line len %u: '%s'", (uint32_t)strlen(line), line);
419
0
            continue;
420
0
        }
421
0
    }
422
120
    THashConsolidateMemcap(set->hash);
423
424
120
    fclose(fp);
425
120
    SCLogConfig("dataset: %s loaded %u records", set->name, cnt);
426
120
    return 0;
427
120
}
428
429
static int DatasetLoadSha256(Dataset *set)
430
1.44k
{
431
1.44k
    if (strlen(set->load) == 0)
432
62
        return 0;
433
434
1.37k
    SCLogConfig("dataset: %s loading from '%s'", set->name, set->load);
435
1.37k
    const char *fopen_mode = "r";
436
1.37k
    if (strlen(set->save) > 0 && strcmp(set->save, set->load) == 0) {
437
106
        fopen_mode = "a+";
438
106
    }
439
440
1.37k
    FILE *fp = fopen(set->load, fopen_mode);
441
1.37k
    if (fp == NULL) {
442
1.37k
        SCLogError("fopen '%s' failed: %s", set->load, strerror(errno));
443
1.37k
        return -1;
444
1.37k
    }
445
446
1
    uint32_t cnt = 0;
447
1
    char line[1024];
448
1
    while (fgets(line, (int)sizeof(line), fp) != NULL) {
449
        /* straight black/white list */
450
0
        if (strlen(line) == 65) {
451
0
            line[strlen(line) - 1] = '\0';
452
0
            SCLogDebug("line: '%s'", line);
453
454
0
            uint8_t hash[32];
455
0
            if (HexToRaw((const uint8_t *)line, 64, hash, sizeof(hash)) < 0) {
456
0
                FatalErrorOnInit("bad hash for dataset %s/%s", set->name, set->load);
457
0
                continue;
458
0
            }
459
460
0
            if (DatasetAdd(set, (const uint8_t *)hash, (uint32_t)32) < 0) {
461
0
                FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
462
0
                continue;
463
0
            }
464
0
            cnt++;
465
466
            /* list with rep data */
467
0
        } else if (strlen(line) > 65 && line[64] == ',') {
468
0
            line[strlen(line) - 1] = '\0';
469
0
            SCLogDebug("SHA-256 with REP line: '%s'", line);
470
471
0
            uint8_t hash[32];
472
0
            if (HexToRaw((const uint8_t *)line, 64, hash, sizeof(hash)) < 0) {
473
0
                FatalErrorOnInit("bad hash for dataset %s/%s", set->name, set->load);
474
0
                continue;
475
0
            }
476
477
0
            DataRepType rep = { .value = 0 };
478
0
            if (ParseRepLine(line + 65, strlen(line) - 65, &rep) < 0) {
479
0
                FatalErrorOnInit("bad rep for dataset %s/%s", set->name, set->load);
480
0
                continue;
481
0
            }
482
483
0
            SCLogDebug("rep %u", rep.value);
484
485
0
            if (DatasetAddwRep(set, hash, 32, &rep) < 0) {
486
0
                FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
487
0
                continue;
488
0
            }
489
0
            cnt++;
490
0
        }
491
0
    }
492
1
    THashConsolidateMemcap(set->hash);
493
494
1
    fclose(fp);
495
1
    SCLogConfig("dataset: %s loaded %u records", set->name, cnt);
496
1
    return 0;
497
1
}
498
499
static int DatasetLoadString(Dataset *set)
500
1.83k
{
501
1.83k
    if (strlen(set->load) == 0)
502
96
        return 0;
503
504
1.73k
    SCLogConfig("dataset: %s loading from '%s'", set->name, set->load);
505
1.73k
    const char *fopen_mode = "r";
506
1.73k
    if (strlen(set->save) > 0 && strcmp(set->save, set->load) == 0) {
507
240
        fopen_mode = "a+";
508
240
    }
509
510
1.73k
    FILE *fp = fopen(set->load, fopen_mode);
511
1.73k
    if (fp == NULL) {
512
1.72k
        SCLogError("fopen '%s' failed: %s", set->load, strerror(errno));
513
1.72k
        return -1;
514
1.72k
    }
515
516
16
    uint32_t cnt = 0;
517
16
    char line[1024];
518
16
    while (fgets(line, (int)sizeof(line), fp) != NULL) {
519
0
        if (strlen(line) <= 1)
520
0
            continue;
521
522
0
        char *r = strchr(line, ',');
523
0
        if (r == NULL) {
524
0
            line[strlen(line) - 1] = '\0';
525
0
            SCLogDebug("line: '%s'", line);
526
527
            // coverity[alloc_strlen : FALSE]
528
0
            uint8_t decoded[strlen(line)];
529
0
            uint32_t consumed = 0, num_decoded = 0;
530
0
            Base64Ecode code = DecodeBase64(decoded, strlen(line), (const uint8_t *)line,
531
0
                    strlen(line), &consumed, &num_decoded, BASE64_MODE_STRICT);
532
0
            if (code == BASE64_ECODE_ERR) {
533
0
                FatalErrorOnInit("bad base64 encoding %s/%s", set->name, set->load);
534
0
                continue;
535
0
            }
536
537
0
            if (DatasetAdd(set, (const uint8_t *)decoded, num_decoded) < 0) {
538
0
                FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
539
0
                continue;
540
0
            }
541
0
            cnt++;
542
0
        } else {
543
0
            line[strlen(line) - 1] = '\0';
544
0
            SCLogDebug("line: '%s'", line);
545
546
0
            *r = '\0';
547
548
            // coverity[alloc_strlen : FALSE]
549
0
            uint8_t decoded[strlen(line)];
550
0
            uint32_t consumed = 0, num_decoded = 0;
551
0
            Base64Ecode code = DecodeBase64(decoded, strlen(line), (const uint8_t *)line,
552
0
                    strlen(line), &consumed, &num_decoded, BASE64_MODE_STRICT);
553
0
            if (code == BASE64_ECODE_ERR) {
554
0
                FatalErrorOnInit("bad base64 encoding %s/%s", set->name, set->load);
555
0
                continue;
556
0
            }
557
558
0
            r++;
559
0
            SCLogDebug("r '%s'", r);
560
561
0
            DataRepType rep = { .value = 0 };
562
0
            if (ParseRepLine(r, strlen(r), &rep) < 0) {
563
0
                FatalErrorOnInit("die: bad rep");
564
0
                continue;
565
0
            }
566
0
            SCLogDebug("rep %u", rep.value);
567
568
0
            if (DatasetAddwRep(set, (const uint8_t *)decoded, num_decoded, &rep) < 0) {
569
0
                FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
570
0
                continue;
571
0
            }
572
0
            cnt++;
573
574
0
            SCLogDebug("line with rep %s, %s", line, r);
575
0
        }
576
0
    }
577
16
    THashConsolidateMemcap(set->hash);
578
579
16
    fclose(fp);
580
16
    SCLogConfig("dataset: %s loaded %u records", set->name, cnt);
581
16
    return 0;
582
16
}
583
584
extern bool g_system;
585
586
enum DatasetGetPathType {
587
    TYPE_STATE,
588
    TYPE_LOAD,
589
};
590
591
static void DatasetGetPath(const char *in_path,
592
        char *out_path, size_t out_size, enum DatasetGetPathType type)
593
0
{
594
0
    char path[PATH_MAX];
595
0
    struct stat st;
596
597
0
    if (PathIsAbsolute(in_path)) {
598
0
        strlcpy(path, in_path, sizeof(path));
599
0
        strlcpy(out_path, path, out_size);
600
0
        return;
601
0
    }
602
603
0
    const char *data_dir = ConfigGetDataDirectory();
604
0
    if (stat(data_dir, &st) != 0) {
605
0
        SCLogDebug("data-dir '%s': %s", data_dir, strerror(errno));
606
0
        return;
607
0
    }
608
609
0
    snprintf(path, sizeof(path), "%s/%s", data_dir, in_path); // TODO WINDOWS
610
611
0
    if (type == TYPE_LOAD) {
612
0
        if (stat(path, &st) != 0) {
613
0
            SCLogDebug("path %s: %s", path, strerror(errno));
614
0
            if (!g_system) {
615
0
                snprintf(path, sizeof(path), "%s", in_path);
616
0
            }
617
0
        }
618
0
    }
619
0
    strlcpy(out_path, path, out_size);
620
0
    SCLogDebug("in_path \'%s\' => \'%s\'", in_path, out_path);
621
0
}
622
623
/** \brief look for set by name without creating it */
624
Dataset *DatasetFind(const char *name, enum DatasetTypes type)
625
0
{
626
0
    SCMutexLock(&sets_lock);
627
0
    Dataset *set = DatasetSearchByName(name);
628
0
    if (set) {
629
0
        if (set->type != type) {
630
0
            SCMutexUnlock(&sets_lock);
631
0
            return NULL;
632
0
        }
633
0
    }
634
0
    SCMutexUnlock(&sets_lock);
635
0
    return set;
636
0
}
637
638
static bool DatasetCheckHashsize(const char *name, uint32_t hash_size)
639
23.5k
{
640
23.5k
    if (dataset_max_one_hashsize > 0 && hash_size > dataset_max_one_hashsize) {
641
1.25k
        SCLogError("hashsize %u in dataset '%s' exceeds configured 'single-hashsize' limit (%u)",
642
1.25k
                hash_size, name, dataset_max_one_hashsize);
643
1.25k
        return false;
644
1.25k
    }
645
    // we cannot underflow as we know from conf loading that
646
    // dataset_max_total_hashsize >= dataset_max_one_hashsize if dataset_max_total_hashsize > 0
647
22.3k
    if (dataset_max_total_hashsize > 0 &&
648
22.3k
            dataset_max_total_hashsize - hash_size < dataset_used_hashsize) {
649
0
        SCLogError("hashsize %u in dataset '%s' exceeds configured 'total-hashsizes' limit (%u, in "
650
0
                   "use %u)",
651
0
                hash_size, name, dataset_max_total_hashsize, dataset_used_hashsize);
652
0
        return false;
653
0
    }
654
655
22.3k
    return true;
656
22.3k
}
657
658
static void DatasetUpdateHashsize(const char *name, uint32_t hash_size)
659
1.54k
{
660
1.54k
    if (dataset_max_total_hashsize > 0) {
661
1.54k
        dataset_used_hashsize += hash_size;
662
1.54k
        SCLogDebug("set %s adding with hash_size %u", name, hash_size);
663
1.54k
    }
664
1.54k
}
665
666
Dataset *DatasetGet(const char *name, enum DatasetTypes type, const char *save, const char *load,
667
        uint64_t memcap, uint32_t hashsize)
668
59.1k
{
669
59.1k
    uint64_t default_memcap = 0;
670
59.1k
    uint32_t default_hashsize = 0;
671
59.1k
    if (strlen(name) > DATASET_NAME_MAX_LEN) {
672
0
        return NULL;
673
0
    }
674
675
59.1k
    SCMutexLock(&sets_lock);
676
59.1k
    Dataset *set = DatasetSearchByName(name);
677
59.1k
    if (set) {
678
41.4k
        if (type != DATASET_TYPE_NOTSET && set->type != type) {
679
1.57k
            SCLogError("dataset %s already "
680
1.57k
                       "exists and is of type %u",
681
1.57k
                    set->name, set->type);
682
1.57k
            SCMutexUnlock(&sets_lock);
683
1.57k
            return NULL;
684
1.57k
        }
685
686
39.8k
        if ((save == NULL || strlen(save) == 0) &&
687
37.0k
            (load == NULL || strlen(load) == 0)) {
688
            // OK, rule keyword doesn't have to set state/load,
689
            // even when yaml set has set it.
690
22.4k
        } else {
691
17.4k
            if ((save == NULL && strlen(set->save) > 0) ||
692
17.4k
                    (save != NULL && strcmp(set->save, save) != 0)) {
693
1.45k
                SCLogError("dataset %s save mismatch: %s != %s", set->name, set->save, save);
694
1.45k
                SCMutexUnlock(&sets_lock);
695
1.45k
                return NULL;
696
1.45k
            }
697
15.9k
            if ((load == NULL && strlen(set->load) > 0) ||
698
15.9k
                    (load != NULL && strcmp(set->load, load) != 0)) {
699
13.6k
                SCLogError("dataset %s load mismatch: %s != %s", set->name, set->load, load);
700
13.6k
                SCMutexUnlock(&sets_lock);
701
13.6k
                return NULL;
702
13.6k
            }
703
15.9k
        }
704
705
24.7k
        SCMutexUnlock(&sets_lock);
706
24.7k
        return set;
707
39.8k
    } else {
708
17.6k
        if (type == DATASET_TYPE_NOTSET) {
709
4.18k
            SCLogError("dataset %s not defined", name);
710
4.18k
            goto out_err;
711
4.18k
        }
712
17.6k
    }
713
714
13.4k
    GetDefaultMemcap(&default_memcap, &default_hashsize);
715
13.4k
    if (hashsize == 0) {
716
7.79k
        hashsize = default_hashsize;
717
7.79k
    }
718
719
13.4k
    if (!DatasetCheckHashsize(name, hashsize)) {
720
647
        goto out_err;
721
647
    }
722
723
12.8k
    set = DatasetAlloc(name);
724
12.8k
    if (set == NULL) {
725
0
        goto out_err;
726
0
    }
727
728
12.8k
    strlcpy(set->name, name, sizeof(set->name));
729
12.8k
    set->type = type;
730
12.8k
    if (save && strlen(save)) {
731
1.71k
        strlcpy(set->save, save, sizeof(set->save));
732
1.71k
        SCLogDebug("name %s save '%s'", name, set->save);
733
1.71k
    }
734
12.8k
    if (load && strlen(load)) {
735
12.3k
        strlcpy(set->load, load, sizeof(set->load));
736
12.3k
        SCLogDebug("set \'%s\' loading \'%s\' from \'%s\'", set->name, load, set->load);
737
12.3k
    }
738
739
12.8k
    char cnf_name[128];
740
12.8k
    snprintf(cnf_name, sizeof(cnf_name), "datasets.%s.hash", name);
741
742
12.8k
    switch (type) {
743
8.78k
        case DATASET_TYPE_MD5:
744
8.78k
            set->hash = THashInit(cnf_name, sizeof(Md5Type), Md5StrSet, Md5StrFree, Md5StrHash,
745
8.78k
                    Md5StrCompare, load != NULL ? 1 : 0, memcap > 0 ? memcap : default_memcap,
746
8.78k
                    hashsize);
747
8.78k
            if (set->hash == NULL)
748
9
                goto out_err;
749
8.77k
            if (DatasetLoadMd5(set) < 0)
750
8.50k
                goto out_err;
751
270
            break;
752
1.84k
        case DATASET_TYPE_STRING:
753
1.84k
            set->hash = THashInit(cnf_name, sizeof(StringType), StringSet, StringFree, StringHash,
754
1.84k
                    StringCompare, load != NULL ? 1 : 0, memcap > 0 ? memcap : default_memcap,
755
1.84k
                    hashsize);
756
1.84k
            if (set->hash == NULL)
757
12
                goto out_err;
758
1.83k
            if (DatasetLoadString(set) < 0)
759
1.72k
                goto out_err;
760
112
            break;
761
1.73k
        case DATASET_TYPE_SHA256:
762
1.73k
            set->hash = THashInit(cnf_name, sizeof(Sha256Type), Sha256StrSet, Sha256StrFree,
763
1.73k
                    Sha256StrHash, Sha256StrCompare, load != NULL ? 1 : 0,
764
1.73k
                    memcap > 0 ? memcap : default_memcap, hashsize);
765
1.73k
            if (set->hash == NULL)
766
299
                goto out_err;
767
1.44k
            if (DatasetLoadSha256(set) < 0)
768
1.37k
                goto out_err;
769
63
            break;
770
193
        case DATASET_TYPE_IPV4:
771
193
            set->hash =
772
193
                    THashInit(cnf_name, sizeof(IPv4Type), IPv4Set, IPv4Free, IPv4Hash, IPv4Compare,
773
193
                            load != NULL ? 1 : 0, memcap > 0 ? memcap : default_memcap, hashsize);
774
193
            if (set->hash == NULL)
775
1
                goto out_err;
776
192
            if (DatasetLoadIPv4(set) < 0)
777
124
                goto out_err;
778
68
            break;
779
291
        case DATASET_TYPE_IPV6:
780
291
            set->hash =
781
291
                    THashInit(cnf_name, sizeof(IPv6Type), IPv6Set, IPv6Free, IPv6Hash, IPv6Compare,
782
291
                            load != NULL ? 1 : 0, memcap > 0 ? memcap : default_memcap, hashsize);
783
291
            if (set->hash == NULL)
784
6
                goto out_err;
785
285
            if (DatasetLoadIPv6(set) < 0)
786
110
                goto out_err;
787
175
            break;
788
12.8k
    }
789
688
    if (set->hash == NULL) {
790
0
        goto out_err;
791
0
    }
792
793
688
    if (SC_ATOMIC_GET(set->hash->memcap_reached)) {
794
0
        SCLogError("dataset too large for set memcap");
795
0
        goto out_err;
796
0
    }
797
798
688
    SCLogDebug("set %p/%s type %u save %s load %s",
799
688
            set, set->name, set->type, set->save, set->load);
800
801
688
    set->next = sets;
802
688
    sets = set;
803
804
    /* hash size accounting */
805
688
    DEBUG_VALIDATE_BUG_ON(set->hash->config.hash_size != hashsize);
806
688
    DatasetUpdateHashsize(set->name, set->hash->config.hash_size);
807
808
688
    SCMutexUnlock(&sets_lock);
809
688
    return set;
810
16.9k
out_err:
811
16.9k
    if (set) {
812
12.1k
        if (set->hash) {
813
11.8k
            THashShutdown(set->hash);
814
11.8k
        }
815
12.1k
        SCFree(set);
816
12.1k
    }
817
16.9k
    SCMutexUnlock(&sets_lock);
818
16.9k
    return NULL;
819
688
}
820
821
static bool DatasetIsStatic(const char *save, const char *load)
822
2.76M
{
823
    /* A set is static if it does not have any dynamic properties like
824
     * save and/or state defined but has load defined.
825
     * */
826
2.76M
    if ((load != NULL && strlen(load) > 0) &&
827
54.7k
            (save == NULL || strlen(save) == 0)) {
828
82
        return true;
829
82
    }
830
2.76M
    return false;
831
2.76M
}
832
833
void DatasetReload(void)
834
64.2k
{
835
    /* In order to reload the datasets, just mark the current sets as hidden
836
     * and clean them up later.
837
     * New datasets shall be created with the rule reload and do not require
838
     * any intervention.
839
     * */
840
64.2k
    SCMutexLock(&sets_lock);
841
64.2k
    Dataset *set = sets;
842
2.82M
    while (set) {
843
2.76M
        if (!DatasetIsStatic(set->save, set->load) || set->from_yaml == true) {
844
2.76M
            SCLogDebug("Not a static set, skipping %s", set->name);
845
2.76M
            set = set->next;
846
2.76M
            continue;
847
2.76M
        }
848
82
        set->hidden = true;
849
82
        if (dataset_max_total_hashsize > 0) {
850
82
            dataset_used_hashsize -= set->hash->config.hash_size;
851
82
        }
852
82
        SCLogDebug("Set %s at %p hidden successfully", set->name, set);
853
82
        set = set->next;
854
82
    }
855
64.2k
    SCMutexUnlock(&sets_lock);
856
64.2k
}
857
858
void DatasetPostReloadCleanup(void)
859
64.2k
{
860
64.2k
    SCLogDebug("Post Reload Cleanup starting.. Hidden sets will be removed");
861
64.2k
    SCMutexLock(&sets_lock);
862
64.2k
    Dataset *cur = sets;
863
64.2k
    Dataset *prev = NULL;
864
2.82M
    while (cur) {
865
2.76M
        Dataset *next = cur->next;
866
2.76M
        if (cur->hidden == false) {
867
2.76M
            prev = cur;
868
2.76M
            cur = next;
869
2.76M
            continue;
870
2.76M
        }
871
        // Delete the set in case it was hidden
872
82
        if (prev != NULL) {
873
2
            prev->next = next;
874
80
        } else {
875
80
            sets = next;
876
80
        }
877
82
        THashShutdown(cur->hash);
878
82
        SCFree(cur);
879
82
        cur = next;
880
82
    }
881
64.2k
    SCMutexUnlock(&sets_lock);
882
64.2k
}
883
884
/* Value reflects THASH_DEFAULT_HASHSIZE which is what the default was earlier,
885
 * despite 2048 commented out in the default yaml. */
886
13.5k
#define DATASETS_HASHSIZE_DEFAULT 4096
887
888
static void GetDefaultMemcap(uint64_t *memcap, uint32_t *hashsize)
889
13.5k
{
890
13.5k
    const char *str = NULL;
891
13.5k
    if (ConfGet("datasets.defaults.memcap", &str) == 1) {
892
0
        if (ParseSizeStringU64(str, memcap) < 0) {
893
0
            SCLogWarning("memcap value cannot be deduced: %s,"
894
0
                         " resetting to default",
895
0
                    str);
896
0
            *memcap = 0;
897
0
        }
898
0
    }
899
900
13.5k
    *hashsize = (uint32_t)DATASETS_HASHSIZE_DEFAULT;
901
13.5k
    if (ConfGet("datasets.defaults.hashsize", &str) == 1) {
902
0
        if (ParseSizeStringU32(str, hashsize) < 0) {
903
0
            *hashsize = (uint32_t)DATASETS_HASHSIZE_DEFAULT;
904
0
            SCLogWarning("hashsize value cannot be deduced: %s,"
905
0
                         " resetting to default: %u",
906
0
                    str, *hashsize);
907
0
        }
908
0
    }
909
13.5k
}
910
911
int DatasetsInit(void)
912
5
{
913
5
    SCLogDebug("datasets start");
914
5
    ConfNode *datasets = ConfGetNode("datasets");
915
5
    uint64_t default_memcap = 0;
916
5
    uint32_t default_hashsize = 0;
917
5
    GetDefaultMemcap(&default_memcap, &default_hashsize);
918
5
    if (datasets != NULL) {
919
4
        const char *str = NULL;
920
4
        if (ConfGet("datasets.limits.total-hashsizes", &str) == 1) {
921
0
            if (ParseSizeStringU32(str, &dataset_max_total_hashsize) < 0) {
922
0
                FatalError("failed to parse datasets.limits.total-hashsizes value: %s", str);
923
0
            }
924
0
        }
925
4
        if (ConfGet("datasets.limits.single-hashsize", &str) == 1) {
926
0
            if (ParseSizeStringU32(str, &dataset_max_one_hashsize) < 0) {
927
0
                FatalError("failed to parse datasets.limits.single-hashsize value: %s", str);
928
0
            }
929
0
        }
930
4
        if (dataset_max_total_hashsize > 0 &&
931
4
                dataset_max_total_hashsize < dataset_max_one_hashsize) {
932
0
            FatalError("total-hashsizes (%u) cannot be smaller than single-hashsize (%u)",
933
0
                    dataset_max_total_hashsize, dataset_max_one_hashsize);
934
0
        }
935
4
        if (dataset_max_total_hashsize > 0 && dataset_max_one_hashsize == 0) {
936
            // the total limit also applies for single limit
937
0
            dataset_max_one_hashsize = dataset_max_total_hashsize;
938
0
        }
939
940
4
        int list_pos = 0;
941
4
        ConfNode *iter = NULL;
942
4
        TAILQ_FOREACH(iter, &datasets->head, next) {
943
4
            if (iter->name == NULL) {
944
0
                list_pos++;
945
0
                continue;
946
0
            }
947
948
4
            char save[PATH_MAX] = "";
949
4
            char load[PATH_MAX] = "";
950
4
            uint64_t memcap = 0;
951
4
            uint32_t hashsize = 0;
952
953
4
            const char *set_name = iter->name;
954
4
            if (strlen(set_name) > DATASET_NAME_MAX_LEN) {
955
0
                FatalErrorOnInit(
956
0
                        "set name '%s' too long, max %d chars", set_name, DATASET_NAME_MAX_LEN);
957
0
                continue;
958
0
            }
959
960
4
            ConfNode *set_type =
961
4
                ConfNodeLookupChild(iter, "type");
962
4
            if (set_type == NULL) {
963
4
                list_pos++;
964
4
                continue;
965
4
            }
966
967
0
            ConfNode *set_save =
968
0
                ConfNodeLookupChild(iter, "state");
969
0
            if (set_save) {
970
0
                DatasetGetPath(set_save->val, save, sizeof(save), TYPE_STATE);
971
0
                strlcpy(load, save, sizeof(load));
972
0
            } else {
973
0
                ConfNode *set_load =
974
0
                    ConfNodeLookupChild(iter, "load");
975
0
                if (set_load) {
976
0
                    DatasetGetPath(set_load->val, load, sizeof(load), TYPE_LOAD);
977
0
                }
978
0
            }
979
980
0
            ConfNode *set_memcap = ConfNodeLookupChild(iter, "memcap");
981
0
            if (set_memcap) {
982
0
                if (ParseSizeStringU64(set_memcap->val, &memcap) < 0) {
983
0
                    SCLogWarning("memcap value cannot be"
984
0
                                 " deduced: %s, resetting to default",
985
0
                            set_memcap->val);
986
0
                    memcap = 0;
987
0
                }
988
0
            }
989
0
            ConfNode *set_hashsize = ConfNodeLookupChild(iter, "hashsize");
990
0
            if (set_hashsize) {
991
0
                if (ParseSizeStringU32(set_hashsize->val, &hashsize) < 0) {
992
0
                    SCLogWarning("hashsize value cannot be"
993
0
                                 " deduced: %s, resetting to default",
994
0
                            set_hashsize->val);
995
0
                    hashsize = 0;
996
0
                }
997
0
            }
998
0
            char conf_str[1024];
999
0
            snprintf(conf_str, sizeof(conf_str), "datasets.%d.%s", list_pos, set_name);
1000
1001
0
            SCLogDebug("set %s type %s. Conf %s", set_name, set_type->val, conf_str);
1002
1003
0
            if (strcmp(set_type->val, "md5") == 0) {
1004
0
                Dataset *dset = DatasetGet(set_name, DATASET_TYPE_MD5, save, load,
1005
0
                        memcap > 0 ? memcap : default_memcap,
1006
0
                        hashsize > 0 ? hashsize : default_hashsize);
1007
0
                if (dset == NULL) {
1008
0
                    FatalErrorOnInit("failed to setup dataset for %s", set_name);
1009
0
                    continue;
1010
0
                }
1011
0
                SCLogDebug("dataset %s: id %u type %s", set_name, dset->id, set_type->val);
1012
0
                dset->from_yaml = true;
1013
1014
0
            } else if (strcmp(set_type->val, "sha256") == 0) {
1015
0
                Dataset *dset = DatasetGet(set_name, DATASET_TYPE_SHA256, save, load,
1016
0
                        memcap > 0 ? memcap : default_memcap,
1017
0
                        hashsize > 0 ? hashsize : default_hashsize);
1018
0
                if (dset == NULL) {
1019
0
                    FatalErrorOnInit("failed to setup dataset for %s", set_name);
1020
0
                    continue;
1021
0
                }
1022
0
                SCLogDebug("dataset %s: id %u type %s", set_name, dset->id, set_type->val);
1023
0
                dset->from_yaml = true;
1024
1025
0
            } else if (strcmp(set_type->val, "string") == 0) {
1026
0
                Dataset *dset = DatasetGet(set_name, DATASET_TYPE_STRING, save, load,
1027
0
                        memcap > 0 ? memcap : default_memcap,
1028
0
                        hashsize > 0 ? hashsize : default_hashsize);
1029
0
                if (dset == NULL) {
1030
0
                    FatalErrorOnInit("failed to setup dataset for %s", set_name);
1031
0
                    continue;
1032
0
                }
1033
0
                SCLogDebug("dataset %s: id %u type %s", set_name, dset->id, set_type->val);
1034
0
                dset->from_yaml = true;
1035
1036
0
            } else if (strcmp(set_type->val, "ipv4") == 0) {
1037
0
                Dataset *dset = DatasetGet(set_name, DATASET_TYPE_IPV4, save, load,
1038
0
                        memcap > 0 ? memcap : default_memcap,
1039
0
                        hashsize > 0 ? hashsize : default_hashsize);
1040
0
                if (dset == NULL) {
1041
0
                    FatalErrorOnInit("failed to setup dataset for %s", set_name);
1042
0
                    continue;
1043
0
                }
1044
0
                SCLogDebug("dataset %s: id %u type %s", set_name, dset->id, set_type->val);
1045
0
                dset->from_yaml = true;
1046
1047
0
            } else if (strcmp(set_type->val, "ip") == 0) {
1048
0
                Dataset *dset = DatasetGet(set_name, DATASET_TYPE_IPV6, save, load,
1049
0
                        memcap > 0 ? memcap : default_memcap,
1050
0
                        hashsize > 0 ? hashsize : default_hashsize);
1051
0
                if (dset == NULL) {
1052
0
                    FatalErrorOnInit("failed to setup dataset for %s", set_name);
1053
0
                    continue;
1054
0
                }
1055
0
                SCLogDebug("dataset %s: id %u type %s", set_name, dset->id, set_type->val);
1056
0
                dset->from_yaml = true;
1057
0
            }
1058
1059
0
            list_pos++;
1060
0
        }
1061
4
    }
1062
5
    SCLogDebug("datasets done: %p", datasets);
1063
5
    return 0;
1064
5
}
1065
1066
void DatasetsDestroy(void)
1067
0
{
1068
0
    SCLogDebug("destroying datasets: %p", sets);
1069
0
    SCMutexLock(&sets_lock);
1070
0
    Dataset *set = sets;
1071
0
    while (set) {
1072
0
        SCLogDebug("destroying set %s", set->name);
1073
0
        Dataset *next = set->next;
1074
0
        THashShutdown(set->hash);
1075
0
        SCFree(set);
1076
0
        set = next;
1077
0
    }
1078
0
    sets = NULL;
1079
0
    SCMutexUnlock(&sets_lock);
1080
0
    SCLogDebug("destroying datasets done: %p", sets);
1081
0
}
1082
1083
static int SaveCallback(void *ctx, const uint8_t *data, const uint32_t data_len)
1084
0
{
1085
0
    FILE *fp = ctx;
1086
    //PrintRawDataFp(fp, data, data_len);
1087
0
    if (fp) {
1088
0
        return fwrite(data, data_len, 1, fp);
1089
0
    }
1090
0
    return 0;
1091
0
}
1092
1093
static int Md5AsAscii(const void *s, char *out, size_t out_size)
1094
0
{
1095
0
    const Md5Type *md5 = s;
1096
0
    char str[256];
1097
0
    PrintHexString(str, sizeof(str), (uint8_t *)md5->md5, sizeof(md5->md5));
1098
0
    strlcat(out, str, out_size);
1099
0
    strlcat(out, "\n", out_size);
1100
0
    return strlen(out);
1101
0
}
1102
1103
static int Sha256AsAscii(const void *s, char *out, size_t out_size)
1104
0
{
1105
0
    const Sha256Type *sha = s;
1106
0
    char str[256];
1107
0
    PrintHexString(str, sizeof(str), (uint8_t *)sha->sha256, sizeof(sha->sha256));
1108
0
    strlcat(out, str, out_size);
1109
0
    strlcat(out, "\n", out_size);
1110
0
    return strlen(out);
1111
0
}
1112
1113
static int IPv4AsAscii(const void *s, char *out, size_t out_size)
1114
0
{
1115
0
    const IPv4Type *ip4 = s;
1116
0
    char str[256];
1117
0
    PrintInet(AF_INET, ip4->ipv4, str, sizeof(str));
1118
0
    strlcat(out, str, out_size);
1119
0
    strlcat(out, "\n", out_size);
1120
0
    return strlen(out);
1121
0
}
1122
1123
static int IPv6AsAscii(const void *s, char *out, size_t out_size)
1124
0
{
1125
0
    const IPv6Type *ip6 = s;
1126
0
    char str[256];
1127
0
    bool is_ipv4 = true;
1128
0
    for (int i = 4; i <= 15; i++) {
1129
0
        if (ip6->ipv6[i] != 0) {
1130
0
            is_ipv4 = false;
1131
0
            break;
1132
0
        }
1133
0
    }
1134
0
    if (is_ipv4) {
1135
0
        PrintInet(AF_INET, ip6->ipv6, str, sizeof(str));
1136
0
    } else {
1137
0
        PrintInet(AF_INET6, ip6->ipv6, str, sizeof(str));
1138
0
    }
1139
0
    strlcat(out, str, out_size);
1140
0
    strlcat(out, "\n", out_size);
1141
0
    return strlen(out);
1142
0
}
1143
1144
void DatasetsSave(void)
1145
0
{
1146
0
    SCLogDebug("saving datasets: %p", sets);
1147
0
    SCMutexLock(&sets_lock);
1148
0
    Dataset *set = sets;
1149
0
    while (set) {
1150
0
        if (strlen(set->save) == 0)
1151
0
            goto next;
1152
1153
0
        FILE *fp = fopen(set->save, "w");
1154
0
        if (fp == NULL)
1155
0
            goto next;
1156
1157
0
        SCLogDebug("dumping %s to %s", set->name, set->save);
1158
1159
0
        switch (set->type) {
1160
0
            case DATASET_TYPE_STRING:
1161
0
                THashWalk(set->hash, StringAsBase64, SaveCallback, fp);
1162
0
                break;
1163
0
            case DATASET_TYPE_MD5:
1164
0
                THashWalk(set->hash, Md5AsAscii, SaveCallback, fp);
1165
0
                break;
1166
0
            case DATASET_TYPE_SHA256:
1167
0
                THashWalk(set->hash, Sha256AsAscii, SaveCallback, fp);
1168
0
                break;
1169
0
            case DATASET_TYPE_IPV4:
1170
0
                THashWalk(set->hash, IPv4AsAscii, SaveCallback, fp);
1171
0
                break;
1172
0
            case DATASET_TYPE_IPV6:
1173
0
                THashWalk(set->hash, IPv6AsAscii, SaveCallback, fp);
1174
0
                break;
1175
0
        }
1176
1177
0
        fclose(fp);
1178
1179
0
    next:
1180
0
        set = set->next;
1181
0
    }
1182
0
    SCMutexUnlock(&sets_lock);
1183
0
}
1184
1185
static int DatasetLookupString(Dataset *set, const uint8_t *data, const uint32_t data_len)
1186
15
{
1187
15
    if (set == NULL)
1188
0
        return -1;
1189
1190
15
    StringType lookup = { .ptr = (uint8_t *)data, .len = data_len, .rep.value = 0 };
1191
15
    THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1192
15
    if (rdata) {
1193
0
        DatasetUnlockData(rdata);
1194
0
        return 1;
1195
0
    }
1196
15
    return 0;
1197
15
}
1198
1199
static DataRepResultType DatasetLookupStringwRep(Dataset *set,
1200
        const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1201
486
{
1202
486
    DataRepResultType rrep = { .found = false, .rep = { .value = 0 }};
1203
1204
486
    if (set == NULL)
1205
0
        return rrep;
1206
1207
486
    StringType lookup = { .ptr = (uint8_t *)data, .len = data_len, .rep = *rep };
1208
486
    THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1209
486
    if (rdata) {
1210
0
        StringType *found = rdata->data;
1211
0
        rrep.found = true;
1212
0
        rrep.rep = found->rep;
1213
0
        DatasetUnlockData(rdata);
1214
0
        return rrep;
1215
0
    }
1216
486
    return rrep;
1217
486
}
1218
1219
static int DatasetLookupIPv4(Dataset *set, const uint8_t *data, const uint32_t data_len)
1220
250
{
1221
250
    if (set == NULL)
1222
0
        return -1;
1223
1224
250
    if (data_len != 4)
1225
6
        return -1;
1226
1227
244
    IPv4Type lookup = { .rep.value = 0 };
1228
244
    memcpy(lookup.ipv4, data, 4);
1229
244
    THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1230
244
    if (rdata) {
1231
0
        DatasetUnlockData(rdata);
1232
0
        return 1;
1233
0
    }
1234
244
    return 0;
1235
244
}
1236
1237
static DataRepResultType DatasetLookupIPv4wRep(
1238
        Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1239
0
{
1240
0
    DataRepResultType rrep = { .found = false, .rep = { .value = 0 } };
1241
1242
0
    if (set == NULL)
1243
0
        return rrep;
1244
1245
0
    if (data_len != 4)
1246
0
        return rrep;
1247
1248
0
    IPv4Type lookup = { .rep.value = 0 };
1249
0
    memcpy(lookup.ipv4, data, data_len);
1250
0
    THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1251
0
    if (rdata) {
1252
0
        IPv4Type *found = rdata->data;
1253
0
        rrep.found = true;
1254
0
        rrep.rep = found->rep;
1255
0
        DatasetUnlockData(rdata);
1256
0
        return rrep;
1257
0
    }
1258
0
    return rrep;
1259
0
}
1260
1261
static int DatasetLookupIPv6(Dataset *set, const uint8_t *data, const uint32_t data_len)
1262
264
{
1263
264
    if (set == NULL)
1264
0
        return -1;
1265
1266
264
    if (data_len != 16 && data_len != 4)
1267
0
        return -1;
1268
1269
264
    IPv6Type lookup = { .rep.value = 0 };
1270
264
    memcpy(lookup.ipv6, data, data_len);
1271
264
    THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1272
264
    if (rdata) {
1273
0
        DatasetUnlockData(rdata);
1274
0
        return 1;
1275
0
    }
1276
264
    return 0;
1277
264
}
1278
1279
static DataRepResultType DatasetLookupIPv6wRep(
1280
        Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1281
0
{
1282
0
    DataRepResultType rrep = { .found = false, .rep = { .value = 0 } };
1283
1284
0
    if (set == NULL)
1285
0
        return rrep;
1286
1287
0
    if (data_len != 16 && data_len != 4)
1288
0
        return rrep;
1289
1290
0
    IPv6Type lookup = { .rep.value = 0 };
1291
0
    memcpy(lookup.ipv6, data, data_len);
1292
0
    THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1293
0
    if (rdata) {
1294
0
        IPv6Type *found = rdata->data;
1295
0
        rrep.found = true;
1296
0
        rrep.rep = found->rep;
1297
0
        DatasetUnlockData(rdata);
1298
0
        return rrep;
1299
0
    }
1300
0
    return rrep;
1301
0
}
1302
1303
static int DatasetLookupMd5(Dataset *set, const uint8_t *data, const uint32_t data_len)
1304
12
{
1305
12
    if (set == NULL)
1306
0
        return -1;
1307
1308
12
    if (data_len != 16)
1309
12
        return -1;
1310
1311
0
    Md5Type lookup = { .rep.value = 0 };
1312
0
    memcpy(lookup.md5, data, data_len);
1313
0
    THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1314
0
    if (rdata) {
1315
0
        DatasetUnlockData(rdata);
1316
0
        return 1;
1317
0
    }
1318
0
    return 0;
1319
0
}
1320
1321
static DataRepResultType DatasetLookupMd5wRep(Dataset *set,
1322
        const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1323
18
{
1324
18
    DataRepResultType rrep = { .found = false, .rep = { .value = 0 }};
1325
1326
18
    if (set == NULL)
1327
0
        return rrep;
1328
1329
18
    if (data_len != 16)
1330
10
        return rrep;
1331
1332
8
    Md5Type lookup = { .rep.value = 0};
1333
8
    memcpy(lookup.md5, data, data_len);
1334
8
    THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1335
8
    if (rdata) {
1336
0
        Md5Type *found = rdata->data;
1337
0
        rrep.found = true;
1338
0
        rrep.rep = found->rep;
1339
0
        DatasetUnlockData(rdata);
1340
0
        return rrep;
1341
0
    }
1342
8
    return rrep;
1343
8
}
1344
1345
static int DatasetLookupSha256(Dataset *set, const uint8_t *data, const uint32_t data_len)
1346
0
{
1347
0
    if (set == NULL)
1348
0
        return -1;
1349
1350
0
    if (data_len != 32)
1351
0
        return -1;
1352
1353
0
    Sha256Type lookup = { .rep.value = 0 };
1354
0
    memcpy(lookup.sha256, data, data_len);
1355
0
    THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1356
0
    if (rdata) {
1357
0
        DatasetUnlockData(rdata);
1358
0
        return 1;
1359
0
    }
1360
0
    return 0;
1361
0
}
1362
1363
static DataRepResultType DatasetLookupSha256wRep(Dataset *set,
1364
        const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1365
29
{
1366
29
    DataRepResultType rrep = { .found = false, .rep = { .value = 0 }};
1367
1368
29
    if (set == NULL)
1369
0
        return rrep;
1370
1371
29
    if (data_len != 32)
1372
29
        return rrep;
1373
1374
0
    Sha256Type lookup = { .rep.value = 0 };
1375
0
    memcpy(lookup.sha256, data, data_len);
1376
0
    THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1377
0
    if (rdata) {
1378
0
        Sha256Type *found = rdata->data;
1379
0
        rrep.found = true;
1380
0
        rrep.rep = found->rep;
1381
0
        DatasetUnlockData(rdata);
1382
0
        return rrep;
1383
0
    }
1384
0
    return rrep;
1385
0
}
1386
1387
/**
1388
 *  \brief see if \a data is part of the set
1389
 *  \param set dataset
1390
 *  \param data data to look up
1391
 *  \param data_len length in bytes of \a data
1392
 *  \retval -1 error
1393
 *  \retval 0 not found
1394
 *  \retval 1 found
1395
 */
1396
int DatasetLookup(Dataset *set, const uint8_t *data, const uint32_t data_len)
1397
541
{
1398
541
    if (set == NULL)
1399
0
        return -1;
1400
1401
541
    switch (set->type) {
1402
15
        case DATASET_TYPE_STRING:
1403
15
            return DatasetLookupString(set, data, data_len);
1404
12
        case DATASET_TYPE_MD5:
1405
12
            return DatasetLookupMd5(set, data, data_len);
1406
0
        case DATASET_TYPE_SHA256:
1407
0
            return DatasetLookupSha256(set, data, data_len);
1408
250
        case DATASET_TYPE_IPV4:
1409
250
            return DatasetLookupIPv4(set, data, data_len);
1410
264
        case DATASET_TYPE_IPV6:
1411
264
            return DatasetLookupIPv6(set, data, data_len);
1412
541
    }
1413
0
    return -1;
1414
541
}
1415
1416
DataRepResultType DatasetLookupwRep(Dataset *set, const uint8_t *data, const uint32_t data_len,
1417
        const DataRepType *rep)
1418
533
{
1419
533
    DataRepResultType rrep = { .found = false, .rep = { .value = 0 }};
1420
533
    if (set == NULL)
1421
0
        return rrep;
1422
1423
533
    switch (set->type) {
1424
486
        case DATASET_TYPE_STRING:
1425
486
            return DatasetLookupStringwRep(set, data, data_len, rep);
1426
18
        case DATASET_TYPE_MD5:
1427
18
            return DatasetLookupMd5wRep(set, data, data_len, rep);
1428
29
        case DATASET_TYPE_SHA256:
1429
29
            return DatasetLookupSha256wRep(set, data, data_len, rep);
1430
0
        case DATASET_TYPE_IPV4:
1431
0
            return DatasetLookupIPv4wRep(set, data, data_len, rep);
1432
0
        case DATASET_TYPE_IPV6:
1433
0
            return DatasetLookupIPv6wRep(set, data, data_len, rep);
1434
533
    }
1435
0
    return rrep;
1436
533
}
1437
1438
/**
1439
 *  \retval 1 data was added to the hash
1440
 *  \retval 0 data was not added to the hash as it is already there
1441
 *  \retval -1 failed to add data to the hash
1442
 */
1443
static int DatasetAddString(Dataset *set, const uint8_t *data, const uint32_t data_len)
1444
56.5k
{
1445
56.5k
    if (set == NULL)
1446
0
        return -1;
1447
1448
56.5k
    StringType lookup = { .ptr = (uint8_t *)data, .len = data_len,
1449
56.5k
        .rep.value = 0 };
1450
56.5k
    struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1451
56.5k
    if (res.data) {
1452
56.5k
        DatasetUnlockData(res.data);
1453
56.5k
        return res.is_new ? 1 : 0;
1454
56.5k
    }
1455
0
    return -1;
1456
56.5k
}
1457
1458
/**
1459
 *  \retval 1 data was added to the hash
1460
 *  \retval 0 data was not added to the hash as it is already there
1461
 *  \retval -1 failed to add data to the hash
1462
 */
1463
static int DatasetAddStringwRep(
1464
        Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1465
0
{
1466
0
    if (set == NULL)
1467
0
        return -1;
1468
1469
0
    StringType lookup = { .ptr = (uint8_t *)data, .len = data_len,
1470
0
        .rep = *rep };
1471
0
    struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1472
0
    if (res.data) {
1473
0
        DatasetUnlockData(res.data);
1474
0
        return res.is_new ? 1 : 0;
1475
0
    }
1476
0
    return -1;
1477
0
}
1478
1479
static int DatasetAddIPv4(Dataset *set, const uint8_t *data, const uint32_t data_len)
1480
22.1k
{
1481
22.1k
    if (set == NULL) {
1482
0
        return -1;
1483
0
    }
1484
1485
22.1k
    if (data_len < 4) {
1486
0
        return -2;
1487
0
    }
1488
1489
22.1k
    IPv4Type lookup = { .rep.value = 0 };
1490
22.1k
    memcpy(lookup.ipv4, data, 4);
1491
22.1k
    struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1492
22.1k
    if (res.data) {
1493
22.1k
        DatasetUnlockData(res.data);
1494
22.1k
        return res.is_new ? 1 : 0;
1495
22.1k
    }
1496
0
    return -1;
1497
22.1k
}
1498
1499
static int DatasetAddIPv6(Dataset *set, const uint8_t *data, const uint32_t data_len)
1500
8.99k
{
1501
8.99k
    if (set == NULL) {
1502
0
        return -1;
1503
0
    }
1504
1505
8.99k
    if (data_len != 16 && data_len != 4) {
1506
0
        return -2;
1507
0
    }
1508
1509
8.99k
    IPv6Type lookup = { .rep.value = 0 };
1510
8.99k
    memcpy(lookup.ipv6, data, data_len);
1511
8.99k
    struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1512
8.99k
    if (res.data) {
1513
8.99k
        DatasetUnlockData(res.data);
1514
8.99k
        return res.is_new ? 1 : 0;
1515
8.99k
    }
1516
0
    return -1;
1517
8.99k
}
1518
1519
static int DatasetAddIPv4wRep(
1520
        Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1521
0
{
1522
0
    if (set == NULL)
1523
0
        return -1;
1524
1525
0
    if (data_len < 4)
1526
0
        return -2;
1527
1528
0
    IPv4Type lookup = { .rep = *rep };
1529
0
    memcpy(lookup.ipv4, data, 4);
1530
0
    struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1531
0
    if (res.data) {
1532
0
        DatasetUnlockData(res.data);
1533
0
        return res.is_new ? 1 : 0;
1534
0
    }
1535
0
    return -1;
1536
0
}
1537
1538
static int DatasetAddIPv6wRep(
1539
        Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1540
0
{
1541
0
    if (set == NULL)
1542
0
        return -1;
1543
1544
0
    if (data_len != 16)
1545
0
        return -2;
1546
1547
0
    IPv6Type lookup = { .rep = *rep };
1548
0
    memcpy(lookup.ipv6, data, 16);
1549
0
    struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1550
0
    if (res.data) {
1551
0
        DatasetUnlockData(res.data);
1552
0
        return res.is_new ? 1 : 0;
1553
0
    }
1554
0
    return -1;
1555
0
}
1556
1557
static int DatasetAddMd5(Dataset *set, const uint8_t *data, const uint32_t data_len)
1558
25
{
1559
25
    if (set == NULL)
1560
0
        return -1;
1561
1562
25
    if (data_len != 16)
1563
25
        return -2;
1564
1565
0
    Md5Type lookup = { .rep.value = 0 };
1566
0
    memcpy(lookup.md5, data, 16);
1567
0
    struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1568
0
    if (res.data) {
1569
0
        DatasetUnlockData(res.data);
1570
0
        return res.is_new ? 1 : 0;
1571
0
    }
1572
0
    return -1;
1573
0
}
1574
1575
static int DatasetAddMd5wRep(
1576
        Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1577
0
{
1578
0
    if (set == NULL)
1579
0
        return -1;
1580
1581
0
    if (data_len != 16)
1582
0
        return -2;
1583
1584
0
    Md5Type lookup = { .rep = *rep };
1585
0
    memcpy(lookup.md5, data, 16);
1586
0
    struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1587
0
    if (res.data) {
1588
0
        DatasetUnlockData(res.data);
1589
0
        return res.is_new ? 1 : 0;
1590
0
    }
1591
0
    return -1;
1592
0
}
1593
1594
static int DatasetAddSha256wRep(
1595
        Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1596
0
{
1597
0
    if (set == NULL)
1598
0
        return -1;
1599
1600
0
    if (data_len != 32)
1601
0
        return -2;
1602
1603
0
    Sha256Type lookup = { .rep = *rep };
1604
0
    memcpy(lookup.sha256, data, 32);
1605
0
    struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1606
0
    if (res.data) {
1607
0
        DatasetUnlockData(res.data);
1608
0
        return res.is_new ? 1 : 0;
1609
0
    }
1610
0
    return -1;
1611
0
}
1612
1613
static int DatasetAddSha256(Dataset *set, const uint8_t *data, const uint32_t data_len)
1614
2
{
1615
2
    if (set == NULL)
1616
0
        return -1;
1617
1618
2
    if (data_len != 32)
1619
2
        return -2;
1620
1621
0
    Sha256Type lookup = { .rep.value = 0 };
1622
0
    memcpy(lookup.sha256, data, 32);
1623
0
    struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1624
0
    if (res.data) {
1625
0
        DatasetUnlockData(res.data);
1626
0
        return res.is_new ? 1 : 0;
1627
0
    }
1628
0
    return -1;
1629
0
}
1630
1631
int DatasetAdd(Dataset *set, const uint8_t *data, const uint32_t data_len)
1632
22.5k
{
1633
22.5k
    if (set == NULL)
1634
0
        return -1;
1635
1636
22.5k
    switch (set->type) {
1637
6.71k
        case DATASET_TYPE_STRING:
1638
6.71k
            return DatasetAddString(set, data, data_len);
1639
10
        case DATASET_TYPE_MD5:
1640
10
            return DatasetAddMd5(set, data, data_len);
1641
0
        case DATASET_TYPE_SHA256:
1642
0
            return DatasetAddSha256(set, data, data_len);
1643
12.8k
        case DATASET_TYPE_IPV4:
1644
12.8k
            return DatasetAddIPv4(set, data, data_len);
1645
2.97k
        case DATASET_TYPE_IPV6:
1646
2.97k
            return DatasetAddIPv6(set, data, data_len);
1647
22.5k
    }
1648
0
    return -1;
1649
22.5k
}
1650
1651
static int DatasetAddwRep(Dataset *set, const uint8_t *data, const uint32_t data_len,
1652
        DataRepType *rep)
1653
0
{
1654
0
    if (set == NULL)
1655
0
        return -1;
1656
1657
0
    switch (set->type) {
1658
0
        case DATASET_TYPE_STRING:
1659
0
            return DatasetAddStringwRep(set, data, data_len, rep);
1660
0
        case DATASET_TYPE_MD5:
1661
0
            return DatasetAddMd5wRep(set, data, data_len, rep);
1662
0
        case DATASET_TYPE_SHA256:
1663
0
            return DatasetAddSha256wRep(set, data, data_len, rep);
1664
0
        case DATASET_TYPE_IPV4:
1665
0
            return DatasetAddIPv4wRep(set, data, data_len, rep);
1666
0
        case DATASET_TYPE_IPV6:
1667
0
            return DatasetAddIPv6wRep(set, data, data_len, rep);
1668
0
    }
1669
0
    return -1;
1670
0
}
1671
1672
typedef int (*DatasetOpFunc)(Dataset *set, const uint8_t *data, const uint32_t data_len);
1673
1674
static int DatasetOpSerialized(Dataset *set, const char *string, DatasetOpFunc DatasetOpString,
1675
        DatasetOpFunc DatasetOpMd5, DatasetOpFunc DatasetOpSha256, DatasetOpFunc DatasetOpIPv4,
1676
        DatasetOpFunc DatasetOpIPv6)
1677
0
{
1678
0
    if (set == NULL)
1679
0
        return -1;
1680
1681
0
    switch (set->type) {
1682
0
        case DATASET_TYPE_STRING: {
1683
            // coverity[alloc_strlen : FALSE]
1684
0
            uint8_t decoded[strlen(string)];
1685
0
            uint32_t consumed = 0, num_decoded = 0;
1686
0
            Base64Ecode code = DecodeBase64(decoded, strlen(string), (const uint8_t *)string,
1687
0
                    strlen(string), &consumed, &num_decoded, BASE64_MODE_STRICT);
1688
0
            if (code == BASE64_ECODE_ERR) {
1689
0
                return -2;
1690
0
            }
1691
1692
0
            return DatasetOpString(set, decoded, num_decoded);
1693
0
        }
1694
0
        case DATASET_TYPE_MD5: {
1695
0
            if (strlen(string) != 32)
1696
0
                return -2;
1697
0
            uint8_t hash[16];
1698
0
            if (HexToRaw((const uint8_t *)string, 32, hash, sizeof(hash)) < 0)
1699
0
                return -2;
1700
0
            return DatasetOpMd5(set, hash, 16);
1701
0
        }
1702
0
        case DATASET_TYPE_SHA256: {
1703
0
            if (strlen(string) != 64)
1704
0
                return -2;
1705
0
            uint8_t hash[32];
1706
0
            if (HexToRaw((const uint8_t *)string, 64, hash, sizeof(hash)) < 0)
1707
0
                return -2;
1708
0
            return DatasetOpSha256(set, hash, 32);
1709
0
        }
1710
0
        case DATASET_TYPE_IPV4: {
1711
0
            struct in_addr in;
1712
0
            if (inet_pton(AF_INET, string, &in) != 1)
1713
0
                return -2;
1714
0
            return DatasetOpIPv4(set, (uint8_t *)&in.s_addr, 4);
1715
0
        }
1716
0
        case DATASET_TYPE_IPV6: {
1717
0
            struct in6_addr in6;
1718
0
            if (ParseIpv6String(set, string, &in6) != 0) {
1719
0
                SCLogError("Dataset failed to import %s as IPv6", string);
1720
0
                return -2;
1721
0
            }
1722
0
            return DatasetOpIPv6(set, (uint8_t *)&in6.s6_addr, 16);
1723
0
        }
1724
0
    }
1725
0
    return -1;
1726
0
}
1727
1728
/** \brief add serialized data to set
1729
 *  \retval int 1 added
1730
 *  \retval int 0 already in hash
1731
 *  \retval int -1 API error (not added)
1732
 *  \retval int -2 DATA error
1733
 */
1734
int DatasetAddSerialized(Dataset *set, const char *string)
1735
0
{
1736
0
    return DatasetOpSerialized(set, string, DatasetAddString, DatasetAddMd5, DatasetAddSha256,
1737
0
            DatasetAddIPv4, DatasetAddIPv6);
1738
0
}
1739
1740
/** \brief add serialized data to set
1741
 *  \retval int 1 added
1742
 *  \retval int 0 already in hash
1743
 *  \retval int -1 API error (not added)
1744
 *  \retval int -2 DATA error
1745
 */
1746
int DatasetLookupSerialized(Dataset *set, const char *string)
1747
0
{
1748
0
    return DatasetOpSerialized(set, string, DatasetLookupString, DatasetLookupMd5,
1749
0
            DatasetLookupSha256, DatasetLookupIPv4, DatasetLookupIPv6);
1750
0
}
1751
1752
/**
1753
 *  \retval 1 data was removed from the hash
1754
 *  \retval 0 data not removed (busy)
1755
 *  \retval -1 data not found
1756
 */
1757
static int DatasetRemoveString(Dataset *set, const uint8_t *data, const uint32_t data_len)
1758
1
{
1759
1
    if (set == NULL)
1760
0
        return -1;
1761
1762
1
    StringType lookup = { .ptr = (uint8_t *)data, .len = data_len,
1763
1
        .rep.value = 0 };
1764
1
    return THashRemoveFromHash(set->hash, &lookup);
1765
1
}
1766
1767
static int DatasetRemoveIPv4(Dataset *set, const uint8_t *data, const uint32_t data_len)
1768
0
{
1769
0
    if (set == NULL)
1770
0
        return -1;
1771
1772
0
    if (data_len != 4)
1773
0
        return -2;
1774
1775
0
    IPv4Type lookup = { .rep.value = 0 };
1776
0
    memcpy(lookup.ipv4, data, 4);
1777
0
    return THashRemoveFromHash(set->hash, &lookup);
1778
0
}
1779
1780
static int DatasetRemoveIPv6(Dataset *set, const uint8_t *data, const uint32_t data_len)
1781
0
{
1782
0
    if (set == NULL)
1783
0
        return -1;
1784
1785
0
    if (data_len != 16)
1786
0
        return -2;
1787
1788
0
    IPv6Type lookup = { .rep.value = 0 };
1789
0
    memcpy(lookup.ipv6, data, 16);
1790
0
    return THashRemoveFromHash(set->hash, &lookup);
1791
0
}
1792
1793
static int DatasetRemoveMd5(Dataset *set, const uint8_t *data, const uint32_t data_len)
1794
0
{
1795
0
    if (set == NULL)
1796
0
        return -1;
1797
1798
0
    if (data_len != 16)
1799
0
        return -2;
1800
1801
0
    Md5Type lookup = { .rep.value = 0 };
1802
0
    memcpy(lookup.md5, data, 16);
1803
0
    return THashRemoveFromHash(set->hash, &lookup);
1804
0
}
1805
1806
static int DatasetRemoveSha256(Dataset *set, const uint8_t *data, const uint32_t data_len)
1807
0
{
1808
0
    if (set == NULL)
1809
0
        return -1;
1810
1811
0
    if (data_len != 32)
1812
0
        return -2;
1813
1814
0
    Sha256Type lookup = { .rep.value = 0 };
1815
0
    memcpy(lookup.sha256, data, 32);
1816
0
    return THashRemoveFromHash(set->hash, &lookup);
1817
0
}
1818
1819
/** \brief remove serialized data from set
1820
 *  \retval int 1 removed
1821
 *  \retval int 0 found but busy (not removed)
1822
 *  \retval int -1 API error (not removed)
1823
 *  \retval int -2 DATA error */
1824
int DatasetRemoveSerialized(Dataset *set, const char *string)
1825
0
{
1826
0
    return DatasetOpSerialized(set, string, DatasetRemoveString, DatasetRemoveMd5,
1827
0
            DatasetRemoveSha256, DatasetRemoveIPv4, DatasetRemoveIPv6);
1828
0
}
1829
1830
int DatasetRemove(Dataset *set, const uint8_t *data, const uint32_t data_len)
1831
1
{
1832
1
    if (set == NULL)
1833
0
        return -1;
1834
1835
1
    switch (set->type) {
1836
1
        case DATASET_TYPE_STRING:
1837
1
            return DatasetRemoveString(set, data, data_len);
1838
0
        case DATASET_TYPE_MD5:
1839
0
            return DatasetRemoveMd5(set, data, data_len);
1840
0
        case DATASET_TYPE_SHA256:
1841
0
            return DatasetRemoveSha256(set, data, data_len);
1842
0
        case DATASET_TYPE_IPV4:
1843
0
            return DatasetRemoveIPv4(set, data, data_len);
1844
0
        case DATASET_TYPE_IPV6:
1845
0
            return DatasetRemoveIPv6(set, data, data_len);
1846
1
    }
1847
0
    return -1;
1848
1
}