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

OISF / suricata / 23374838686

21 Mar 2026 07:29AM UTC coverage: 59.341% (-20.0%) from 79.315%
23374838686

Pull #15075

github

web-flow
Merge 90b4e834f into 6587e363a
Pull Request #15075: Stack 8001 v16.4

38 of 70 new or added lines in 10 files covered. (54.29%)

34165 existing lines in 563 files now uncovered.

119621 of 201584 relevant lines covered (59.34%)

650666.92 hits per line

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

9.93
/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)
UNCOV
55
{
×
UNCOV
56
    return ++srep_version;
×
UNCOV
57
}
×
58

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

64
void SRepResetVersion(void)
UNCOV
65
{
×
UNCOV
66
    srep_version = 0;
×
UNCOV
67
}
×
68

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

74
static void SRepCIDRFreeUserData(void *data)
UNCOV
75
{
×
UNCOV
76
    if (data != NULL)
×
UNCOV
77
        SCFree(data);
×
UNCOV
78
}
×
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)
UNCOV
84
{
×
UNCOV
85
    SReputation *user_data = NULL;
×
UNCOV
86
    if ((user_data = SCCalloc(1, sizeof(SReputation))) == NULL) {
×
87
        FatalError("Error allocating memory. Exiting");
×
88
    }
×
89

UNCOV
90
    user_data->version = SRepGetVersion();
×
UNCOV
91
    user_data->rep[cat] = value;
×
92

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

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

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

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

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

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

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

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

UNCOV
144
    return rep;
×
UNCOV
145
}
×
146

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

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

UNCOV
156
    return rep;
×
UNCOV
157
}
×
158

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

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

175
/** \brief Set effective reputation version after
176
 *         reputation initialization is complete. */
177
static void SRepInitComplete(void)
UNCOV
178
{
×
UNCOV
179
    (void) SC_ATOMIC_SET(srep_eversion, 1);
×
UNCOV
180
    SCLogDebug("effective Reputation version %u", SRepGetEffectiveVersion());
×
UNCOV
181
}
×
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)
UNCOV
213
{
×
UNCOV
214
    size_t line_len = strlen(line);
×
UNCOV
215
    char *ptrs[2] = {NULL,NULL};
×
UNCOV
216
    int i = 0;
×
UNCOV
217
    int idx = 0;
×
UNCOV
218
    char *origline = line;
×
219

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

UNCOV
224
            ptrs[idx] = line;
×
UNCOV
225
            idx++;
×
226

UNCOV
227
            line += (i+1);
×
UNCOV
228
            i = 0;
×
229

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

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

UNCOV
245
    SCLogDebug("%s, %s", ptrs[0], ptrs[1]);
×
246

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

UNCOV
251
    *cat = (uint8_t)c;
×
UNCOV
252
    strlcpy(shortname, ptrs[1], shortname_len);
×
UNCOV
253
    return 0;
×
UNCOV
254
}
×
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)
UNCOV
262
{
×
UNCOV
263
    size_t line_len = strlen(line);
×
UNCOV
264
    char *ptrs[3] = {NULL,NULL,NULL};
×
UNCOV
265
    int i = 0;
×
UNCOV
266
    int idx = 0;
×
UNCOV
267
    char *origline = line;
×
268

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

UNCOV
274
            ptrs[idx] = line;
×
UNCOV
275
            idx++;
×
276

UNCOV
277
            line += (i+1);
×
UNCOV
278
            i = 0;
×
279

UNCOV
280
            if (line >= origline + line_len)
×
UNCOV
281
                break;
×
UNCOV
282
            if (strlen(line) == 0)
×
283
                break;
×
UNCOV
284
            if (idx == 3)
×
UNCOV
285
                break;
×
UNCOV
286
        } else {
×
UNCOV
287
            i++;
×
UNCOV
288
        }
×
UNCOV
289
    }
×
290

UNCOV
291
    if (idx != 3) {
×
UNCOV
292
        return -1;
×
UNCOV
293
    }
×
294

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

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

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

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

UNCOV
307
    if (strchr(ptrs[0], '/') != NULL) {
×
UNCOV
308
        SRepCIDRAddNetblock(cidr_ctx, ptrs[0], c, v);
×
UNCOV
309
        return 1;
×
UNCOV
310
    } else {
×
UNCOV
311
        if (inet_pton(AF_INET, ptrs[0], &ip->address) == 1) {
×
UNCOV
312
            ip->family = AF_INET;
×
UNCOV
313
        } else if (inet_pton(AF_INET6, ptrs[0], &ip->address) == 1) {
×
UNCOV
314
            ip->family = AF_INET6;
×
UNCOV
315
        } else {
×
316
            return -1;
×
317
        }
×
318

UNCOV
319
        *cat = c;
×
UNCOV
320
        *value = v;
×
UNCOV
321
    }
×
322

UNCOV
323
    return 0;
×
UNCOV
324
}
×
325

UNCOV
326
#define SREP_SHORTNAME_LEN 32
×
327
static char srep_cat_table[SREP_MAX_CATS][SREP_SHORTNAME_LEN];
328

329
uint8_t SCSRepCatGetByShortname(const char *shortname)
330
{
1,601✔
331
    uint8_t cat;
1,601✔
332
    for (cat = 0; cat < SREP_MAX_CATS; cat++) {
97,661✔
333
        if (strcmp(srep_cat_table[cat], shortname) == 0)
96,060✔
UNCOV
334
            return cat;
×
335
    }
96,060✔
336

337
    return 0;
1,601✔
338
}
1,601✔
339

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

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

UNCOV
350
    r = SRepLoadCatFileFromFD(fp);
