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

jasonish / suricata / 23105300094

15 Mar 2026 06:48AM UTC coverage: 75.784% (-0.7%) from 76.495%
23105300094

push

github

jasonish
github-ci: ubuntu minimal build fixups

- Don't run on the GitHub provided VM, it contains a newer Rust than
  stock Ubuntu does.

252836 of 333628 relevant lines covered (75.78%)

1978514.46 hits per line

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

81.84
/src/reputation.c
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 Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
22
 * \author Victor Julien <victor@inliniac.net>
23
 *         Original Idea by Matt Jonkman
24
 *
25
 * IP Reputation Module, initial API for IPV4 and IPV6 feed
26
 */
27

28
#include "suricata-common.h"
29
#include "detect.h"
30
#include "reputation.h"
31
#include "threads.h"
32
#include "conf.h"
33

34
#include "util-byte.h"
35
#include "util-debug.h"
36
#include "util-error.h"
37
#include "util-ip.h"
38
#include "util-path.h"
39
#include "util-print.h"
40
#include "util-unittest.h"
41
#include "util-validate.h"
42
#include "util-radix4-tree.h"
43
#include "util-radix6-tree.h"
44

45
/** effective reputation version, atomic as the host
46
 *  time out code will use it to check if a host's
47
 *  reputation info is outdated. */
48
SC_ATOMIC_DECLARE(uint32_t, srep_eversion);
49
/** reputation version set to the host's reputation,
50
 *  this will be set to 1 before rep files are loaded,
51
 *  so hosts will always have a minimal value of 1 */
52
static uint32_t srep_version = 0;
53

54
static uint32_t SRepIncrVersion(void)
55
{
19✔
56
    return ++srep_version;
19✔
57
}
19✔
58

59
static uint32_t SRepGetVersion(void)
60
{
166,225✔
61
    return srep_version;
166,225✔
62
}
166,225✔
63

64
void SRepResetVersion(void)
65
{
11✔
66
    srep_version = 0;
11✔
67
}
11✔
68

69
static uint32_t SRepGetEffectiveVersion(void)
70
{
×
71
    return SC_ATOMIC_GET(srep_eversion);
×
72
}
×
73

74
static void SRepCIDRFreeUserData(void *data)
75
{
2,415✔
76
    if (data != NULL)
2,415✔
77
        SCFree(data);
2,415✔
78
}
2,415✔
79

80
static SCRadix4Config iprep_radix4_config = { SRepCIDRFreeUserData, NULL };
81
static SCRadix6Config iprep_radix6_config = { SRepCIDRFreeUserData, NULL };
82

83
static void SRepCIDRAddNetblock(SRepCIDRTree *cidr_ctx, char *ip, int cat, uint8_t value)
84
{
2,419✔
85
    SReputation *user_data = NULL;
2,419✔
86
    if ((user_data = SCCalloc(1, sizeof(SReputation))) == NULL) {
2,419✔
87
        FatalError("Error allocating memory. Exiting");
×
88
    }
×
89

90
    user_data->version = SRepGetVersion();
2,419✔
91
    user_data->rep[cat] = value;
2,419✔
92

93
    if (strchr(ip, ':') != NULL) {
2,419✔
94
        SCLogDebug("adding ipv6 host %s", ip);
6✔
95
        if (!SCRadix6AddKeyIPV6String(
6✔
96
                    &cidr_ctx->srep_ipv6_tree[cat], &iprep_radix6_config, ip, (void *)user_data)) {
6✔
97
            SCFree(user_data);
2✔
98
            if (sc_errno != SC_EEXIST)
2✔
99
                SCLogWarning("failed to add ipv6 host %s", ip);
×
100
        }
2✔
101

102
    } else {
2,413✔
103
        SCLogDebug("adding ipv4 host %s", ip);
2,413✔
104
        if (!SCRadix4AddKeyIPV4String(
2,413✔
105
                    &cidr_ctx->srep_ipv4_tree[cat], &iprep_radix4_config, ip, (void *)user_data)) {
2,413✔
106
            SCFree(user_data);
2✔
107
            if (sc_errno != SC_EEXIST)
2✔
108
                SCLogWarning("failed to add ipv4 host %s", ip);
×
109
        }
2✔
110
    }
2,413✔
111
}
2,419✔
112

