iprep: extends cidr support

Implements new API to expand the IP reputation
to netblocks with CIDR notation

A new object 'srepCIDRTree' is kept in the DetectionEngineCtx,
which contains two tree (one for ipv4 and one for ipv6)
where the reputation values are stored.
pull/1184/head
Giuseppe Longo 12 years ago committed by Victor Julien
parent 667b9a5220
commit a1d8439b25

@ -39,6 +39,7 @@
#include "util-error.h"
#include "util-radix-tree.h"
#include "util-file.h"
#include "reputation.h"
#include "detect-mark.h"
@ -586,6 +587,9 @@ typedef struct DetectEngineCtx_ {
/* version of the srep data */
uint32_t srep_version;
/* reputation for netblocks */
SRepCIDRTree *srepCIDR_ctx;
Signature **sig_array;
uint32_t sig_array_size; /* size in bytes */
uint32_t sig_array_len; /* size in array members */

@ -57,11 +57,116 @@ static uint32_t SRepGetVersion(void)
return srep_version;
}
void SRepResetVersion(void)
{
srep_version = 0;
}
static uint32_t SRepGetEffectiveVersion(void)
{
return SC_ATOMIC_GET(srep_eversion);
}
static void SRepCIDRFreeUserData(void *data)
{
if (data != NULL)
SCFree(data);
return;
}
static void SRepCIDRAddNetblock(SRepCIDRTree *cidr_ctx, char *ip, int cat, int value)
{
SReputation *user_data = NULL;
if ((user_data = SCMalloc(sizeof(SReputation))) == NULL) {
SCLogError(SC_ERR_FATAL, "Error allocating memory. Exiting");
exit(EXIT_FAILURE);
}
memset(user_data, 0x00, sizeof(SReputation));
user_data->version = SRepGetVersion();
user_data->rep[cat] = value;
if (strchr(ip, ':') != NULL) {
if (cidr_ctx->srepIPV6_tree[cat] == NULL) {
cidr_ctx->srepIPV6_tree[cat] = SCRadixCreateRadixTree(SRepCIDRFreeUserData, NULL);
if (cidr_ctx->srepIPV6_tree[cat] == NULL) {
SCLogDebug("Error initializing Reputation IPV6 with CIDR module for cat %d", cat);
exit(EXIT_FAILURE);
}
SCLogDebug("Reputation IPV6 with CIDR module for cat %d initialized", cat);
}
SCLogDebug("adding ipv6 host %s", ip);
if (SCRadixAddKeyIPV6String(ip, cidr_ctx->srepIPV6_tree[cat], (void *)user_data) == NULL) {
SCLogWarning(SC_ERR_INVALID_VALUE,
"failed to add ipv6 host %s", ip);
}
} else {
if (cidr_ctx->srepIPV4_tree[cat] == NULL) {
cidr_ctx->srepIPV4_tree[cat] = SCRadixCreateRadixTree(SRepCIDRFreeUserData, NULL);
if (cidr_ctx->srepIPV4_tree[cat] == NULL) {
SCLogDebug("Error initializing Reputation IPV4 with CIDR module for cat %d", cat);
exit(EXIT_FAILURE);
}
SCLogDebug("Reputation IPV4 with CIDR module for cat %d initialized", cat);
}
SCLogDebug("adding ipv4 host %s", ip);
if (SCRadixAddKeyIPV4String(ip, cidr_ctx->srepIPV4_tree[cat], (void *)user_data) == NULL) {
SCLogWarning(SC_ERR_INVALID_VALUE,
"failed to add ipv4 host %s", ip);
}
}
}
static uint8_t SRepCIDRGetIPv4IPRep(SRepCIDRTree *cidr_ctx, uint8_t *ipv4_addr, uint8_t cat)
{
void *user_data = NULL;
(void)SCRadixFindKeyIPV4BestMatch(ipv4_addr, cidr_ctx->srepIPV4_tree[cat], &user_data);
if (user_data == NULL)
return 0;
SReputation *r = (SReputation *)user_data;
return r->rep[cat];
}
static uint8_t SRepCIDRGetIPv6IPRep(SRepCIDRTree *cidr_ctx, uint8_t *ipv6_addr, uint8_t cat)
{
void *user_data = NULL;
(void)SCRadixFindKeyIPV6BestMatch(ipv6_addr, cidr_ctx->srepIPV6_tree[cat], &user_data);
if (user_data == NULL)
return 0;
SReputation *r = (SReputation *)user_data;
return r->rep[cat];
}
uint8_t SRepCIDRGetIPRepSrc(SRepCIDRTree *cidr_ctx, Packet *p, uint8_t cat, uint32_t version)
{
uint8_t rep = 0;
if (PKT_IS_IPV4(p))
rep = SRepCIDRGetIPv4IPRep(cidr_ctx, (uint8_t *)GET_IPV4_SRC_ADDR_PTR(p), cat);
else if (PKT_IS_IPV6(p))
rep = SRepCIDRGetIPv6IPRep(cidr_ctx, (uint8_t *)GET_IPV6_SRC_ADDR(p), cat);
return rep;
}
uint8_t SRepCIDRGetIPRepDst(SRepCIDRTree *cidr_ctx, Packet *p, uint8_t cat, uint32_t version)
{
uint8_t rep = 0;
if (PKT_IS_IPV4(p))
rep = SRepCIDRGetIPv4IPRep(cidr_ctx, (uint8_t *)GET_IPV4_DST_ADDR_PTR(p), cat);
else if (PKT_IS_IPV6(p))
rep = SRepCIDRGetIPv6IPRep(cidr_ctx, (uint8_t *)GET_IPV6_DST_ADDR(p), cat);
return rep;
}
/** \brief Increment effective reputation version after
* a rule/reputatio reload is complete. */
void SRepReloadComplete(void)
@ -162,7 +267,7 @@ static int SRepCatSplitLine(char *line, uint8_t *cat, char *shortname, size_t sh
* \retval 1 header
* \retval -1 boo
*/
static int SRepSplitLine(char *line, uint32_t *ip, uint8_t *cat, uint8_t *value)
static int SRepSplitLine(SRepCIDRTree *cidr_ctx, char *line, uint32_t *ip, uint8_t *cat, uint8_t *value)
{
size_t line_len = strlen(line);
char *ptrs[3] = {NULL,NULL,NULL};
@ -200,11 +305,6 @@ static int SRepSplitLine(char *line, uint32_t *ip, uint8_t *cat, uint8_t *value)
if (strcmp(ptrs[0], "ip") == 0)
return 1;
uint32_t addr;
if (inet_pton(AF_INET, ptrs[0], &addr) <= 0) {
return -1;
}
int c = atoi(ptrs[1]);
if (c < 0 || c >= SREP_MAX_CATS) {
return -1;
@ -215,9 +315,20 @@ static int SRepSplitLine(char *line, uint32_t *ip, uint8_t *cat, uint8_t *value)
return -1;
}
*ip = addr;
*cat = c;
*value = v;
if (strchr(ptrs[0], '/') != NULL) {
SRepCIDRAddNetblock(cidr_ctx, ptrs[0], c, v);
return 1;
} else {
uint32_t addr;
if (inet_pton(AF_INET, ptrs[0], &addr) <= 0) {
return -1;
}
*ip = addr;
*cat = c;
*value = v;
}
return 0;
}
@ -246,7 +357,24 @@ uint8_t SRepCatGetByShortname(char *shortname)
return 0;
}
int SRepLoadCatFile(char *filename)
static int SRepLoadCatFile(char *filename)
{
int r = 0;
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
SCLogError(SC_ERR_OPENING_RULE_FILE, "opening ip rep file %s: %s", filename, strerror(errno));
return -1;
}
r = SRepLoadCatFileFromFD(fp);
fclose(fp);
fp = NULL;
return r;
}
int SRepLoadCatFileFromFD(FILE *fp)
{
char line[8192] = "";
Address a;
@ -256,12 +384,6 @@ int SRepLoadCatFile(char *filename)
BUG_ON(SRepGetVersion() > 0);
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
SCLogError(SC_ERR_OPENING_RULE_FILE, "opening ip rep file %s: %s", filename, strerror(errno));
return -1;
}
while(fgets(line, (int)sizeof(line), fp) != NULL) {
size_t len = strlen(line);
if (len == 0)
@ -290,8 +412,6 @@ int SRepLoadCatFile(char *filename)
SCLogError(SC_ERR_NO_REPUTATION, "bad line \"%s\"", line);
}
}
fclose(fp);
fp = NULL;
SCLogDebug("IP Rep categories:");
int i;
@ -303,19 +423,31 @@ int SRepLoadCatFile(char *filename)
return 0;
}
static int SRepLoadFile(char *filename)
static int SRepLoadFile(SRepCIDRTree *cidr_ctx, char *filename)
{
char line[8192] = "";
Address a;
memset(&a, 0x00, sizeof(a));
a.family = AF_INET;
int r = 0;
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
SCLogError(SC_ERR_OPENING_RULE_FILE, "opening ip rep file \"%s\": %s", filename, strerror(errno));
SCLogError(SC_ERR_OPENING_RULE_FILE, "opening ip rep file %s: %s", filename, strerror(errno));
return -1;
}
r = SRepLoadFileFromFD(cidr_ctx, fp);
fclose(fp);
fp = NULL;
return r;
}
int SRepLoadFileFromFD(SRepCIDRTree *cidr_ctx, FILE *fp)
{
char line[8192] = "";
Address a;
memset(&a, 0x00, sizeof(a));
a.family = AF_INET;
while(fgets(line, (int)sizeof(line), fp) != NULL) {
size_t len = strlen(line);
if (len == 0)
@ -338,7 +470,7 @@ static int SRepLoadFile(char *filename)
uint32_t ip = 0;
uint8_t cat = 0, value = 0;
int r = SRepSplitLine(line, &ip, &cat, &value);
int r = SRepSplitLine(cidr_ctx, line, &ip, &cat, &value);
if (r < 0) {
SCLogError(SC_ERR_NO_REPUTATION, "bad line \"%s\"", line);
} else if (r == 0) {
@ -394,8 +526,6 @@ static int SRepLoadFile(char *filename)
}
}
}
fclose(fp);
fp = NULL;
return 0;
}
@ -459,6 +589,18 @@ int SRepInit(DetectEngineCtx *de_ctx)
char *sfile = NULL;
char *filename = NULL;
int init = 0;
int i = 0;
de_ctx->srepCIDR_ctx = (SRepCIDRTree *)SCMalloc(sizeof(SRepCIDRTree));
if (de_ctx->srepCIDR_ctx == NULL)
exit(EXIT_FAILURE);
memset(de_ctx->srepCIDR_ctx, 0, sizeof(SRepCIDRTree));
SRepCIDRTree *cidr_ctx = de_ctx->srepCIDR_ctx;
for (i = 0; i < SREP_MAX_CATS; i++) {
cidr_ctx->srepIPV4_tree[i] = NULL;
cidr_ctx->srepIPV6_tree[i] = NULL;
}
if (SRepGetVersion() == 0) {
SC_ATOMIC_INIT(srep_eversion);
@ -502,7 +644,7 @@ int SRepInit(DetectEngineCtx *de_ctx)
sfile = SRepCompleteFilePath(file->val);
SCLogInfo("Loading reputation file: %s", sfile);
r = SRepLoadFile(sfile);
r = SRepLoadFile(cidr_ctx, sfile);
if (r < 0){
if (de_ctx->failure_fatal == 1) {
exit(EXIT_FAILURE);

@ -26,17 +26,22 @@
#ifndef __REPUTATION_H__
#define __REPUTATION_H__
#include "detect.h"
#include "host.h"
#define SREP_MAX_CATS 60
typedef struct SRepCIDRTree_ {
SCRadixTree *srepIPV4_tree[SREP_MAX_CATS];
SCRadixTree *srepIPV6_tree[SREP_MAX_CATS];
} SRepCIDRTree;
typedef struct SReputation_ {
uint32_t version;
uint8_t rep[SREP_MAX_CATS];
} SReputation;
uint8_t SRepCatGetByShortname(char *shortname);
int SRepInit(DetectEngineCtx *de_ctx);
int SRepInit(struct DetectEngineCtx_ *de_ctx);
void SRepReloadComplete(void);
int SRepHostTimedOut(Host *);
@ -76,6 +81,12 @@ typedef struct IPReputationCtx_ {
SCMutex reputationIPV6_lock;
}IPReputationCtx;
uint8_t SRepCIDRGetIPRepSrc(SRepCIDRTree *cidr_ctx, Packet *p, uint8_t cat, uint32_t version);
uint8_t SRepCIDRGetIPRepDst(SRepCIDRTree *cidr_ctx, Packet *p, uint8_t cat, uint32_t version);
void SRepResetVersion();
int SRepLoadCatFileFromFD(FILE *fp);
int SRepLoadFileFromFD(SRepCIDRTree *cidr_ctx, FILE *fp);
/** Reputation Data */
//TODO: Add a timestamp here to know the last update of this reputation.
typedef struct Reputation_ {

Loading…
Cancel
Save