×
351

UNCOV
352
    fclose(fp);
×
UNCOV
353
    fp = NULL;
×
UNCOV
354
    return r;
×
UNCOV
355
}
×
356

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

UNCOV
365
    BUG_ON(SRepGetVersion() > 0);
×
366

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

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

UNCOV
376
        while (isspace((unsigned char)line[--len]));
×
377

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

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

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

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

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

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

UNCOV
416
    r = SRepLoadFileFromFD(cidr_ctx, fp);
×
417

UNCOV
418
    fclose(fp);
×
UNCOV
419
    fp = NULL;
×
UNCOV
420
    return r;
×
UNCOV
421
}
×
422

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

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

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

UNCOV
436
        while (isspace((unsigned char)line[--len]));
×
437

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

UNCOV
443
        if (line[len - 1] == '\n' || line[len - 1] == '\r') {
×
UNCOV
444
            line[len - 1] = '\0';
×
UNCOV
445
        }
×
446

UNCOV
447
        Address a;
×
UNCOV
448
        memset(&a, 0x00, sizeof(a));
×
UNCOV
449
        a.family = AF_INET;
×
450

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

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

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

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

UNCOV
488
                    rep->version = SRepGetVersion();
×
UNCOV
489
                    rep->rep[cat] = value;
×
490

UNCOV
491
                    SCLogDebug("host %p iprep %p setting cat %u to value %u",
×
UNCOV
492
                        h, h->iprep, cat, value);
×
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
UNCOV
505
                }
×
506

UNCOV
507
                HostRelease(h);
×
UNCOV
508
            }
×
UNCOV
509
        }
×
UNCOV
510
    }
×
511

UNCOV
512
    return 0;
×
UNCOV
513
}
×
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)
UNCOV
521
{
×
UNCOV
522
    const char *defaultpath = NULL;
×
UNCOV
523
    char *path = NULL;
×
524

525
    /* Path not specified */
UNCOV
526
    if (PathIsRelative(file)) {
×
UNCOV
527
        if (SCConfGet("default-reputation-path", &defaultpath) == 1) {
×
UNCOV
528
            SCLogDebug("Default path: %s", defaultpath);
×
UNCOV
529
            size_t path_len = sizeof(char) * (strlen(defaultpath) +
×
UNCOV
530
                          strlen(file) + 2);
×
UNCOV
531
            path = SCMalloc(path_len);
×
UNCOV
532
            if (unlikely(path == NULL))
×
533
                return NULL;
×
UNCOV
534
            strlcpy(path, defaultpath, path_len);
×
535
#if defined OS_WIN32 || defined __CYGWIN__
536
            if (path[strlen(path) - 1] != '\\')
537
                strlcat(path, "\\\\", path_len);
538
#else
UNCOV
539
            if (path[strlen(path) - 1] != '/')
×
UNCOV
540
                strlcat(path, "/", path_len);
×
UNCOV
541
#endif
×
UNCOV
542
            strlcat(path, file, path_len);
×
UNCOV
543
        } else {
×
UNCOV
544
            path = SCStrdup(file);
×
UNCOV
545
            if (unlikely(path == NULL))
×
546
                return NULL;
×
UNCOV
547
        }
×
UNCOV
548
    } else {
×
UNCOV
549
        path = SCStrdup(file);
×
UNCOV
550
        if (unlikely(path == NULL))
×
551
            return NULL;
×
UNCOV
552
    }
×
UNCOV
553
    return path;
×
UNCOV
554
}
×
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
{
35,469✔
568
    SCConfNode *files;
35,469✔
569
    SCConfNode *file = NULL;
35,469✔
570
    const char *filename = NULL;
35,469✔
571
    int init = 0;
35,469✔
572

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

577
    for (int i = 0; i < SREP_MAX_CATS; i++) {
2,163,609✔
578
        de_ctx->srepCIDR_ctx->srep_ipv4_tree[i] = SCRadix4TreeInitialize();
2,128,140✔
579
        de_ctx->srepCIDR_ctx->srep_ipv6_tree[i] = SCRadix6TreeInitialize();
2,128,140✔
580
    }
2,128,140✔
581

582
    SRepCIDRTree *cidr_ctx = de_ctx->srepCIDR_ctx;
35,469✔
583

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

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

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

UNCOV
602
    if (init) {
×
UNCOV
603
        if (filename == NULL) {
×
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 */
UNCOV
610
        if (SRepLoadCatFile(filename) < 0) {
×
611
            SCLogError("failed to load reputation "
×
612
                       "categories file %s",
×
613
                    filename);
×
614
            return -1;
×
615
        }
×
UNCOV
616
    }
×
617

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

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

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

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

UNCOV
645
    HostPrintStats();
×
UNCOV
646
    return 0;
×
UNCOV
647
}
×
648

649
void SRepDestroy(DetectEngineCtx *de_ctx)
650
{
35,466✔
651
    if (de_ctx->srepCIDR_ctx != NULL) {
35,466✔
652
        for (int i = 0; i < SREP_MAX_CATS; i++) {
2,163,426✔
653
            SCRadix4TreeRelease(&de_ctx->srepCIDR_ctx->srep_ipv4_tree[i], &iprep_radix4_config);
2,127,960✔
654
            SCRadix6TreeRelease(&de_ctx->srepCIDR_ctx->srep_ipv6_tree[i], &iprep_radix6_config);
2,127,960✔
655
        }
2,127,960✔
656
        SCFree(de_ctx->srepCIDR_ctx);
35,466✔
657
        de_ctx->srepCIDR_ctx = NULL;
658
    }
35,466✔
659
}
35,466✔
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