113
static int8_t SRepCIDRGetIPv4IPRep(SRepCIDRTree *cidr_ctx, uint8_t *ipv4_addr, uint8_t cat)
114
{
208✔
115
    void *user_data = NULL;
208✔
116
    (void)SCRadix4TreeFindBestMatch(&cidr_ctx->srep_ipv4_tree[cat], ipv4_addr, &user_data);
208✔
117
    if (user_data == NULL)
208✔
118
        return -1;
77✔
119

120
    SReputation *r = (SReputation *)user_data;
131✔
121
    return r->rep[cat];
131✔
122
}
208✔
123

124
static int8_t SRepCIDRGetIPv6IPRep(SRepCIDRTree *cidr_ctx, uint8_t *ipv6_addr, uint8_t cat)
125
{
1✔
126
    void *user_data = NULL;
1✔
127
    (void)SCRadix6TreeFindBestMatch(&cidr_ctx->srep_ipv6_tree[cat], ipv6_addr, &user_data);
1✔
128
    if (user_data == NULL)
1✔
129
        return -1;
×
130

131
    SReputation *r = (SReputation *)user_data;
1✔
132
    return r->rep[cat];
1✔
133
}
1✔
134

135
int8_t SRepCIDRGetIPRepSrc(SRepCIDRTree *cidr_ctx, Packet *p, uint8_t cat, uint32_t version)
136
{
111✔
137
    int8_t rep = -3;
111✔
138

139
    if (PacketIsIPv4(p))
111✔
140
        rep = SRepCIDRGetIPv4IPRep(cidr_ctx, (uint8_t *)GET_IPV4_SRC_ADDR_PTR(p), cat);
110✔
141
    else if (PacketIsIPv6(p))
1✔
142
        rep = SRepCIDRGetIPv6IPRep(cidr_ctx, (uint8_t *)GET_IPV6_SRC_ADDR(p), cat);
1✔
143

144
    return rep;
111✔
145
}
111✔
146

147
int8_t SRepCIDRGetIPRepDst(SRepCIDRTree *cidr_ctx, Packet *p, uint8_t cat, uint32_t version)
148
{
98✔
149
    int8_t rep = -3;
98✔
150

151
    if (PacketIsIPv4(p))
98✔
152
        rep = SRepCIDRGetIPv4IPRep(cidr_ctx, (uint8_t *)GET_IPV4_DST_ADDR_PTR(p), cat);
98✔
153
    else if (PacketIsIPv6(p))
×
154
        rep = SRepCIDRGetIPv6IPRep(cidr_ctx, (uint8_t *)GET_IPV6_DST_ADDR(p), cat);
×
155

156
    return rep;
98✔
157
}
98✔
158

159
/** \brief Increment effective reputation version after
160
 *         a rule/reputation reload is complete. */
161
void SRepReloadComplete(void)
162
{
×
163
    (void) SC_ATOMIC_ADD(srep_eversion, 1);
×
164
    SCLogDebug("effective Reputation version %u", SRepGetEffectiveVersion());
×
165
}
×
166

167
void SRepFreeHostData(Host *h)
168
{
75,106✔
169
    SCFree(h->iprep);
75,106✔
170
    h->iprep = NULL;
75,106✔
171
    DEBUG_VALIDATE_BUG_ON(SC_ATOMIC_GET(h->use_cnt) != 1);
75,106✔
172
    HostDecrUsecnt(h);
75,106✔
173
}
75,106✔
174

175
/** \brief Set effective reputation version after
176
 *         reputation initialization is complete. */
177
static void SRepInitComplete(void)
178
{
19✔
179
    (void) SC_ATOMIC_SET(srep_eversion, 1);
19✔
180
    SCLogDebug("effective Reputation version %u", SRepGetEffectiveVersion());
19✔
181
}
19✔
182

183
/** \brief Check if a Host is timed out wrt ip rep, meaning a new
184
 *         version is in place.
185
 *
186
 *  We clean up the old version here.
187
 *
188
 *  \param h host
189
 *
190
 *  \retval 0 not timed out
191
 *  \retval 1 timed out
192
 */
193
int SRepHostTimedOut(Host *h)
194
{
×
195
    BUG_ON(h == NULL);
×
196

197
    if (h->iprep == NULL)
×
198
        return 1;
×
199

200
    uint32_t eversion = SRepGetEffectiveVersion();
×
201
    SReputation *r = h->iprep;
×
202
    if (r->version < eversion) {
×
203
        SCLogDebug("host %p has reputation version %u, "
×
204
                "effective version is %u", h, r->version, eversion);
×
205
        SRepFreeHostData(h);
×
206
        return 1;
×
207
    }
×
208

209
    return 0;
×
210
}
×
211

212
static int SRepCatSplitLine(char *line, uint8_t *cat, char *shortname, size_t shortname_len)
213
{
73✔
214
    size_t line_len = strlen(line);
73✔
215
    char *ptrs[2] = {NULL,NULL};
73✔
216
    int i = 0;
73✔
217
    int idx = 0;
73✔
218
    char *origline = line;
73✔
219

220
    while (i < (int)line_len) {
717✔
221
        if (line[i] == ',' || line[i] == '\n' || line[i] == '\0' || i == (int)(line_len - 1)) {
717✔
222
            line[i] = '\0';
146✔
223

224
            ptrs[idx] = line;
146✔
225
            idx++;
146✔
226

227
            line += (i+1);
146✔
228
            i = 0;
146✔
229

230
            if (line >= origline + line_len)
146✔
231
                break;
×
232
            if (strlen(line) == 0)
146✔
233
                break;
×
234
            if (idx == 2)
146✔
235
                break;
73✔
236
        } else {
571✔
237
            i++;
571✔
238
        }
571✔
239
    }
717✔
240

241
    if (idx != 2) {
73✔
242
        return -1;
×
243
    }
×
244

245
    SCLogDebug("%s, %s", ptrs[0], ptrs[1]);
73✔
246

247
    int c;
73✔
248
    if (StringParseI32RangeCheck(&c, 10, 0, (const char *)ptrs[0], 0, SREP_MAX_CATS - 1) < 0)
73✔
249
        return -1;
×
250

251
    *cat = (uint8_t)c;
73✔
252
    strlcpy(shortname, ptrs[1], shortname_len);
73✔
253
    return 0;
73✔
254
}
73✔
255

256
/**
257
 *  \retval 0 valid
258
 *  \retval 1 header
259
 *  \retval -1 bad line
260
 */
261
static int SRepSplitLine(SRepCIDRTree *cidr_ctx, char *line, Address *ip, uint8_t *cat, uint8_t *value)
262
{
82,655✔
263
    size_t line_len = strlen(line);
82,655✔
264
    char *ptrs[3] = {NULL,NULL,NULL};
82,655✔
265
    int i = 0;
82,655✔
266
    int idx = 0;
82,655✔
267
    char *origline = line;
82,655✔
268

269
    while (i < (int)line_len) {
1,781,619✔
270
        if (line[i] == ',' || line[i] == '\n' || line[i] == '\r' || line[i] == '\0' ||
1,781,619✔
271
                i == (int)(line_len - 1)) {
1,781,619✔
272
            line[i] = '\0';
247,961✔
273

274
            ptrs[idx] = line;
247,961✔
275
            idx++;
247,961✔
276

277
            line += (i+1);
247,961✔
278
            i = 0;
247,961✔
279

280
            if (line >= origline + line_len)
247,961✔
281
                break;
82,654✔
282
            if (strlen(line) == 0)
165,307✔
283
                break;
×
284
            if (idx == 3)
165,307✔
285
                break;
1✔
286
        } else {
1,533,658✔
287
            i++;
1,533,658✔
288
        }
1,533,658✔
289
    }
1,781,619✔
290

291
    if (idx != 3) {
82,655✔
292
        return -1;
2✔
293
    }
2✔
294

295
    //SCLogInfo("%s, %s, %s", ptrs[0], ptrs[1], ptrs[2]);
296

297
    if (strcmp(ptrs[0], "ip") == 0)
82,653✔
298
        return 1;
×
299

300
    uint8_t c, v;
82,653✔
301
    if (StringParseU8RangeCheck(&c, 10, 0, (const char *)ptrs[1], 0, SREP_MAX_CATS - 1) <= 0)
82,653✔
302
        return -1;
×
303

304
    if (StringParseU8RangeCheck(&v, 10, 0, (const char *)ptrs[2], 0, SREP_MAX_VAL) <= 0)
82,653✔
305
        return -1;
×
306

307
    if (strchr(ptrs[0], '/') != NULL) {
82,653✔
308
        SRepCIDRAddNetblock(cidr_ctx, ptrs[0], c, v);
2,419✔
309
        return 1;
2,419✔
310
    } else {
80,255✔
311
        if (inet_pton(AF_INET, ptrs[0], &ip->address) == 1) {
80,234✔
312
            ip->family = AF_INET;
75,752✔
313
        } else if (inet_pton(AF_INET6, ptrs[0], &ip->address) == 1) {
75,752✔
314
            ip->family = AF_INET6;
4,482✔
315
        } else {
4,482✔
316
            return -1;
×
317
        }
×
318

319
        *cat = c;
80,234✔
320
        *value = v;
80,234✔
321
    }
80,234✔
322

323
    return 0;
80,234✔
324
}
82,653✔
325

326
#define SREP_SHORTNAME_LEN 32
72✔
327
static char srep_cat_table[SREP_MAX_CATS][SREP_SHORTNAME_LEN];
328

329
uint8_t SCSRepCatGetByShortname(const char *shortname)
330
{
57✔
331
    uint8_t cat;
57✔
332
    for (cat = 0; cat < SREP_MAX_CATS; cat++) {
225✔
333
        if (strcmp(srep_cat_table[cat], shortname) == 0)
225✔
334
            return cat;
57✔
335
    }
225✔
336

337
    return 0;
×
338
}
57✔
339

340
static int SRepLoadCatFile(const char *filename)
341
{
19✔
342
    int r = 0;
19✔
343
    FILE *fp = fopen(filename, "r");
19✔
344

345
    if (fp == NULL) {
19✔
346
        SCLogError("opening ip rep file %s: %s", filename, strerror(errno));
×
347
        return -1;
×
348
    }
×
349

350
    r = SRepLoadCatFileFromFD(fp);
19✔
351

352
    fclose(fp);
19✔
353
    fp = NULL;
19✔
354
    return r;
19✔
355
}
19✔
356

357
int SRepLoadCatFileFromFD(FILE *fp)
358
{
30✔
359
    char line[8192] = "";
30✔
360
    Address a;
30✔
361
    memset(&a, 0x00, sizeof(a));
30✔
362
    a.family = AF_INET;
30✔
363
    memset(&srep_cat_table, 0x00, sizeof(srep_cat_table));
30✔
364

365
    BUG_ON(SRepGetVersion() > 0);
30✔
366

367
    while(fgets(line, (int)sizeof(line), fp) != NULL) {
102✔
368
        size_t len = strlen(line);
72✔
369
        if (len == 0)
72✔
370
            continue;
×
371

372
        /* ignore comments and empty lines */
373
        if (line[0] == '\n' || line [0] == '\r' || line[0] == ' ' || line[0] == '#' || line[0] == '\t')
72✔
374
            continue;
×
375

376
        while (isspace((unsigned char)line[--len]));
72✔
377

378
        /* Check if we have a trailing newline, and remove it */
379
        len = strlen(line);
72✔
380
        if (len == 0)
72✔
381
            continue;
×
382

383
        if (line[len - 1] == '\n' || line[len - 1] == '\r') {
72✔
384
            line[len - 1] = '\0';
64✔
385
        }
64✔
386

387
        uint8_t cat = 0;
72✔
388
        char shortname[SREP_SHORTNAME_LEN];
72✔
389
        if (SRepCatSplitLine(line, &cat, shortname, sizeof(shortname)) == 0) {
72✔
390
            strlcpy(srep_cat_table[cat], shortname, SREP_SHORTNAME_LEN);
72✔
391
        } else {
72✔
392
            SCLogError("bad line \"%s\"", line);
×
393
        }
×
394
    }
72✔
395

396
    SCLogDebug("IP Rep categories:");
30✔
397
    int i;
30✔
398
    for (i = 0; i < SREP_MAX_CATS; i++) {
1,830✔
399
        if (strlen(srep_cat_table[i]) == 0)
1,800✔
400
            continue;
1,728✔
401
        SCLogDebug("CAT %d, name %s", i, srep_cat_table[i]);
72✔
402
    }
72✔
403
    return 0;
30✔
404
}
30✔
405

406
static int SRepLoadFile(SRepCIDRTree *cidr_ctx, char *filename)
407
{
19✔
408
    int r = 0;
19✔
409
    FILE *fp = fopen(filename, "r");
19✔
410

411
    if (fp == NULL) {
19✔
412
        SCLogError("opening ip rep file %s: %s", filename, strerror(errno));
×
413
        return -1;
×
414
    }
×
415

416
    r = SRepLoadFileFromFD(cidr_ctx, fp);
19✔
417

418
    fclose(fp);
19✔
419
    fp = NULL;
19✔
420
    return r;
19✔
421
}
19✔
422

423
int SRepLoadFileFromFD(SRepCIDRTree *cidr_ctx, FILE *fp)
424
{
30✔
425
    char line[8192] = "";
30✔
426

427
    while(fgets(line, (int)sizeof(line), fp) != NULL) {
82,678✔
428
        size_t len = strlen(line);
82,648✔
429
        if (len == 0)
82,648✔
430
            continue;
×
431

432
        /* ignore comments and empty lines */
433
        if (line[0] == '\n' || line [0] == '\r' || line[0] == ' ' || line[0] == '#' || line[0] == '\t')
82,648✔
434
            continue;
4✔
435

436
        while (isspace((unsigned char)line[--len]));
82,647✔
437

438
        /* Check if we have a trailing newline, and remove it */
439
        len = strlen(line);
82,644✔
440
        if (len == 0)
82,644✔
441
            continue;
×
442

443
        if (line[len - 1] == '\n' || line[len - 1] == '\r') {
82,644✔
444
            line[len - 1] = '\0';
82,633✔
445
        }
82,633✔
446

447
        Address a;
82,644✔
448
        memset(&a, 0x00, sizeof(a));
82,644✔
449
        a.family = AF_INET;
82,644✔
450

451
        uint8_t cat = 0, value = 0;
82,644✔
452
        int r = SRepSplitLine(cidr_ctx, line, &a, &cat, &value);
82,644✔
453
        if (r < 0) {
82,644✔
454
            SCLogError("bad line \"%s\"", line);
×
455
        } else if (r == 0) {
82,644✔
456
            if (a.family == AF_INET) {
80,233✔
457
                char ipstr[16];
75,751✔
458
                PrintInet(AF_INET, (const void *)&a.address, ipstr, sizeof(ipstr));
75,751✔
459
                SCLogDebug("%s %u %u", ipstr, cat, value);
75,751✔
460
            } else {
75,751✔
461
                char ipstr[128];
4,482✔
462
                PrintInet(AF_INET6, (const void *)&a.address, ipstr, sizeof(ipstr));
4,482✔
463
                SCLogDebug("%s %u %u", ipstr, cat, value);
4,482✔
464
            }
4,482✔
465

466
            Host *h = HostGetHostFromHash(&a);
80,233✔
467
            if (h == NULL) {
80,233✔
468
                SCLogError("failed to get a host, increase host.memcap");
×
469
                break;
×
470
            } else {
80,233✔
471
                //SCLogInfo("host %p", h);
472

473
                if (h->iprep == NULL) {
80,233✔
474
                    h->iprep = SCCalloc(1, sizeof(SReputation));
75,106✔
475
                    if (h->iprep != NULL) {
75,106✔
476
                        HostIncrUsecnt(h);
75,106✔
477
                    }
75,106✔
478
                }
75,106✔
479
                if (h->iprep != NULL) {
80,233✔
480
                    SReputation *rep = h->iprep;
80,233✔
481

482
                    /* if version is outdated, it's an older entry that we'll
483
                     * now replace. */
484
                    if (rep->version != SRepGetVersion()) {
80,233✔
485
                        memset(rep, 0x00, sizeof(SReputation));
75,106✔
486
                    }
75,106✔
487

488
                    rep->version = SRepGetVersion();
80,233✔
489
                    rep->rep[cat] = value;
80,233✔
490

491
                    SCLogDebug("host %p iprep %p setting cat %u to value %u",
80,233✔
492
                        h, h->iprep, cat, value);
80,233✔
493
#ifdef DEBUG
494
                    if (SCLogDebugEnabled()) {
495
                        int i;
496
                        for (i = 0; i < SREP_MAX_CATS; i++) {
497
                            if (rep->rep[i] == 0)
498
                                continue;
499

500
                            SCLogDebug("--> host %p iprep %p cat %d to value %u",
501
                                    h, h->iprep, i, rep->rep[i]);
502
                        }
503
                    }
504
#endif
505
                }
80,233✔
506

507
                HostRelease(h);
80,233✔
508
            }
80,233✔
509
        }
80,233✔
510
    }
82,644✔
511

512
    return 0;
30✔
513
}
30✔
514

515
/**
516
 *  \brief Create the path if default-rule-path was specified
517
 *  \param sig_file The name of the file
518
 *  \retval str Pointer to the string path + sig_file
519
 */
520
static char *SRepCompleteFilePath(char *file)
521
{
19✔
522
    const char *defaultpath = NULL;
19✔
523
    char *path = NULL;
19✔
524

525
    /* Path not specified */
526
    if (PathIsRelative(file)) {
19✔
527
        if (SCConfGet("default-reputation-path", &defaultpath) == 1) {
12✔
528
            SCLogDebug("Default path: %s", defaultpath);
11✔
529
            size_t path_len = sizeof(char) * (strlen(defaultpath) +
11✔
530
                          strlen(file) + 2);
11✔
531
            path = SCMalloc(path_len);
11✔
532
            if (unlikely(path == NULL))
11✔
533
                return NULL;
×
534
            strlcpy(path, defaultpath, path_len);
11✔
535
#if defined OS_WIN32 || defined __CYGWIN__
536
            if (path[strlen(path) - 1] != '\\')
537
                strlcat(path, "\\\\", path_len);
538
#else
539
            if (path[strlen(path) - 1] != '/')
11✔
540
                strlcat(path, "/", path_len);
11✔
541
#endif
11✔
542
            strlcat(path, file, path_len);
11✔
543
        } else {
11✔
544
            path = SCStrdup(file);
1✔
545
            if (unlikely(path == NULL))
1✔
546
                return NULL;
×
547
        }
1✔
548
    } else {
12✔
549
        path = SCStrdup(file);
7✔
550
        if (unlikely(path == NULL))
7✔
551
            return NULL;
×
552
    }
7✔
553
    return path;
19✔
554
}
19✔
555

556
/** \brief init reputation
557
 *
558
 *  \param de_ctx detection engine ctx for tracking iprep version
559
 *
560
 *  \retval 0 ok
561
 *  \retval -1 error
562
 *
563
 *  If this function is called more than once, the category file
564
 *  is not reloaded.
565
 */
566
int SRepInit(DetectEngineCtx *de_ctx)
567
{
3,310✔
568
    SCConfNode *files;
3,310✔
569
    SCConfNode *file = NULL;
3,310✔
570
    const char *filename = NULL;
3,310✔
571
    int init = 0;
3,310✔
572

573
    de_ctx->srepCIDR_ctx = (SRepCIDRTree *)SCCalloc(1, sizeof(SRepCIDRTree));
3,310✔
574
    if (de_ctx->srepCIDR_ctx == NULL)
3,310✔
575
        exit(EXIT_FAILURE);
×
576

577
    for (int i = 0; i < SREP_MAX_CATS; i++) {
201,910✔
578
        de_ctx->srepCIDR_ctx->srep_ipv4_tree[i] = SCRadix4TreeInitialize();
198,600✔
579
        de_ctx->srepCIDR_ctx->srep_ipv6_tree[i] = SCRadix6TreeInitialize();
198,600✔
580
    }
198,600✔
581

582
    SRepCIDRTree *cidr_ctx = de_ctx->srepCIDR_ctx;
3,310✔
583

584
    if (SRepGetVersion() == 0) {
3,310✔
585
        SC_ATOMIC_INIT(srep_eversion);
3,310✔
586
        init = 1;
3,310✔
587
    }
3,310✔
588

589
    /* if both settings are missing, we assume the user doesn't want ip rep */
590
    (void)SCConfGet("reputation-categories-file", &filename);
3,310✔
591
    files = SCConfGetNode("reputation-files");
3,310✔
592
    if (filename == NULL && files == NULL) {
3,310✔
593
        SCLogConfig("IP reputation disabled");
3,291✔
594
        return 0;
3,291✔
595
    }
3,291✔
596

597
    if (files == NULL) {
19✔
598
        SCLogError("\"reputation-files\" not set");
×
599
        return -1;
×
600
    }
×
601

602
    if (init) {
19✔
603
        if (filename == NULL) {
19✔
604
            SCLogError("\"reputation-categories-file\" not set");
×
605
            return -1;
×
606
        }
×
607

608
        /* init even if we have reputation files, so that when we
609
         * have a live reload, we have inited the cats */
610
        if (SRepLoadCatFile(filename) < 0) {
19✔
611
            SCLogError("failed to load reputation "
×
612
                       "categories file %s",
×
613
                    filename);
×
614
            return -1;
×
615
        }
×
616
    }
19✔
617

618
    de_ctx->srep_version = SRepIncrVersion();
19✔
619
    SCLogDebug("Reputation version %u", de_ctx->srep_version);
19✔
620

621
    /* ok, let's load reputation files from the general config */
622
    if (files != NULL) {
19✔
623
        TAILQ_FOREACH(file, &files->head, next) {
19✔
624
            char *sfile = SRepCompleteFilePath(file->val);
19✔
625
            if (sfile) {
19✔
626
                SCLogInfo("Loading reputation file: %s", sfile);
19✔
627

628
                int r = SRepLoadFile(cidr_ctx, sfile);
19✔
629
                if (r < 0){
19✔
630
                    if (de_ctx->failure_fatal) {
×
631
                        exit(EXIT_FAILURE);
×
632
                    }
×
633
                }
×
634
                SCFree(sfile);
19✔
635
            }
19✔
636
        }
19✔
637
    }
19✔
638

639
    /* Set effective rep version.
640
     * On live reload we will handle this after de_ctx has been swapped */
641
    if (init) {
19✔
642
        SRepInitComplete();
19✔
643
    }
19✔
644

645
    HostPrintStats();
19✔
646
    return 0;
19✔
647
}
19✔
648

649
void SRepDestroy(DetectEngineCtx *de_ctx)
650
{
3,258✔
651
    if (de_ctx->srepCIDR_ctx != NULL) {
3,258✔
652
        for (int i = 0; i < SREP_MAX_CATS; i++) {
198,616✔
653
            SCRadix4TreeRelease(&de_ctx->srepCIDR_ctx->srep_ipv4_tree[i], &iprep_radix4_config);
195,360✔
654
            SCRadix6TreeRelease(&de_ctx->srepCIDR_ctx->srep_ipv6_tree[i], &iprep_radix6_config);
195,360✔
655
        }
195,360✔
656
        SCFree(de_ctx->srepCIDR_ctx);
3,256✔
657
        de_ctx->srepCIDR_ctx = NULL;
658
    }
3,256✔
659
}
3,258✔
660

661
#ifdef UNITTESTS
662
#include "tests/reputation.c"
663
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc