suricata
reputation.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2018 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 "util-error.h"
30 #include "util-debug.h"
31 #include "util-ip.h"
32 #include "util-radix-tree.h"
33 #include "util-unittest.h"
34 #include "threads.h"
35 #include "util-print.h"
36 #include "host.h"
37 #include "conf.h"
38 #include "detect.h"
39 #include "reputation.h"
40 
41 /** effective reputation version, atomic as the host
42  * time out code will use it to check if a host's
43  * reputation info is outdated. */
44 SC_ATOMIC_DECLARE(uint32_t, srep_eversion);
45 /** reputation version set to the host's reputation,
46  * this will be set to 1 before rep files are loaded,
47  * so hosts will always have a minial value of 1 */
48 static uint32_t srep_version = 0;
49 
50 static uint32_t SRepIncrVersion(void)
51 {
52  return ++srep_version;
53 }
54 
55 static uint32_t SRepGetVersion(void)
56 {
57  return srep_version;
58 }
59 
60 void SRepResetVersion(void)
61 {
62  srep_version = 0;
63 }
64 
65 static uint32_t SRepGetEffectiveVersion(void)
66 {
67  return SC_ATOMIC_GET(srep_eversion);
68 }
69 
70 static void SRepCIDRFreeUserData(void *data)
71 {
72  if (data != NULL)
73  SCFree(data);
74 
75  return;
76 }
77 
78 static void SRepCIDRAddNetblock(SRepCIDRTree *cidr_ctx, char *ip, int cat, int value)
79 {
80  SReputation *user_data = NULL;
81  if ((user_data = SCMalloc(sizeof(SReputation))) == NULL) {
82  SCLogError(SC_ERR_FATAL, "Error allocating memory. Exiting");
83  exit(EXIT_FAILURE);
84  }
85  memset(user_data, 0x00, sizeof(SReputation));
86 
87  user_data->version = SRepGetVersion();
88  user_data->rep[cat] = value;
89 
90  if (strchr(ip, ':') != NULL) {
91  if (cidr_ctx->srepIPV6_tree[cat] == NULL) {
92  cidr_ctx->srepIPV6_tree[cat] = SCRadixCreateRadixTree(SRepCIDRFreeUserData, NULL);
93  if (cidr_ctx->srepIPV6_tree[cat] == NULL) {
94  SCLogDebug("Error initializing Reputation IPV6 with CIDR module for cat %d", cat);
95  exit(EXIT_FAILURE);
96  }
97  SCLogDebug("Reputation IPV6 with CIDR module for cat %d initialized", cat);
98  }
99 
100  SCLogDebug("adding ipv6 host %s", ip);
101  if (SCRadixAddKeyIPV6String(ip, cidr_ctx->srepIPV6_tree[cat], (void *)user_data) == NULL) {
103  "failed to add ipv6 host %s", ip);
104  }
105 
106  } else {
107  if (cidr_ctx->srepIPV4_tree[cat] == NULL) {
108  cidr_ctx->srepIPV4_tree[cat] = SCRadixCreateRadixTree(SRepCIDRFreeUserData, NULL);
109  if (cidr_ctx->srepIPV4_tree[cat] == NULL) {
110  SCLogDebug("Error initializing Reputation IPV4 with CIDR module for cat %d", cat);
111  exit(EXIT_FAILURE);
112  }
113  SCLogDebug("Reputation IPV4 with CIDR module for cat %d initialized", cat);
114  }
115 
116  SCLogDebug("adding ipv4 host %s", ip);
117  if (SCRadixAddKeyIPV4String(ip, cidr_ctx->srepIPV4_tree[cat], (void *)user_data) == NULL) {
119  "failed to add ipv4 host %s", ip);
120  }
121  }
122 }
123 
124 static uint8_t SRepCIDRGetIPv4IPRep(SRepCIDRTree *cidr_ctx, uint8_t *ipv4_addr, uint8_t cat)
125 {
126  void *user_data = NULL;
127  (void)SCRadixFindKeyIPV4BestMatch(ipv4_addr, cidr_ctx->srepIPV4_tree[cat], &user_data);
128  if (user_data == NULL)
129  return 0;
130 
131  SReputation *r = (SReputation *)user_data;
132  return r->rep[cat];
133 }
134 
135 static uint8_t SRepCIDRGetIPv6IPRep(SRepCIDRTree *cidr_ctx, uint8_t *ipv6_addr, uint8_t cat)
136 {
137  void *user_data = NULL;
138  (void)SCRadixFindKeyIPV6BestMatch(ipv6_addr, cidr_ctx->srepIPV6_tree[cat], &user_data);
139  if (user_data == NULL)
140  return 0;
141 
142  SReputation *r = (SReputation *)user_data;
143  return r->rep[cat];
144 }
145 
146 uint8_t SRepCIDRGetIPRepSrc(SRepCIDRTree *cidr_ctx, Packet *p, uint8_t cat, uint32_t version)
147 {
148  uint8_t rep = 0;
149 
150  if (PKT_IS_IPV4(p))
151  rep = SRepCIDRGetIPv4IPRep(cidr_ctx, (uint8_t *)GET_IPV4_SRC_ADDR_PTR(p), cat);
152  else if (PKT_IS_IPV6(p))
153  rep = SRepCIDRGetIPv6IPRep(cidr_ctx, (uint8_t *)GET_IPV6_SRC_ADDR(p), cat);
154 
155  return rep;
156 }
157 
158 uint8_t SRepCIDRGetIPRepDst(SRepCIDRTree *cidr_ctx, Packet *p, uint8_t cat, uint32_t version)
159 {
160  uint8_t rep = 0;
161 
162  if (PKT_IS_IPV4(p))
163  rep = SRepCIDRGetIPv4IPRep(cidr_ctx, (uint8_t *)GET_IPV4_DST_ADDR_PTR(p), cat);
164  else if (PKT_IS_IPV6(p))
165  rep = SRepCIDRGetIPv6IPRep(cidr_ctx, (uint8_t *)GET_IPV6_DST_ADDR(p), cat);
166 
167  return rep;
168 }
169 
170 /** \brief Increment effective reputation version after
171  * a rule/reputatio reload is complete. */
173 {
174  (void) SC_ATOMIC_ADD(srep_eversion, 1);
175  SCLogDebug("effective Reputation version %u", SRepGetEffectiveVersion());
176 }
177 
178 /** \brief Set effective reputation version after
179  * reputation initialization is complete. */
180 static void SRepInitComplete(void)
181 {
182  (void) SC_ATOMIC_SET(srep_eversion, 1);
183  SCLogDebug("effective Reputation version %u", SRepGetEffectiveVersion());
184 }
185 
186 /** \brief Check if a Host is timed out wrt ip rep, meaning a new
187  * version is in place.
188  *
189  * We clean up the old version here.
190  *
191  * \param h host
192  *
193  * \retval 0 not timed out
194  * \retval 1 timed out
195  */
197 {
198  BUG_ON(h == NULL);
199 
200  if (h->iprep == NULL)
201  return 1;
202 
203  uint32_t eversion = SRepGetEffectiveVersion();
204  SReputation *r = h->iprep;
205  if (r->version < eversion) {
206  SCLogDebug("host %p has reputation version %u, "
207  "effective version is %u", h, r->version, eversion);
208 
209  SCFree(h->iprep);
210  h->iprep = NULL;
211 
212  HostDecrUsecnt(h);
213  return 1;
214  }
215 
216  return 0;
217 }
218 
219 static int SRepCatSplitLine(char *line, uint8_t *cat, char *shortname, size_t shortname_len)
220 {
221  size_t line_len = strlen(line);
222  char *ptrs[2] = {NULL,NULL};
223  int i = 0;
224  int idx = 0;
225  char *origline = line;
226 
227  while (i < (int)line_len) {
228  if (line[i] == ',' || line[i] == '\n' || line[i] == '\0' || i == (int)(line_len - 1)) {
229  line[i] = '\0';
230 
231  ptrs[idx] = line;
232  idx++;
233 
234  line += (i+1);
235  i = 0;
236 
237  if (line >= origline + line_len)
238  break;
239  if (strlen(line) == 0)
240  break;
241  if (idx == 2)
242  break;
243  } else {
244  i++;
245  }
246  }
247 
248  if (idx != 2) {
249  return -1;
250  }
251 
252  SCLogDebug("%s, %s", ptrs[0], ptrs[1]);
253 
254  int c = atoi(ptrs[0]);
255  if (c < 0 || c >= SREP_MAX_CATS) {
256  return -1;
257  }
258 
259  *cat = (uint8_t)c;
260  strlcpy(shortname, ptrs[1], shortname_len);
261  return 0;
262 
263 }
264 
265 /**
266  * \retval 0 valid
267  * \retval 1 header
268  * \retval -1 bad line
269  */
270 static int SRepSplitLine(SRepCIDRTree *cidr_ctx, char *line, Address *ip, uint8_t *cat, uint8_t *value)
271 {
272  size_t line_len = strlen(line);
273  char *ptrs[3] = {NULL,NULL,NULL};
274  int i = 0;
275  int idx = 0;
276  char *origline = line;
277 
278  while (i < (int)line_len) {
279  if (line[i] == ',' || line[i] == '\n' || line[i] == '\0' || i == (int)(line_len - 1)) {
280  line[i] = '\0';
281 
282  ptrs[idx] = line;
283  idx++;
284 
285  line += (i+1);
286  i = 0;
287 
288  if (line >= origline + line_len)
289  break;
290  if (strlen(line) == 0)
291  break;
292  if (idx == 3)
293  break;
294  } else {
295  i++;
296  }
297  }
298 
299  if (idx != 3) {
300  return -1;
301  }
302 
303  //SCLogInfo("%s, %s, %s", ptrs[0], ptrs[1], ptrs[2]);
304 
305  if (strcmp(ptrs[0], "ip") == 0)
306  return 1;
307 
308  int c = atoi(ptrs[1]);
309  if (c < 0 || c >= SREP_MAX_CATS) {
310  return -1;
311  }
312 
313  int v = atoi(ptrs[2]);
314  if (v < 0 || v > 127) {
315  return -1;
316  }
317 
318  if (strchr(ptrs[0], '/') != NULL) {
319  SRepCIDRAddNetblock(cidr_ctx, ptrs[0], c, v);
320  return 1;
321  } else {
322  if (inet_pton(AF_INET, ptrs[0], &ip->address) == 1) {
323  ip->family = AF_INET;
324  } else if (inet_pton(AF_INET6, ptrs[0], &ip->address) == 1) {
325  ip->family = AF_INET6;
326  } else {
327  return -1;
328  }
329 
330  *cat = c;
331  *value = v;
332  }
333 
334  return 0;
335 }
336 
337 #define SREP_SHORTNAME_LEN 32
338 static char srep_cat_table[SREP_MAX_CATS][SREP_SHORTNAME_LEN];
339 
340 uint8_t SRepCatGetByShortname(char *shortname)
341 {
342  uint8_t cat;
343  for (cat = 0; cat < SREP_MAX_CATS; cat++) {
344  if (strcmp(srep_cat_table[cat], shortname) == 0)
345  return cat;
346  }
347 
348  return 0;
349 }
350 
351 static int SRepLoadCatFile(const char *filename)
352 {
353  int r = 0;
354  FILE *fp = fopen(filename, "r");
355 
356  if (fp == NULL) {
357  SCLogError(SC_ERR_OPENING_RULE_FILE, "opening ip rep file %s: %s", filename, strerror(errno));
358  return -1;
359  }
360 
361  r = SRepLoadCatFileFromFD(fp);
362 
363  fclose(fp);
364  fp = NULL;
365  return r;
366 }
367 
369 {
370  char line[8192] = "";
371  Address a;
372  memset(&a, 0x00, sizeof(a));
373  a.family = AF_INET;
374  memset(&srep_cat_table, 0x00, sizeof(srep_cat_table));
375 
376  BUG_ON(SRepGetVersion() > 0);
377 
378  while(fgets(line, (int)sizeof(line), fp) != NULL) {
379  size_t len = strlen(line);
380  if (len == 0)
381  continue;
382 
383  /* ignore comments and empty lines */
384  if (line[0] == '\n' || line [0] == '\r' || line[0] == ' ' || line[0] == '#' || line[0] == '\t')
385  continue;
386 
387  while (isspace((unsigned char)line[--len]));
388 
389  /* Check if we have a trailing newline, and remove it */
390  len = strlen(line);
391  if (len == 0)
392  continue;
393 
394  if (line[len - 1] == '\n' || line[len - 1] == '\r') {
395  line[len - 1] = '\0';
396  }
397 
398  uint8_t cat = 0;
399  char shortname[SREP_SHORTNAME_LEN];
400  if (SRepCatSplitLine(line, &cat, shortname, sizeof(shortname)) == 0) {
401  strlcpy(srep_cat_table[cat], shortname, SREP_SHORTNAME_LEN);
402  } else {
403  SCLogError(SC_ERR_NO_REPUTATION, "bad line \"%s\"", line);
404  }
405  }
406 
407  SCLogDebug("IP Rep categories:");
408  int i;
409  for (i = 0; i < SREP_MAX_CATS; i++) {
410  if (strlen(srep_cat_table[i]) == 0)
411  continue;
412  SCLogDebug("CAT %d, name %s", i, srep_cat_table[i]);
413  }
414  return 0;
415 }
416 
417 static int SRepLoadFile(SRepCIDRTree *cidr_ctx, char *filename)
418 {
419  int r = 0;
420  FILE *fp = fopen(filename, "r");
421 
422  if (fp == NULL) {
423  SCLogError(SC_ERR_OPENING_RULE_FILE, "opening ip rep file %s: %s", filename, strerror(errno));
424  return -1;
425  }
426 
427  r = SRepLoadFileFromFD(cidr_ctx, fp);
428 
429  fclose(fp);
430  fp = NULL;
431  return r;
432 
433 }
434 
435 int SRepLoadFileFromFD(SRepCIDRTree *cidr_ctx, FILE *fp)
436 {
437  char line[8192] = "";
438  Address a;
439  memset(&a, 0x00, sizeof(a));
440  a.family = AF_INET;
441 
442  while(fgets(line, (int)sizeof(line), fp) != NULL) {
443  size_t len = strlen(line);
444  if (len == 0)
445  continue;
446 
447  /* ignore comments and empty lines */
448  if (line[0] == '\n' || line [0] == '\r' || line[0] == ' ' || line[0] == '#' || line[0] == '\t')
449  continue;
450 
451  while (isspace((unsigned char)line[--len]));
452 
453  /* Check if we have a trailing newline, and remove it */
454  len = strlen(line);
455  if (len == 0)
456  continue;
457 
458  if (line[len - 1] == '\n' || line[len - 1] == '\r') {
459  line[len - 1] = '\0';
460  }
461 
462  uint8_t cat = 0, value = 0;
463  int r = SRepSplitLine(cidr_ctx, line, &a, &cat, &value);
464  if (r < 0) {
465  SCLogError(SC_ERR_NO_REPUTATION, "bad line \"%s\"", line);
466  } else if (r == 0) {
467  if (a.family == AF_INET) {
468  char ipstr[16];
469  PrintInet(AF_INET, (const void *)&a.address, ipstr, sizeof(ipstr));
470  SCLogDebug("%s %u %u", ipstr, cat, value);
471  } else {
472  char ipstr[128];
473  PrintInet(AF_INET6, (const void *)&a.address, ipstr, sizeof(ipstr));
474  SCLogDebug("%s %u %u", ipstr, cat, value);
475  }
476 
477  Host *h = HostGetHostFromHash(&a);
478  if (h == NULL) {
479  SCLogError(SC_ERR_NO_REPUTATION, "failed to get a host, increase host.memcap");
480  break;
481  } else {
482  //SCLogInfo("host %p", h);
483 
484  if (h->iprep == NULL) {
485  h->iprep = SCMalloc(sizeof(SReputation));
486  if (h->iprep != NULL) {
487  memset(h->iprep, 0x00, sizeof(SReputation));
488 
489  HostIncrUsecnt(h);
490  }
491  }
492  if (h->iprep != NULL) {
493  SReputation *rep = h->iprep;
494 
495  /* if version is outdated, it's an older entry that we'll
496  * now replace. */
497  if (rep->version != SRepGetVersion()) {
498  memset(rep, 0x00, sizeof(SReputation));
499  }
500 
501  rep->version = SRepGetVersion();
502  rep->rep[cat] = value;
503 
504  SCLogDebug("host %p iprep %p setting cat %u to value %u",
505  h, h->iprep, cat, value);
506 #ifdef DEBUG
507  if (SCLogDebugEnabled()) {
508  int i;
509  for (i = 0; i < SREP_MAX_CATS; i++) {
510  if (rep->rep[i] == 0)
511  continue;
512 
513  SCLogDebug("--> host %p iprep %p cat %d to value %u",
514  h, h->iprep, i, rep->rep[i]);
515  }
516  }
517 #endif
518  }
519 
520  HostRelease(h);
521  }
522  }
523  }
524 
525  return 0;
526 }
527 
528 /**
529  * \brief Create the path if default-rule-path was specified
530  * \param sig_file The name of the file
531  * \retval str Pointer to the string path + sig_file
532  */
533 static char *SRepCompleteFilePath(char *file)
534 {
535  const char *defaultpath = NULL;
536  char *path = NULL;
537 
538  /* Path not specified */
539  if (PathIsRelative(file)) {
540  if (ConfGet("default-reputation-path", &defaultpath) == 1) {
541  SCLogDebug("Default path: %s", defaultpath);
542  size_t path_len = sizeof(char) * (strlen(defaultpath) +
543  strlen(file) + 2);
544  path = SCMalloc(path_len);
545  if (unlikely(path == NULL))
546  return NULL;
547  strlcpy(path, defaultpath, path_len);
548 #if defined OS_WIN32 || defined __CYGWIN__
549  if (path[strlen(path) - 1] != '\\')
550  strlcat(path, "\\\\", path_len);
551 #else
552  if (path[strlen(path) - 1] != '/')
553  strlcat(path, "/", path_len);
554 #endif
555  strlcat(path, file, path_len);
556  } else {
557  path = SCStrdup(file);
558  if (unlikely(path == NULL))
559  return NULL;
560  }
561  } else {
562  path = SCStrdup(file);
563  if (unlikely(path == NULL))
564  return NULL;
565  }
566  return path;
567 }
568 
569 /** \brief init reputation
570  *
571  * \param de_ctx detection engine ctx for tracking iprep version
572  *
573  * \retval 0 ok
574  * \retval -1 error
575  *
576  * If this function is called more than once, the category file
577  * is not reloaded.
578  */
580 {
581  ConfNode *files;
582  ConfNode *file = NULL;
583  const char *filename = NULL;
584  int init = 0;
585  int i = 0;
586 
587  de_ctx->srepCIDR_ctx = (SRepCIDRTree *)SCMalloc(sizeof(SRepCIDRTree));
588  if (de_ctx->srepCIDR_ctx == NULL)
589  exit(EXIT_FAILURE);
590  memset(de_ctx->srepCIDR_ctx, 0, sizeof(SRepCIDRTree));
591  SRepCIDRTree *cidr_ctx = de_ctx->srepCIDR_ctx;
592 
593  for (i = 0; i < SREP_MAX_CATS; i++) {
594  cidr_ctx->srepIPV4_tree[i] = NULL;
595  cidr_ctx->srepIPV6_tree[i] = NULL;
596  }
597 
598  if (SRepGetVersion() == 0) {
599  SC_ATOMIC_INIT(srep_eversion);
600  init = 1;
601  }
602 
603  /* if both settings are missing, we assume the user doesn't want ip rep */
604  (void)ConfGet("reputation-categories-file", &filename);
605  files = ConfGetNode("reputation-files");
606  if (filename == NULL && files == NULL) {
607  SCLogConfig("IP reputation disabled");
608  return 0;
609  }
610 
611  if (files == NULL) {
612  SCLogError(SC_ERR_NO_REPUTATION, "\"reputation-files\" not set");
613  return -1;
614  }
615 
616  if (init) {
617  if (filename == NULL) {
618  SCLogError(SC_ERR_NO_REPUTATION, "\"reputation-categories-file\" not set");
619  return -1;
620  }
621 
622  /* init even if we have reputation files, so that when we
623  * have a live reload, we have inited the cats */
624  if (SRepLoadCatFile(filename) < 0) {
625  SCLogError(SC_ERR_NO_REPUTATION, "failed to load reputation "
626  "categories file %s", filename);
627  return -1;
628  }
629  }
630 
631  de_ctx->srep_version = SRepIncrVersion();
632  SCLogDebug("Reputation version %u", de_ctx->srep_version);
633 
634  /* ok, let's load reputation files from the general config */
635  if (files != NULL) {
636  TAILQ_FOREACH(file, &files->head, next) {
637  char *sfile = SRepCompleteFilePath(file->val);
638  if (sfile) {
639  SCLogInfo("Loading reputation file: %s", sfile);
640 
641  int r = SRepLoadFile(cidr_ctx, sfile);
642  if (r < 0){
643  if (de_ctx->failure_fatal == 1) {
644  exit(EXIT_FAILURE);
645  }
646  }
647  SCFree(sfile);
648  }
649  }
650  }
651 
652  /* Set effective rep version.
653  * On live reload we will handle this after de_ctx has been swapped */
654  if (init) {
655  SRepInitComplete();
656  }
657 
658  HostPrintStats();
659  return 0;
660 }
661 
663  if (de_ctx->srepCIDR_ctx != NULL) {
664  int i;
665  for (i = 0; i < SREP_MAX_CATS; i++) {
666  if (de_ctx->srepCIDR_ctx->srepIPV4_tree[i] != NULL) {
668  de_ctx->srepCIDR_ctx->srepIPV4_tree[i] = NULL;
669  }
670 
671  if (de_ctx->srepCIDR_ctx->srepIPV6_tree[i] != NULL) {
673  de_ctx->srepCIDR_ctx->srepIPV6_tree[i] = NULL;
674  }
675  }
676 
677  SCFree(de_ctx->srepCIDR_ctx);
678  de_ctx->srepCIDR_ctx = NULL;
679  }
680 }
681 
682 #ifdef UNITTESTS
683 #include "conf-yaml-loader.h"
684 #include "detect-engine.h"
685 #include "stream-tcp-private.h"
686 #include "stream-tcp-reassemble.h"
687 #include "stream-tcp.h"
688 #include "util-unittest-helper.h"
689 
690 static int SRepTest01(void)
691 {
692  char str[] = "1.2.3.4,1,2";
693  int result = 0;
695  if (de_ctx == NULL) {
696  return 0;
697  }
698 
699  SRepInit(de_ctx);
700  Address a;
701  uint8_t cat = 0, value = 0;
702  if (SRepSplitLine(de_ctx->srepCIDR_ctx, str, &a, &cat, &value) != 0) {
703  goto end;
704  }
705 
706  char ipstr[16];
707  PrintInet(AF_INET, (const void *)&a.address, ipstr, sizeof(ipstr));
708 
709  if (strcmp(ipstr, "1.2.3.4") != 0)
710  goto end;
711 
712  if (cat != 1)
713  goto end;
714 
715  if (value != 2)
716  goto end;
717 
718  result = 1;
719 
720 end:
721  DetectEngineCtxFree(de_ctx);
722  return result;
723 }
724 
725 static int SRepTest02(void)
726 {
727  char str[] = "1.1.1.1,";
728  int result = 0;
730  if (de_ctx == NULL) {
731  return 0;
732  }
733 
734  SRepInit(de_ctx);
735  Address a;
736  uint8_t cat = 0, value = 0;
737  if (SRepSplitLine(de_ctx->srepCIDR_ctx, str, &a, &cat, &value) == 0) {
738  goto end;
739  }
740  result = 1;
741 
742 end:
743  DetectEngineCtxFree(de_ctx);
744  return result;
745 }
746 
747 static int SRepTest03(void)
748 {
749  char str[] = "1,Shortname,Long Name";
750 
751  uint8_t cat = 0;
752  char shortname[SREP_SHORTNAME_LEN];
753 
754  if (SRepCatSplitLine(str, &cat, shortname, sizeof(shortname)) != 0) {
755  printf("split failed: ");
756  return 0;
757  }
758 
759  if (strcmp(shortname, "Shortname") != 0) {
760  printf("%s != Shortname: ", shortname);
761  return 0;
762  }
763 
764  if (cat != 1) {
765  printf("cat 1 != %u: ", cat);
766  return 0;
767  }
768 
769  return 1;
770 }
771 
772 static int SRepTest04(void)
773 {
774  int result = 0;
775 
776  DetectEngineCtx *de_ctx;
777  de_ctx = DetectEngineCtxInit();
778  if (de_ctx == NULL) {
779  goto end;
780  }
781  SRepInit(de_ctx);
782 
783  char str[] = "10.0.0.0/16,1,2";
784 
785  Address a;
786  uint8_t cat = 0, value = 0;
787  if (SRepSplitLine(de_ctx->srepCIDR_ctx, str, &a, &cat, &value) != 1) {
788  goto end;
789  }
790 
791  result = 1;
792 
793 end:
794  DetectEngineCtxFree(de_ctx);
795  return result;
796 }
797 
798 static int SRepTest05(void)
799 {
800  Packet *p = NULL;
801  int result = 0;
802  uint8_t *buf = (uint8_t *)"Hi all!";
803  uint16_t buflen = strlen((char *)buf);
804 
805  p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
806  if (p == NULL) {
807  return result;
808  }
809 
810  p->src.addr_data32[0] = UTHSetIPv4Address("10.0.0.1");
811 
812  DetectEngineCtx *de_ctx;
813  de_ctx = DetectEngineCtxInit();
814  if (de_ctx == NULL) {
815  return result;
816  }
817  SRepInit(de_ctx);
818 
819  char str[] = "10.0.0.0/16,1,20";
820 
821  Address a;
822  uint8_t cat = 0, value = 0;
823  if (SRepSplitLine(de_ctx->srepCIDR_ctx, str, &a, &cat, &value) != 1) {
824  goto end;
825  }
826  cat = 1;
827  value = SRepCIDRGetIPRepSrc(de_ctx->srepCIDR_ctx, p, cat, 0);
828  if (value != 20) {
829  goto end;
830  }
831  result = 1;
832 
833 end:
834  UTHFreePacket(p);
835  DetectEngineCtxFree(de_ctx);
836  return result;
837 }
838 
839 static int SRepTest06(void)
840 {
841  Packet *p = NULL;
842  int result = 0;
843  uint8_t *buf = (uint8_t *)"Hi all!";
844  uint16_t buflen = strlen((char *)buf);
845 
846  p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
847  if (p == NULL) {
848  return result;
849  }
850 
851  p->src.addr_data32[0] = UTHSetIPv4Address("192.168.0.1");
852 
853  DetectEngineCtx *de_ctx;
854  de_ctx = DetectEngineCtxInit();
855  if (de_ctx == NULL) {
856  return result;
857  }
858  SRepInit(de_ctx);
859 
860  char str[] =
861  "0.0.0.0/0,1,10\n"
862  "192.168.0.0/16,2,127";
863 
864  Address a;
865  uint8_t cat = 0, value = 0;
866  if (SRepSplitLine(de_ctx->srepCIDR_ctx, str, &a, &cat, &value) != 1) {
867  goto end;
868  }
869  cat = 1;
870  value = SRepCIDRGetIPRepSrc(de_ctx->srepCIDR_ctx, p, cat, 0);
871  if (value != 10) {
872  goto end;
873  }
874  result = 1;
875 
876 end:
877  UTHFreePacket(p);
878  DetectEngineCtxFree(de_ctx);
879  return result;
880 }
881 
882 static int SRepTest07(void) {
883  char str[] = "2000:0000:0000:0000:0000:0000:0000:0001,";
884  int result = 0;
886  if (de_ctx == NULL) {
887  return 0;
888  }
889 
890  SRepInit(de_ctx);
891  Address a;
892  uint8_t cat = 0, value = 0;
893  if (SRepSplitLine(de_ctx->srepCIDR_ctx, str, &a, &cat, &value) == 0) {
894  goto end;
895  }
896  result = 1;
897 end:
898  DetectEngineCtxFree(de_ctx);
899  return result;
900 }
901 #endif
902 
903 #if 0
904 /** Global trees that hold host reputation for IPV4 and IPV6 hosts */
905 IPReputationCtx *rep_ctx;
906 
907 /**
908  * \brief Initialization fuction for the Reputation Context (IPV4 and IPV6)
909  *
910  * \retval Pointer to the IPReputationCtx created
911  * NULL Error initializing moule;
912  */
913 IPReputationCtx *SCReputationInitCtx(void)
914 {
915  rep_ctx = (IPReputationCtx *)SCMalloc(sizeof(IPReputationCtx));
916  if (rep_ctx == NULL)
917  return NULL;
918  memset(rep_ctx,0,sizeof(IPReputationCtx));
919 
920  rep_ctx->reputationIPV4_tree = SCRadixCreateRadixTree(SCReputationFreeData, NULL);
921  if (rep_ctx->reputationIPV4_tree == NULL) {
922  SCLogDebug("Error initializing Reputation IPV4 module");
923  return NULL;
924  }
925 
926  SCLogDebug("Reputation IPV4 module initialized");
927 
928  rep_ctx->reputationIPV6_tree = SCRadixCreateRadixTree(SCReputationFreeData, NULL);
929  if (rep_ctx->reputationIPV6_tree == NULL) {
930  SCLogDebug("Error initializing Reputation IPV6 module");
931  return NULL;
932  }
933 
934  SCLogDebug("Reputation IPV6 module initialized");
935  if (SCMutexInit(&rep_ctx->reputationIPV4_lock, NULL) != 0) {
936  SCLogError(SC_ERR_MUTEX, "Mutex not correctly initialized");
937  exit(EXIT_FAILURE);
938  }
939  if (SCMutexInit(&rep_ctx->reputationIPV6_lock, NULL) != 0) {
940  SCLogError(SC_ERR_MUTEX, "Mutex not correctly initialized");
941  exit(EXIT_FAILURE);
942  }
943 
944  return rep_ctx;
945 }
946 
947 
948 /**
949  * \brief Allocates the Reputation structure for a host/netblock
950  *
951  * \retval rep_data On success, pointer to the rep_data that has to be sent
952  * along with the key, to be added to the Radix tree
953  */
954 Reputation *SCReputationAllocData(void)
955 {
956  Reputation *rep_data = NULL;
957 
958  if ( (rep_data = SCMalloc(sizeof(Reputation))) == NULL)
959  return NULL;
960  memset(rep_data,0, sizeof(Reputation));
961  rep_data->ctime = time(NULL);
962  rep_data->mtime= time(NULL);
963 
964  return rep_data;
965 }
966 
967 /**
968  * \brief Used to SCFree the reputation data that is allocated by Reputation API
969  *
970  * \param Pointer to the data that has to be SCFreed
971  */
972 void SCReputationFreeData(void *data)
973 {
974  if (data != NULL)
975  SCFree(data);
976 
977  return;
978 }
979 
980 /**
981  * \brief Allocates the Reputation structure for a host/netblock
982  *
983  * \retval ReputationTransaction pointer On success
984  */
985 ReputationTransaction *SCReputationTransactionAlloc(void)
986 {
987  ReputationTransaction *rtx = NULL;
988 
989  if ( (rtx = SCMalloc(sizeof(ReputationTransaction))) == NULL)
990  return NULL;
991  memset(rtx, 0, sizeof(ReputationTransaction));
992 
993  return rtx;
994 }
995 
996 /**
997  * \brief Used to SCFree the transaction data
998  *
999  * \param Pointer to the data that has to be SCFreed
1000  */
1001 void SCReputationTransactionFreeData(void *data)
1002 {
1003  if (data != NULL)
1004  SCFree(data);
1005 
1006  return;
1007 }
1008 
1009 /**
1010  * \brief Apply the transaction of changes to the reputation
1011  * We use transactions because we cant be locking/unlocking the
1012  * trees foreach update. This help for a better performance
1013  *
1014  * \param rep_data pointer to the reputation to update
1015  * \param rtx pointer to the transaction data
1016  */
1017 void SCReputationApplyTransaction(Reputation *rep_data, ReputationTransaction *rtx)
1018 {
1019  int i = 0;
1020 
1021  /* No modification needed */
1022  if ( !(rtx->flags & TRANSACTION_FLAG_NEEDSYNC))
1023  return;
1024 
1025  /* Here we should apply a formula, a threshold or similar,
1026  * maybe values loaded from config */
1027  for (; i < REPUTATION_NUMBER; i++) {
1028  if (rtx->flags & TRANSACTION_FLAG_INCS) {
1029  if (rep_data->reps[i] + rtx->inc[i] < 255)
1030  rep_data->reps[i] += rtx->inc[i];
1031  else
1032  rep_data->reps[i] = 255;
1033  }
1034  if (rtx->flags & TRANSACTION_FLAG_DECS) {
1035  if (rep_data->reps[i] - rtx->dec[i] > 0)
1036  rep_data->reps[i] -= rtx->dec[i];
1037  else
1038  rep_data->reps[i] = 0;
1039  }
1040  }
1041  rep_data->mtime = time(NULL);
1042  rep_data->flags |= REPUTATION_FLAG_NEEDSYNC;
1043 }
1044 
1045 /**
1046  * \brief Function that compare two reputation structs to determine if they are equal
1047  *
1048  * \param rep1 pointer to reputation 1
1049  * \param rep2 pointer to reputation 2
1050  *
1051  * \retval 1 if they are equal; 0 if not
1052  */
1053 int SCReputationEqual(Reputation *rep1, Reputation *rep2)
1054 {
1055  return (memcmp(rep1->reps, rep2->reps, REPUTATION_NUMBER * sizeof(uint8_t)) == 0)? 1 : 0;
1056 }
1057 
1058 
1059 /**
1060  * \brief Helper function to print the Reputation structure
1061  *
1062  * \param Pointer rep_data to a Reputation structure
1063  */
1064 void SCReputationPrint(Reputation *rep_data)
1065 {
1066  if (rep_data == NULL) {
1067  printf("No Reputation Data!\n");
1068  return;
1069  }
1070  int i = 0;
1071  for (; i < REPUTATION_NUMBER; i++)
1072  printf("Rep_type %d = %d\n", i, rep_data->reps[i]);
1073 
1074  if (rep_data->flags & REPUTATION_FLAG_NEEDSYNC)
1075  printf("REPUTATION_FLAG_NEEDSYNC = 1\n");
1076 }
1077 
1078 /**
1079  * \brief Clone all the data of a reputation
1080  * When you try to update the feed, if the data you have belongs
1081  * to a netblock, it will be cloned and inserted or a host, with
1082  * the modifications that you add
1083  *
1084  * \param orig Pointer to the original reputation (probably of a netblock)
1085  *
1086  * \retval Reputation Pointer to the reputation copy
1087  */
1088 Reputation *SCReputationClone(Reputation *orig)
1089 {
1090  Reputation *rep = NULL;
1091  if (orig == NULL) {
1092  SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid arguments");
1093  return NULL;
1094  }
1095 
1096  if ( (rep = SCMalloc(sizeof(Reputation))) == NULL)
1097  return NULL;
1098  memcpy(rep, orig, sizeof(Reputation));
1099  return rep;
1100 }
1101 
1102 void SCReputationFreeCtx(IPReputationCtx *ctx)
1103 {
1104  if (ctx->reputationIPV4_tree != NULL) {
1106  ctx->reputationIPV4_tree = NULL;
1108  }
1109  if (ctx->reputationIPV6_tree != NULL) {
1111  ctx->reputationIPV6_tree = NULL;
1113  }
1114 }
1115 
1116 /**
1117  * \brief Used to add a new reputation to the reputation module (only at the startup)
1118  *
1119  * \param ipv4addr pointer to the ipv4 address key
1120  * \param netmask_value of the ipv4 address (can be a subnet or a host (32))
1121  * \param rep_data Reputation pointer to the Reputation associated to the host/net
1122  *
1123  * \retval NULL On failure; rep_data on success
1124  */
1125 Reputation *SCReputationAddIPV4Data(uint8_t *ipv4addr, int netmask_value, Reputation *rep_data)
1126 {
1127  struct in_addr *ipv4_addr = (struct in_addr *) ipv4addr;
1128 
1129  if (ipv4_addr == NULL || rep_data == NULL || rep_ctx == NULL) {
1130  SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid arguments");
1131  return NULL;
1132  }
1133 
1134  /* If the reputation tree is not initialized yet */
1135  if (rep_ctx->reputationIPV4_tree == NULL) {
1136  SCLogError(SC_ERR_INVALID_ARGUMENT, "Reputation trees not initialized");
1137  return NULL;
1138  }
1139 
1140  if (netmask_value == 32) {
1141  /* Be careful with the mutex */
1142  SCMutexLock(&rep_ctx->reputationIPV4_lock);
1143  SCRadixAddKeyIPV4((uint8_t *)ipv4_addr, rep_ctx->reputationIPV4_tree,
1144  (void *)rep_data);
1146 
1147  } else {
1148  if (netmask_value < 0 || netmask_value > 31) {
1149  SCLogError(SC_ERR_INVALID_IP_NETBLOCK, "Invalid IPV4 Netblock");
1150  return NULL;
1151  }
1152 
1153  MaskIPNetblock((uint8_t *)ipv4_addr, netmask_value, 32);
1154 
1155  /* Be careful with the mutex */
1156  SCMutexLock(&rep_ctx->reputationIPV4_lock);
1157  SCRadixAddKeyIPV4Netblock((uint8_t *)ipv4_addr, rep_ctx->reputationIPV4_tree,
1158  (void *)rep_data, netmask_value);
1160  }
1161 
1162  return rep_data;
1163 }
1164 
1165 /**
1166  * \brief Retrieves the Reputation of a host (exact match), given an ipv4 address in the raw
1167  * address format.
1168  *
1169  * \param ipv4_addr Pointer to a raw ipv4 address.
1170  *
1171  * \retval Pointer to a copy of the host Reputation on success;
1172  * NULL on failure, or on not finding the key;
1173  */
1174 Reputation *SCReputationLookupIPV4ExactMatch(uint8_t *ipv4_addr)
1175 {
1176  Reputation *rep_data = NULL;
1177 
1178  /* Be careful with this (locking)*/
1179  SCMutexLock(&rep_ctx->reputationIPV4_lock);
1180 
1181  void *user_data = NULL;
1182  (void)SCRadixFindKeyIPV4ExactMatch(ipv4_addr, rep_ctx->reputationIPV4_tree, &user_data);
1183  if (user_data == NULL) {
1184  rep_data = NULL;
1185  } else {
1186  /* Yes, we clone it because the pointer can be outdated
1187  * while another thread remove this reputation */
1188  rep_data = SCReputationClone((Reputation *)user_data);
1189  }
1190 
1192  return rep_data;
1193 }
1194 
1195 /**
1196  * \brief Retrieves the Reputation of a host (best match), given an ipv4 address in the raw
1197  * address format.
1198  *
1199  * \param ipv4_addr Pointer to a raw ipv4 address.
1200  *
1201  * \retval Pointer to a copy of the host Reputation on success;
1202  * NULL on failure, or on not finding the key;
1203  */
1204 Reputation *SCReputationLookupIPV4BestMatch(uint8_t *ipv4_addr)
1205 {
1206  Reputation *rep_data;
1207 
1208  /* Be careful with this (locking)*/
1209  SCMutexLock(&rep_ctx->reputationIPV4_lock);
1210 
1211  void *user_data = NULL;
1212  (void)SCRadixFindKeyIPV4BestMatch(ipv4_addr, rep_ctx->reputationIPV4_tree, &user_data);
1213  if (user_data == NULL) {
1214  rep_data = NULL;
1215  } else {
1216  /* Yes, we clone it because the pointer can be outdated
1217  * while another thread remove this reputation */
1218  rep_data = SCReputationClone((Reputation *)user_data);
1219  }
1220 
1222  return rep_data;
1223 }
1224 
1225 /**
1226  * \brief Retrieves the Reputation of a host (best match), given an ipv6 address in the raw
1227  * address format.
1228  *
1229  * \param Pointer to a raw ipv6 address.
1230  *
1231  * \retval Pointer to a copy of the host Reputation on success;
1232  * NULL on failure, or on not finding the key;
1233  */
1234 Reputation *SCReputationLookupIPV6BestMatch(uint8_t *ipv6_addr)
1235 {
1236  Reputation *rep_data;
1237 
1238  /* Be careful with this (locking)*/
1239  SCMutexLock(&rep_ctx->reputationIPV6_lock);
1240 
1241  void *user_data = NULL;
1242  (void)SCRadixFindKeyIPV6BestMatch(ipv6_addr, rep_ctx->reputationIPV6_tree, &user_data);
1243  if (user_data == NULL) {
1244  rep_data = NULL;
1245  } else {
1246  /* Yes, we clone it because the pointer can be outdated
1247  * while another thread remove this reputation */
1248  rep_data = SCReputationClone((Reputation *)user_data);
1249  }
1250 
1252  return rep_data;
1253 }
1254 
1255 /**
1256  * \brief Retrieves the Reputation of a host (exact match), given an ipv6 address in the raw
1257  * address format.
1258  *
1259  * \param Pointer to a raw ipv6 address.
1260  *
1261  * \retval Pointer to a copy of the host reputation on success;
1262  * NULL on failure, or on not finding the key;
1263  */
1264 Reputation *SCReputationLookupIPV6ExactMatch(uint8_t *ipv6_addr)
1265 {
1266  Reputation *rep_data;
1267 
1268  /* Be careful with this (locking)*/
1269  SCMutexLock(&rep_ctx->reputationIPV6_lock);
1270 
1271  void *user_data = NULL;
1272  (void)SCRadixFindKeyIPV6ExactMatch(ipv6_addr, rep_ctx->reputationIPV6_tree, &user_data);
1273  if (user_data == NULL) {
1274  rep_data = NULL;
1275  } else {
1276  /* Yes, we clone it because the pointer can be outdated
1277  * while another thread remove this reputation */
1278  rep_data = SCReputationClone((Reputation *)user_data);
1279  }
1280 
1282  return rep_data;
1283 }
1284 
1285 
1286 /**
1287  * \brief Retrieves the Real Reputation of a host (exact match), given an ipv4 address in the raw
1288  * address format. (Not thread safe!)
1289  *
1290  * \param ipv4_addr Pointer to a raw ipv4 address.
1291  *
1292  * \retval Pointer to the Reputation of the host on success;
1293  * NULL on failure, or on not finding the key;
1294  */
1295 Reputation *SCReputationLookupIPV4ExactMatchReal(uint8_t *ipv4_addr)
1296 {
1297  void *user_data = NULL;
1298  (void)SCRadixFindKeyIPV4ExactMatch(ipv4_addr, rep_ctx->reputationIPV4_tree, &user_data);
1299  if (user_data == NULL) {
1300  return NULL;
1301  } else {
1302  return (Reputation *)user_data;
1303  }
1304 }
1305 
1306 /**
1307  * \brief Retrieves the Real Reputation of a host (best match), given an ipv4 address in the raw
1308  * address format. (Not thread safe!)
1309  *
1310  * \param ipv4_addr Pointer to a raw ipv4 address.
1311  *
1312  * \retval Pointer to the Reputation of the host on success;
1313  * NULL on failure, or on not finding the key;
1314  */
1315 Reputation *SCReputationLookupIPV4BestMatchReal(uint8_t *ipv4_addr)
1316 {
1317  void *user_data = NULL;
1318  (void)SCRadixFindKeyIPV4BestMatch(ipv4_addr, rep_ctx->reputationIPV4_tree, &user_data);
1319  if (user_data == NULL) {
1320  return NULL;
1321  } else {
1322  return (Reputation *)user_data;
1323  }
1324 }
1325 
1326 /**
1327  * \brief Retrieves the Real Reputation of a host (best match), given an ipv6 address in the raw
1328  * address format. (Not thread safe!)
1329  *
1330  * \param Pointer to a raw ipv6 address.
1331  *
1332  * \retval Pointer to the Reputation of the host on success;
1333  * NULL on failure, or on not finding the key;
1334  */
1335 Reputation *SCReputationLookupIPV6BestMatchReal(uint8_t *ipv6_addr)
1336 {
1337  void *user_data = NULL;
1338  (void)SCRadixFindKeyIPV6BestMatch(ipv6_addr, rep_ctx->reputationIPV6_tree, &user_data);
1339  if (user_data == NULL) {
1340  return NULL;
1341  } else {
1342  return (Reputation *)user_data;
1343  }
1344 }
1345 
1346 /**
1347  * \brief Retrieves the Real Reputation of a host (exact match), given an ipv6 address in the raw
1348  * address format. (Not thread safe!)
1349  *
1350  * \param Pointer to a raw ipv6 address.
1351  *
1352  * \retval Pointer to the Reputation of the host on success;
1353  * NULL on failure, or on not finding the key;
1354  */
1355 Reputation *SCReputationLookupIPV6ExactMatchReal(uint8_t *ipv6_addr)
1356 {
1357  void *user_data = NULL;
1358  (void)SCRadixFindKeyIPV6ExactMatch(ipv6_addr, rep_ctx->reputationIPV6_tree, &user_data);
1359  if (user_data == NULL) {
1360  return NULL;
1361  } else {
1362  return (Reputation *)user_data;
1363  }
1364 }
1365 
1366 /**
1367  * \brief Remove the node of the reputation tree associated to the ipv4 address
1368  *
1369  * \param ipv4_addr Pointer to a raw ipv4 address
1370  * \param netmask_value netmask to apply to the address (32 for host)
1371  *
1372  */
1373 void SCReputationRemoveIPV4Data(uint8_t * ipv4_addr, uint8_t netmask_value)
1374 {
1375  SCMutexLock(&rep_ctx->reputationIPV4_lock);
1376  SCRadixRemoveKeyIPV4Netblock(ipv4_addr, rep_ctx->reputationIPV4_tree, netmask_value);
1378 }
1379 
1380 /**
1381  * \brief Remove the node of the reputation tree associated to the ipv6 address
1382  *
1383  * \param ipv6_addr Pointer to a raw ipv6 address
1384  * \param netmask_value netmask to apply to the address (128 for host)
1385  *
1386  */
1387 void SCReputationRemoveIPV6Data(uint8_t * ipv6_addr, uint8_t netmask_value)
1388 {
1389  SCMutexLock(&rep_ctx->reputationIPV6_lock);
1390  SCRadixRemoveKeyIPV6Netblock(ipv6_addr, rep_ctx->reputationIPV6_tree, netmask_value);
1392 }
1393 
1394 /**
1395  * \brief Used to add a new reputation to the reputation module (only at the startup)
1396  *
1397  * \param ipv6addr pointer to the ipv6 address key
1398  * \param netmask_value of the ipv6 address (can be a subnet)
1399  * \param rep_data Reputation pointer to the Reputation associated to the host/net
1400  *
1401  * \retval NULL On failure
1402  */
1403 Reputation *SCReputationAddIPV6Data(uint8_t *ipv6addr, int netmask_value, Reputation *rep_data)
1404 {
1405  struct in_addr *ipv6_addr = (struct in_addr *) ipv6addr;
1406 
1407  if (ipv6_addr == NULL || rep_data == NULL || rep_ctx == NULL) {
1408  SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid arguments");
1409  return NULL;
1410  }
1411 
1412  /* If the reputation tree is not initialized yet */
1413  if (rep_ctx->reputationIPV6_tree == NULL) {
1414  SCLogError(SC_ERR_INVALID_ARGUMENT, "Reputation trees not initialized");
1415  return NULL;
1416  }
1417 
1418  if (netmask_value == 128) {
1419  /* Be careful with the mutex */
1420  SCMutexLock(&rep_ctx->reputationIPV6_lock);
1421  SCRadixAddKeyIPV6((uint8_t *)ipv6_addr, rep_ctx->reputationIPV6_tree,
1422  (void *)rep_data);
1424 
1425  } else {
1426  if (netmask_value < 0 || netmask_value > 127) {
1427  SCLogError(SC_ERR_INVALID_IP_NETBLOCK, "Invalid IPV6 Netblock");
1428  return NULL;
1429  }
1430 
1431  MaskIPNetblock((uint8_t *)ipv6_addr, netmask_value, 128);
1432 
1433  /* Be careful with the mutex */
1434  SCMutexLock(&rep_ctx->reputationIPV6_lock);
1435  SCRadixAddKeyIPV6Netblock((uint8_t *)ipv6_addr, rep_ctx->reputationIPV6_tree,
1436  (void *)rep_data, netmask_value);
1438  }
1439 
1440  return rep_data;
1441 }
1442 
1443 /**
1444  * \brief Update a reputation or insert a new one. If it doesn't exist
1445  * it will try to search for the reputation of parent subnets to
1446  * create the new reputation data based on this one
1447  *
1448  * \param ipv6addr pointer to the ipv6 address key
1449  * \param rep_data Reputation pointer to the Reputation associated to the host/net
1450  *
1451  * \retval NULL On failure
1452  */
1453 Reputation *SCReputationUpdateIPV4Data(uint8_t *ipv4addr, ReputationTransaction *rtx)
1454 {
1455  struct in_addr *ipv4_addr = (struct in_addr *) ipv4addr;
1456  Reputation *actual_rep;
1457 
1458  if (ipv4_addr == NULL || rtx == NULL || rep_ctx == NULL) {
1459  SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid arguments");
1460  return NULL;
1461  }
1462 
1463  /* If the reputation tree is not initialized yet */
1464  if (rep_ctx->reputationIPV4_tree == NULL) {
1465  SCLogError(SC_ERR_INVALID_ARGUMENT, "Reputation trees not initialized");
1466  return NULL;
1467  }
1468 
1469  /* Be careful with the mutex */
1470  SCMutexLock(&rep_ctx->reputationIPV4_lock);
1471 
1472  /* Search exact match and update */
1473  actual_rep = SCReputationLookupIPV4ExactMatchReal(ipv4addr);
1474  if (actual_rep == NULL) {
1475  /* else search best match (parent subnets) */
1476  actual_rep =SCReputationLookupIPV4BestMatchReal(ipv4addr);
1477 
1478  if (actual_rep != NULL) {
1479  /* clone from parent and insert host */
1480  actual_rep = SCReputationClone(actual_rep);
1481  } else {
1482  /* else insert a new reputation data for the host */
1483  actual_rep = SCReputationAllocData();
1484  /* If new, we only increment values */
1485  rtx->flags = TRANSACTION_FLAG_INCS;
1486  rtx->flags |= TRANSACTION_FLAG_NEEDSYNC;
1487  }
1488 
1489  /* insert the reputation data in the tree */
1490  SCRadixAddKeyIPV4((uint8_t *)ipv4_addr, rep_ctx->reputationIPV4_tree,
1491  (void *)actual_rep);
1492  }
1493  /* Apply updates */
1494  SCReputationApplyTransaction(actual_rep, rtx);
1495 
1496  /* Unlock! */
1498 
1499  return actual_rep;
1500 }
1501 
1502 /**
1503  * \brief Update a reputation or insert a new one. If it doesn't exist
1504  * it will try to search for the reputation of parent subnets to
1505  * create the new reputation data based on this one
1506  *
1507  * \param ipv6addr pointer to the ipv6 address key
1508  * \param rep_data Reputation pointer to the Reputation associated to the host/net
1509  *
1510  * \retval NULL On failure
1511  */
1512 Reputation *SCReputationUpdateIPV6Data(uint8_t *ipv6addr, ReputationTransaction *rtx)
1513 {
1514  struct in_addr *ipv6_addr = (struct in_addr *) ipv6addr;
1515  Reputation *actual_rep;
1516 
1517  if (ipv6_addr == NULL || rtx == NULL || rep_ctx == NULL) {
1518  SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid arguments");
1519  return NULL;
1520  }
1521 
1522  /* If the reputation tree is not initialized yet */
1523  if (rep_ctx->reputationIPV6_tree == NULL) {
1524  SCLogError(SC_ERR_INVALID_ARGUMENT, "Reputation trees not initialized");
1525  return NULL;
1526  }
1527 
1528  /* Be careful with the mutex */
1529  SCMutexLock(&rep_ctx->reputationIPV6_lock);
1530 
1531  /* Search exact match and update */
1532  actual_rep = SCReputationLookupIPV6ExactMatchReal(ipv6addr);
1533  if (actual_rep == NULL) {
1534  /* else search best match (parent subnets) */
1535  actual_rep =SCReputationLookupIPV6BestMatchReal(ipv6addr);
1536 
1537  if (actual_rep != NULL) {
1538  /* clone from parent and insert host */
1539  actual_rep = SCReputationClone(actual_rep);
1540  } else {
1541  /* else insert a new reputation data for the host */
1542  actual_rep = SCReputationAllocData();
1543  /* If new, we only increment values */
1544  rtx->flags = TRANSACTION_FLAG_INCS;
1545  rtx->flags |= TRANSACTION_FLAG_NEEDSYNC;
1546  }
1547 
1548  /* insert the reputation data in the tree */
1549  SCRadixAddKeyIPV6((uint8_t *)ipv6_addr, rep_ctx->reputationIPV6_tree,
1550  (void *)actual_rep);
1551  }
1552  /* Apply updates */
1553  SCReputationApplyTransaction(actual_rep, rtx);
1554 
1555  /* Unlock! */
1557 
1558  return actual_rep;
1559 }
1560 
1561 
1562 /* ----------------- UNITTESTS-------------------- */
1563 #ifdef UNITTESTS
1564 
1565 /**
1566  * \test Adding (from numeric ipv4) and removing host reputation in the Reputation context
1567  * tree. THe reputation data is the real one, no copies here.
1568  */
1569 int SCReputationTestIPV4AddRemoveHost01(void)
1570 {
1571  int i = 0;
1572  struct in_addr in;
1573 
1574  SCReputationInitCtx();
1575  if (rep_ctx == NULL) {
1576  SCLogInfo("Error initializing Reputation Module");
1577  return 0;
1578  }
1579 
1580  Reputation *rep_orig = SCReputationAllocData();
1581  if (rep_orig == NULL)
1582  goto error;
1583 
1584  if (inet_pton(AF_INET, "192.168.1.6", &in) < 0)
1585  goto error;
1586 
1587  /* Fill the reputation with some values.. */
1588  for (i = 0; i < REPUTATION_NUMBER; i++)
1589  rep_orig->reps[i] = i * 10 + 6;
1590 
1591  rep_orig = SCReputationAddIPV4Data((uint8_t *) &in, 32, rep_orig);
1592  if (rep_orig == NULL)
1593  goto error;
1594 
1595  Reputation *rep_data = SCReputationLookupIPV4ExactMatchReal((uint8_t *) &in);
1596  if (rep_data == NULL || rep_data != rep_orig)
1597  goto error;
1598 
1599  rep_orig = SCReputationAllocData();
1600  if (rep_orig == NULL)
1601  goto error;
1602 
1603  if (inet_pton(AF_INET, "192.168.1.7", &in) < 0)
1604  goto error;
1605 
1606  for (i = 0; i < REPUTATION_NUMBER; i++)
1607  rep_orig->reps[i] = i * 10 + 7;
1608 
1609  rep_orig = SCReputationAddIPV4Data((uint8_t *) &in, 32, rep_orig);
1610  if (rep_orig == NULL)
1611  goto error;
1612 
1613  rep_data = SCReputationLookupIPV4ExactMatchReal((uint8_t *) &in);
1614  if (rep_data == NULL || rep_data != rep_orig)
1615  goto error;
1616 
1617  rep_orig = SCReputationAllocData();
1618  if (rep_orig == NULL)
1619  goto error;
1620 
1621  if (inet_pton(AF_INET, "192.168.1.7", &in) < 0)
1622  goto error;
1623 
1624  for (i = 0; i < REPUTATION_NUMBER; i++)
1625  rep_orig->reps[i] = i * 10 + 7;
1626 
1627  rep_orig = SCReputationAddIPV4Data((uint8_t *) &in, 31, rep_orig);
1628  if (rep_orig == NULL)
1629  goto error;
1630 
1631  rep_data = SCReputationLookupIPV4ExactMatchReal((uint8_t *) &in);
1632  /* It should return the host info and not the subnet info */
1633  if (rep_data == NULL || rep_data == rep_orig)
1634  goto error;
1635 
1636  if (inet_pton(AF_INET, "192.168.1.8", &in) < 0)
1637  goto error;
1638 
1639  rep_data = SCReputationLookupIPV4ExactMatchReal((uint8_t *) &in);
1640  /* It should return the host info and not the subnet info */
1641  if (rep_data != NULL)
1642  goto error;
1643 
1644 
1645  /* Removing */
1646  if (inet_pton(AF_INET, "192.168.1.7", &in) < 0)
1647  goto error;
1648 
1649  SCReputationRemoveIPV4Data((uint8_t *) &in, 32);
1650 
1651  rep_data = SCReputationLookupIPV4ExactMatchReal((uint8_t *) &in);
1652  if (rep_data != NULL)
1653  goto error;
1654 
1655  if (inet_pton(AF_INET, "192.168.1.6", &in) < 0)
1656  goto error;
1657 
1658  SCReputationRemoveIPV4Data((uint8_t *) &in, 32);
1659  rep_data = SCReputationLookupIPV4ExactMatchReal((uint8_t *) &in);
1660  if (rep_data != NULL)
1661  goto error;
1662 
1664 
1665  SCReputationFreeCtx(rep_ctx);
1666  rep_ctx = NULL;
1667  return 1;
1668 
1669 error:
1670  SCReputationFreeCtx(rep_ctx);
1671  rep_ctx = NULL;
1672  return 0;
1673 }
1674 
1675 /**
1676  * \test Adding (from numeric ipv6) and removing host reputation in the Reputation context
1677  * tree. THe reputation data is the real one, no copies here.
1678  */
1679 int SCReputationTestIPV6AddRemoveHost01(void)
1680 {
1681  uint8_t in[16];
1682  uint8_t i = 0;
1683 
1684  SCReputationInitCtx();
1685  if (rep_ctx == NULL) {
1686  SCLogInfo("Error initializing Reputation Module");
1687  return 0;
1688  }
1689 
1690  if (inet_pton(AF_INET6, "aaaa:bbbb:cccc:dddd:1223:1722:3425:2362", &in) < 0)
1691  goto error;
1692 
1693  Reputation *rep_orig = SCReputationAllocData();
1694  if (rep_orig == NULL)
1695  goto error;
1696 
1697  /* Fill the reputation with some values.. */
1698  for (i = 0; i < REPUTATION_NUMBER; i++)
1699  rep_orig->reps[i] = i * 10 + 1;
1700 
1701  rep_orig = SCReputationAddIPV6Data((uint8_t *) &in, 128, rep_orig);
1702  if (rep_orig == NULL)
1703  goto error;
1704 
1705  Reputation *rep_data = SCReputationLookupIPV6ExactMatchReal((uint8_t *) &in);
1706  if (rep_data == NULL || rep_data != rep_orig)
1707  goto error;
1708 
1709  rep_orig = SCReputationAllocData();
1710  if (rep_orig == NULL)
1711  goto error;
1712 
1713  if (inet_pton(AF_INET6, "aaaa:bbbb:cccc:dddd:1223:1722:3425:2363", &in) < 0)
1714  goto error;
1715 
1716  for (i = 0; i < REPUTATION_NUMBER; i++)
1717  rep_orig->reps[i] = i * 10 + 8;
1718 
1719  rep_orig = SCReputationAddIPV6Data((uint8_t *) &in, 128, rep_orig);
1720  if (rep_orig == NULL)
1721  goto error;
1722 
1723  rep_data = SCReputationLookupIPV6ExactMatchReal((uint8_t *) &in);
1724 
1725  if (rep_data == NULL || rep_data != rep_orig)
1726  goto error;
1727 
1728  rep_orig = SCReputationAllocData();
1729  if (rep_orig == NULL)
1730  goto error;
1731 
1732  if (inet_pton(AF_INET6, "aaaa:bbbb:cccc:dddd:1223:1722:3425:2363", &in) < 0)
1733  goto error;
1734 
1735  for (i = 0; i < REPUTATION_NUMBER; i++)
1736  rep_orig->reps[i] = i * 10 + 7;
1737 
1738  rep_orig = SCReputationAddIPV6Data((uint8_t *) &in, 127, rep_orig);
1739  if (rep_orig == NULL)
1740  goto error;
1741 
1742  rep_data = SCReputationLookupIPV6ExactMatchReal((uint8_t *) &in);
1743  /* It should return the host info and not the subnet info */
1744  if (rep_data == NULL || rep_data == rep_orig)
1745  goto error;
1746 
1747 
1748  /* Removing */
1749  if (inet_pton(AF_INET6, "aaaa:bbbb:cccc:dddd:1223:1722:3425:2363", &in) < 0)
1750  goto error;
1751 
1752  SCReputationRemoveIPV6Data((uint8_t *) &in, 128);
1753 
1754  rep_data = SCReputationLookupIPV6ExactMatchReal((uint8_t *) &in);
1755  if (rep_data != NULL)
1756  goto error;
1757 
1758  if (inet_pton(AF_INET6, "aaaa:bbbb:cccc:dddd:1223:1722:3425:2362", &in) < 0)
1759  goto error;
1760 
1761  SCReputationRemoveIPV6Data((uint8_t *) &in, 128);
1762  rep_data = SCReputationLookupIPV6ExactMatchReal((uint8_t *) &in);
1763  if (rep_data != NULL)
1764  goto error;
1765 
1767 
1768  SCReputationFreeCtx(rep_ctx);
1769  rep_ctx = NULL;
1770  return 1;
1771 
1772 error:
1773  SCReputationFreeCtx(rep_ctx);
1774  rep_ctx = NULL;
1775  return 0;
1776 }
1777 
1778 /**
1779  * \test Adding (from numeric ipv4) and retrieving reputations
1780  * tree. The reputation data retireved are copies of the original.
1781  */
1782 int SCReputationTestIPV4AddRemoveHost02(void)
1783 {
1784  int i = 0;
1785  struct in_addr in;
1786 
1787  SCReputationInitCtx();
1788  if (rep_ctx == NULL) {
1789  SCLogInfo("Error initializing Reputation Module");
1790  return 0;
1791  }
1792 
1793  Reputation *rep_orig = SCReputationAllocData();
1794  if (rep_orig == NULL)
1795  goto error;
1796 
1797  if (inet_pton(AF_INET, "192.168.1.6", &in) < 0)
1798  goto error;
1799 
1800  /* Fill the reputation with some values.. */
1801  for (i = 0; i < REPUTATION_NUMBER; i++)
1802  rep_orig->reps[i] = i * 10 + 6;
1803 
1804  rep_orig = SCReputationAddIPV4Data((uint8_t *) &in, 32, rep_orig);
1805  if (rep_orig == NULL)
1806  goto error;
1807 
1808  Reputation *rep_data = SCReputationLookupIPV4ExactMatch((uint8_t *) &in);
1809  if (rep_data == NULL || SCReputationEqual(rep_data, rep_orig) == 0)
1810  goto error;
1811 
1812  rep_orig = SCReputationAllocData();
1813  if (rep_orig == NULL)
1814  goto error;
1815 
1816  if (inet_pton(AF_INET, "192.168.1.7", &in) < 0)
1817  goto error;
1818 
1819  for (i = 0; i < REPUTATION_NUMBER; i++)
1820  rep_orig->reps[i] = i * 10 + 7;
1821 
1822  rep_orig = SCReputationAddIPV4Data((uint8_t *) &in, 32, rep_orig);
1823  if (rep_orig == NULL)
1824  goto error;
1825 
1826  rep_data = SCReputationLookupIPV4ExactMatch((uint8_t *) &in);
1827  if (rep_data == NULL || SCReputationEqual(rep_data, rep_orig) == 0)
1828  goto error;
1829 
1830  rep_orig = SCReputationAllocData();
1831  if (rep_orig == NULL)
1832  goto error;
1833 
1834  if (inet_pton(AF_INET, "192.168.1.7", &in) < 0)
1835  goto error;
1836 
1837  for (i = 0; i < REPUTATION_NUMBER; i++)
1838  rep_orig->reps[i] = i * 10 + 9;
1839 
1840  rep_orig = SCReputationAddIPV4Data((uint8_t *) &in, 31, rep_orig);
1841  if (rep_orig == NULL)
1842  goto error;
1843 
1844  rep_data = SCReputationLookupIPV4ExactMatch((uint8_t *) &in);
1845  /* It should return the host info and not the subnet info */
1846  if (rep_data == NULL || SCReputationEqual(rep_data, rep_orig) == 1)
1847  goto error;
1848 
1850 
1851  SCReputationFreeCtx(rep_ctx);
1852  rep_ctx = NULL;
1853  return 1;
1854 
1855 error:
1856  SCReputationFreeCtx(rep_ctx);
1857  rep_ctx = NULL;
1858  return 0;
1859 }
1860 
1861 /**
1862  * \test Adding (from numeric ipv6) and removing host reputation in the Reputation context
1863  * tree. The reputation data retireved are copies of the original.
1864  */
1865 int SCReputationTestIPV6AddRemoveHost02(void)
1866 {
1867  int i = 0;
1868  uint8_t in[16];
1869 
1870  SCReputationInitCtx();
1871  if (rep_ctx == NULL) {
1872  SCLogInfo("Error initializing Reputation Module");
1873  return 0;
1874  }
1875 
1876  Reputation *rep_orig = SCReputationAllocData();
1877  if (rep_orig == NULL)
1878  goto error;
1879 
1880  if (inet_pton(AF_INET6, "aaaa:bbbb:cccc:dddd:1223:1722:3425:2362", &in) < 0)
1881  goto error;
1882 
1883  /* Fill the reputation with some values.. */
1884  for (i = 0; i < REPUTATION_NUMBER; i++)
1885  rep_orig->reps[i] = i * 10 + 6;
1886 
1887  rep_orig = SCReputationAddIPV6Data((uint8_t *) &in, 128, rep_orig);
1888  if (rep_orig == NULL)
1889  goto error;
1890 
1891  Reputation *rep_data = SCReputationLookupIPV6ExactMatch((uint8_t *) &in);
1892  if (rep_data == NULL || SCReputationEqual(rep_data, rep_orig) == 0)
1893  goto error;
1894 
1895  rep_orig = SCReputationAllocData();
1896  if (rep_orig == NULL)
1897  goto error;
1898  if (inet_pton(AF_INET6, "aaaa:bbbb:cccc:dddd:1223:1722:3425:2363", &in) < 0)
1899  goto error;
1900 
1901  for (i = 0; i < REPUTATION_NUMBER; i++)
1902  rep_orig->reps[i] = i * 10 + 7;
1903 
1904  rep_orig = SCReputationAddIPV6Data((uint8_t *) &in, 128, rep_orig);
1905  if (rep_orig == NULL)
1906  goto error;
1907 
1908  rep_data = SCReputationLookupIPV6ExactMatch((uint8_t *) &in);
1909  if (rep_data == NULL || SCReputationEqual(rep_data, rep_orig) == 0)
1910  goto error;
1911 
1912  rep_orig = SCReputationAllocData();
1913  if (rep_orig == NULL)
1914  goto error;
1915 
1916  if (inet_pton(AF_INET6, "aaaa:bbbb:cccc:dddd:1223:1722:3425:2363", &in) < 0)
1917  goto error;
1918 
1919  for (i = 0; i < REPUTATION_NUMBER; i++)
1920  rep_orig->reps[i] = i * 10 + 9;
1921 
1922  rep_orig = SCReputationAddIPV6Data((uint8_t *) &in, 127, rep_orig);
1923  if (rep_orig == NULL)
1924  goto error;
1925 
1926  rep_data = SCReputationLookupIPV6ExactMatch((uint8_t *) &in);
1927  /* It should return the host info and not the subnet info */
1928  if (rep_data == NULL || SCReputationEqual(rep_data, rep_orig) == 1)
1929  goto error;
1930 
1931  if (inet_pton(AF_INET6, "aaaa:bbbb:cccc:dddd:1223:1722:3425:2364", &in) < 0)
1932  goto error;
1933 
1934  rep_data = SCReputationLookupIPV6ExactMatch((uint8_t *) &in);
1935  /* It should return the host info and not the subnet info */
1936  if (rep_data != NULL)
1937  goto error;
1938 
1940 
1941  SCReputationFreeCtx(rep_ctx);
1942  rep_ctx = NULL;
1943  return 1;
1944 
1945 error:
1946  SCReputationFreeCtx(rep_ctx);
1947  rep_ctx = NULL;
1948  return 0;
1949 }
1950 
1951 /**
1952  * \test Test searches (best and exact matches)
1953  */
1954 int SCReputationTestIPV4BestExactMatch01(void)
1955 {
1956  int i = 0;
1957  struct in_addr in;
1958 
1959  SCReputationInitCtx();
1960  if (rep_ctx == NULL) {
1961  SCLogInfo("Error initializing Reputation Module");
1962  return 0;
1963  }
1964 
1965  Reputation *rep_origC = NULL;
1966  Reputation *rep_origB = NULL;
1967  Reputation *rep_origA = NULL;
1968 
1969  Reputation *rep_orig = SCReputationAllocData();
1970  if (rep_orig == NULL)
1971  goto error;
1972 
1973  if (inet_pton(AF_INET, "192.168.1.6", &in) < 0)
1974  goto error;
1975 
1976  /* Fill the reputation with some values.. */
1977  for (i = 0; i < REPUTATION_NUMBER; i++)
1978  rep_orig->reps[i] = i * 10 + 6;
1979 
1980  /* adding a host */
1981  rep_orig = SCReputationAddIPV4Data((uint8_t *) &in, 32, rep_orig);
1982  if (rep_orig == NULL)
1983  goto error;
1984  Reputation *rep_data = SCReputationLookupIPV4ExactMatchReal((uint8_t *) &in);
1985  if (rep_data == NULL || rep_data != rep_orig)
1986  goto error;
1987 
1988  rep_orig = SCReputationAllocData();
1989  if (rep_orig == NULL)
1990  goto error;
1991 
1992  /* Adding C subnet */
1993  if (inet_pton(AF_INET, "192.168.1.0", &in) < 0)
1994  goto error;
1995 
1996  for (i = 0; i < REPUTATION_NUMBER; i++)
1997  rep_orig->reps[i] = i * 10 + 7;
1998 
1999  rep_origC = SCReputationAddIPV4Data((uint8_t *) &in, 24, rep_orig);
2000  if (rep_origC == NULL)
2001  goto error;
2002 
2003  if (inet_pton(AF_INET, "192.168.1.5", &in) < 0)
2004  goto error;
2005 
2006  rep_data = SCReputationLookupIPV4ExactMatchReal((uint8_t *) &in);
2007  if (rep_data != NULL)
2008  goto error;
2009 
2010  rep_data = SCReputationLookupIPV4BestMatchReal((uint8_t *) &in);
2011  if (rep_data == NULL || rep_data != rep_origC)
2012  goto error;
2013 
2014  rep_orig = SCReputationAllocData();
2015  /* Adding B subnet */
2016  if (inet_pton(AF_INET, "192.168.0.0", &in) < 0)
2017  goto error;
2018 
2019  for (i = 0; i < REPUTATION_NUMBER; i++)
2020  rep_orig->reps[i] = i * 10 + 7;
2021 
2022  rep_origB = SCReputationAddIPV4Data((uint8_t *) &in, 16, rep_orig);
2023  if (rep_origB == NULL)
2024  goto error;
2025 
2026  if (inet_pton(AF_INET, "192.168.1.5", &in) < 0)
2027  goto error;
2028 
2029  rep_data = SCReputationLookupIPV4ExactMatchReal((uint8_t *) &in);
2030  if (rep_data != NULL)
2031  goto error;
2032 
2033  rep_data = SCReputationLookupIPV4BestMatchReal((uint8_t *) &in);
2034  if (rep_data == NULL || rep_data != rep_origC)
2035  goto error;
2036 
2037  if (inet_pton(AF_INET, "192.168.2.5", &in) < 0)
2038  goto error;
2039 
2040  rep_data = SCReputationLookupIPV4ExactMatchReal((uint8_t *) &in);
2041  if (rep_data != NULL)
2042  goto error;
2043 
2044  rep_data = SCReputationLookupIPV4BestMatchReal((uint8_t *) &in);
2045  if (rep_data == NULL || rep_data != rep_origB)
2046  goto error;
2047 
2048  rep_orig = SCReputationAllocData();
2049  /* Adding A subnet */
2050  if (inet_pton(AF_INET, "192.0.0.0", &in) < 0)
2051  goto error;
2052 
2053  for (i = 0; i < REPUTATION_NUMBER; i++)
2054  rep_orig->reps[i] = i * 10 + 7;
2055 
2056  rep_origA = SCReputationAddIPV4Data((uint8_t *) &in, 8, rep_orig);
2057  if (rep_origA == NULL)
2058  goto error;
2059 
2060  if (inet_pton(AF_INET, "192.168.1.5", &in) < 0)
2061  goto error;
2062 
2063  rep_data = SCReputationLookupIPV4ExactMatchReal((uint8_t *) &in);
2064  if (rep_data != NULL)
2065  goto error;
2066 
2067  rep_data = SCReputationLookupIPV4BestMatchReal((uint8_t *) &in);
2068  if (rep_data == NULL || rep_data != rep_origC)
2069  goto error;
2070 
2071  if (inet_pton(AF_INET, "192.168.2.5", &in) < 0)
2072  goto error;
2073 
2074  rep_data = SCReputationLookupIPV4ExactMatchReal((uint8_t *) &in);
2075  if (rep_data != NULL)
2076  goto error;
2077 
2078  rep_data = SCReputationLookupIPV4BestMatchReal((uint8_t *) &in);
2079  if (rep_data == NULL || rep_data != rep_origB)
2080  goto error;
2081 
2082  if (inet_pton(AF_INET, "192.167.2.5", &in) < 0)
2083  goto error;
2084 
2085  rep_data = SCReputationLookupIPV4ExactMatchReal((uint8_t *) &in);
2086  if (rep_data != NULL)
2087  goto error;
2088 
2089  rep_data = SCReputationLookupIPV4BestMatchReal((uint8_t *) &in);
2090  if (rep_data == NULL || rep_data != rep_origA)
2091  goto error;
2092 
2094 
2095  SCReputationFreeCtx(rep_ctx);
2096  rep_ctx = NULL;
2097  return 1;
2098 error:
2099  SCReputationFreeCtx(rep_ctx);
2100  rep_ctx = NULL;
2101  return 0;
2102 }
2103 
2104 /**
2105  * \test Update transactions
2106  */
2107 int SCReputationTestIPV4Update01(void)
2108 {
2109  int i = 0;
2110  struct in_addr in;
2111 
2112  SCReputationInitCtx();
2113  if (rep_ctx == NULL) {
2114  SCLogInfo("Error initializing Reputation Module");
2115  return 0;
2116  }
2117 
2118  Reputation *rep_orig = SCReputationAllocData();
2119 
2120  ReputationTransaction rtx;
2121  memset(&rtx, 0, sizeof(ReputationTransaction));
2122  if (rep_orig == NULL)
2123  goto error;
2124 
2125  /* Fill the reputation with some values.. */
2126  for (i = 0; i < REPUTATION_NUMBER; i++) {
2127  rep_orig->reps[i] = 10;
2128  }
2129 
2130  if (inet_pton(AF_INET, "192.168.0.0", &in) < 0)
2131  goto error;
2132 
2133  /* Add add it as net */
2134  rep_orig = SCReputationAddIPV4Data((uint8_t *) &in, 16, rep_orig);
2135  if (rep_orig == NULL)
2136  goto error;
2137 
2138  rtx.dec[REPUTATION_DDOS] = 5;
2139  rtx.inc[REPUTATION_PHISH] = 50;
2140  rtx.inc[REPUTATION_MALWARE] = 30;
2141  rtx.flags |= TRANSACTION_FLAG_NEEDSYNC;
2142  rtx.flags |= TRANSACTION_FLAG_INCS;
2143  rtx.flags |= TRANSACTION_FLAG_DECS;
2144 
2145  if (inet_pton(AF_INET, "192.168.10.100", &in) < 0)
2146  goto error;
2147 
2148  /* Update (it will create the host entry with the data of the net) */
2149  SCReputationUpdateIPV4Data((uint8_t *)&in, &rtx);
2150 
2151  /* Create the reputation that any host 192.168.* should have */
2152  Reputation *rep_aux = SCReputationAllocData();
2153 
2154  /* Fill the reputation with some values.. */
2155  for (i = 0; i < REPUTATION_NUMBER; i++) {
2156  rep_aux->reps[i] = 10;
2157  }
2158 
2159  rep_aux->reps[REPUTATION_DDOS] = 5;
2160  rep_aux->reps[REPUTATION_PHISH] = 60;
2161  rep_aux->reps[REPUTATION_MALWARE] = 40;
2162 
2163  Reputation *rep_data = SCReputationLookupIPV4BestMatchReal((uint8_t *) &in);
2164  if (rep_data == NULL || SCReputationEqual(rep_data, rep_aux) != 1)
2165  goto error;
2166 
2167  /* Now that is created, it should update only the host */
2168  rtx.dec[REPUTATION_DDOS] = 50;
2169  rtx.inc[REPUTATION_PHISH] = 50;
2170  rtx.inc[REPUTATION_MALWARE] = 50;
2171 
2172  rep_aux->reps[REPUTATION_DDOS] = 0;
2173  rep_aux->reps[REPUTATION_PHISH] = 110;
2174  rep_aux->reps[REPUTATION_MALWARE] = 90;
2175 
2176  SCReputationUpdateIPV4Data((uint8_t *)&in, &rtx);
2177 
2178  rep_data = SCReputationLookupIPV4ExactMatchReal((uint8_t *) &in);
2179  if (rep_data == NULL || SCReputationEqual(rep_data, rep_aux) != 1)
2180  goto error;
2181 
2182  /* So let's see if we add a host and get the parent data again */
2183  if (inet_pton(AF_INET, "192.168.10.101", &in) < 0)
2184  goto error;
2185 
2186  rep_aux->reps[REPUTATION_DDOS] = 10;
2187  rep_aux->reps[REPUTATION_PHISH] = 10;
2188  rep_aux->reps[REPUTATION_MALWARE] = 10;
2189 
2190  rep_data = SCReputationLookupIPV4BestMatchReal((uint8_t *) &in);
2191 
2192  if (rep_data == NULL || SCReputationEqual(rep_data, rep_aux) != 1)
2193  goto error;
2194 
2196  SCReputationFreeCtx(rep_ctx);
2197  rep_ctx = NULL;
2198  return 1;
2199 
2200 error:
2201  SCReputationFreeCtx(rep_ctx);
2202  rep_ctx = NULL;
2203  return 0;
2204 }
2205 
2206 /**
2207  * \test Update transactions
2208  */
2209 int SCReputationTestIPV6Update01(void)
2210 {
2211  int i = 0;
2212  uint8_t in[16];
2213 
2214  SCReputationInitCtx();
2215  if (rep_ctx == NULL) {
2216  SCLogInfo("Error initializing Reputation Module");
2217  return 0;
2218  }
2219 
2220  Reputation *rep_orig = SCReputationAllocData();
2221 
2222  ReputationTransaction rtx;
2223  memset(&rtx, 0, sizeof(ReputationTransaction));
2224  if (rep_orig == NULL)
2225  goto error;
2226 
2227  /* Fill the reputation with some values.. */
2228  for (i = 0; i < REPUTATION_NUMBER; i++) {
2229  rep_orig->reps[i] = 10;
2230  }
2231 
2232  if (inet_pton(AF_INET6, "8762:2352:6261:7265:EE23:21AD:2121:1DDD", &in) < 0)
2233  goto error;
2234 
2235  /* Add add it as net */
2236  rep_orig = SCReputationAddIPV6Data((uint8_t *) &in, 98, rep_orig);
2237  if (rep_orig == NULL)
2238  goto error;
2239 
2240  rtx.dec[REPUTATION_DDOS] = 5;
2241  rtx.inc[REPUTATION_PHISH] = 50;
2242  rtx.inc[REPUTATION_MALWARE] = 30;
2243  rtx.flags |= TRANSACTION_FLAG_NEEDSYNC;
2244  rtx.flags |= TRANSACTION_FLAG_INCS;
2245  rtx.flags |= TRANSACTION_FLAG_DECS;
2246 
2247  if (inet_pton(AF_INET6, "8762:2352:6261:7265:EE23:21AD:2121:1ABA", &in) < 0)
2248  goto error;
2249 
2250  /* Update (it will create the host entry with the data of the net) */
2251  SCReputationUpdateIPV6Data((uint8_t *)&in, &rtx);
2252 
2253  /* Create the reputation that any host 192.168.* should have */
2254  Reputation *rep_aux = SCReputationAllocData();
2255 
2256  /* Fill the reputation with some values.. */
2257  for (i = 0; i < REPUTATION_NUMBER; i++) {
2258  rep_aux->reps[i] = 10;
2259  }
2260 
2261  rep_aux->reps[REPUTATION_DDOS] = 5;
2262  rep_aux->reps[REPUTATION_PHISH] = 60;
2263  rep_aux->reps[REPUTATION_MALWARE] = 40;
2264 
2265  Reputation *rep_data = SCReputationLookupIPV6BestMatchReal((uint8_t *) &in);
2266  if (rep_data == NULL || SCReputationEqual(rep_data, rep_aux) != 1)
2267  goto error;
2268 
2269  /* Now that is created, it should update only the host */
2270  rtx.dec[REPUTATION_DDOS] = 50;
2271  rtx.inc[REPUTATION_PHISH] = 50;
2272  rtx.inc[REPUTATION_MALWARE] = 50;
2273 
2274  rep_aux->reps[REPUTATION_DDOS] = 0;
2275  rep_aux->reps[REPUTATION_PHISH] = 110;
2276  rep_aux->reps[REPUTATION_MALWARE] = 90;
2277 
2278  SCReputationUpdateIPV6Data((uint8_t *)&in, &rtx);
2279 
2280  rep_data = SCReputationLookupIPV6ExactMatchReal((uint8_t *) &in);
2281  if (rep_data == NULL || SCReputationEqual(rep_data, rep_aux) != 1)
2282  goto error;
2283 
2284  /* So let's see if we add a host and get the parent data again */
2285  if (inet_pton(AF_INET6, "8762:2352:6261:7265:EE23:21AD:2121:1ACB", &in) < 0)
2286  goto error;
2287 
2288  rep_aux->reps[REPUTATION_DDOS] = 10;
2289  rep_aux->reps[REPUTATION_PHISH] = 10;
2290  rep_aux->reps[REPUTATION_MALWARE] = 10;
2291 
2292  rep_data = SCReputationLookupIPV6BestMatchReal((uint8_t *) &in);
2293 
2294 
2295  if (rep_data == NULL || SCReputationEqual(rep_data, rep_aux) != 1)
2296  goto error;
2297 
2299  SCReputationFreeCtx(rep_ctx);
2300  rep_ctx = NULL;
2301  return 1;
2302 
2303 error:
2304  SCReputationFreeCtx(rep_ctx);
2305  rep_ctx = NULL;
2306  return 0;
2307 }
2308 
2309 #endif /* UNITTESTS */
2310 #endif
2311 
2312 /** Register the following unittests for the Reputation module */
2314 {
2315 #ifdef UNITTESTS
2316 #if 0
2317  UtRegisterTest("SCReputationTestIPV4AddRemoveHost01",
2318  SCReputationTestIPV4AddRemoveHost01);
2319  UtRegisterTest("SCReputationTestIPV6AddRemoveHost01",
2320  SCReputationTestIPV6AddRemoveHost01);
2321 
2322  UtRegisterTest("SCReputationTestIPV4BestExactMatch01",
2323  SCReputationTestIPV4BestExactMatch01);
2324 
2325  UtRegisterTest("SCReputationTestIPV4AddRemoveHost02",
2326  SCReputationTestIPV4AddRemoveHost02);
2327  UtRegisterTest("SCReputationTestIPV6AddRemoveHost02",
2328  SCReputationTestIPV6AddRemoveHost02);
2329 
2330  UtRegisterTest("SCReputationTestIPV4Update01",
2331  SCReputationTestIPV4Update01);
2332  UtRegisterTest("SCReputationTestIPV6Update01",
2333  SCReputationTestIPV6Update01);
2334 #endif
2335  UtRegisterTest("SRepTest01", SRepTest01);
2336  UtRegisterTest("SRepTest02", SRepTest02);
2337  UtRegisterTest("SRepTest03", SRepTest03);
2338  UtRegisterTest("SRepTest04", SRepTest04);
2339  UtRegisterTest("SRepTest05", SRepTest05);
2340  UtRegisterTest("SRepTest06", SRepTest06);
2341  UtRegisterTest("SRepTest07", SRepTest07);
2342 #endif /* UNITTESTS */
2343 }
2344 
void HostPrintStats(void)
print some host stats
Definition: host.c:287
int SRepInit(DetectEngineCtx *de_ctx)
init reputation
Definition: reputation.c:579
#define GET_IPV4_SRC_ADDR_PTR(p)
Definition: decode.h:213
void HostRelease(Host *h)
Definition: host.c:475
int PathIsRelative(const char *path)
Check if a path is relative.
Definition: util-path.c:64
#define REPUTATION_FLAG_NEEDSYNC
Definition: reputation.h:75
#define SCLogDebug(...)
Definition: util-debug.h:335
#define SCMutexDestroy(x)
SCRadixTree * reputationIPV4_tree
Definition: reputation.h:80
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:350
struct HtpBodyChunk_ * next
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
#define BUG_ON(x)
void SCReputationRegisterTests(void)
Definition: reputation.c:2313
void MaskIPNetblock(uint8_t *stream, int netmask, int key_bitlen)
Culls the non-netmask portion of the IP address. For example an IP address 192.168.240.1 would be chopped to 192.168.224.0 against a netmask value of 19.
Definition: util-ip.c:187
void SRepDestroy(DetectEngineCtx *de_ctx)
Definition: reputation.c:662
#define unlikely(expr)
Definition: util-optimize.h:35
#define GET_IPV4_DST_ADDR_PTR(p)
Definition: decode.h:214
uint32_t UTHSetIPv4Address(const char *str)
return the uint32_t for a ipv4 address string
uint8_t SRepCIDRGetIPRepSrc(SRepCIDRTree *cidr_ctx, Packet *p, uint8_t cat, uint32_t version)
Definition: reputation.c:146
union Address_::@48 address
size_t strlcat(char *, const char *src, size_t siz)
Definition: util-strlcatu.c:45
SCRadixTree * srepIPV4_tree[SREP_MAX_CATS]
Definition: reputation.h:34
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:108
#define PKT_IS_IPV6(p)
Definition: decode.h:251
#define SREP_MAX_CATS
Definition: reputation.h:31
SCRadixNode * SCRadixFindKeyIPV4ExactMatch(uint8_t *key_stream, SCRadixTree *tree, void **user_data_result)
Checks if an IPV4 address is present in the tree.
uint32_t srep_version
Definition: detect.h:730
SCRadixNode * SCRadixFindKeyIPV6BestMatch(uint8_t *key_stream, SCRadixTree *tree, void **user_data_result)
Checks if an IPV6 address is present in the tree under a netblock.
void SCRadixPrintTree(SCRadixTree *tree)
Prints the Radix Tree. While printing the radix tree we use the following format. ...
SCRadixTree * SCRadixCreateRadixTree(void(*Free)(void *), void(*PrintData)(void *))
Creates a new Radix tree.
char * val
Definition: conf.h:34
#define PKT_IS_IPV4(p)
Definition: decode.h:250
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:331
int SRepHostTimedOut(Host *h)
Check if a Host is timed out wrt ip rep, meaning a new version is in place.
Definition: reputation.c:196
#define REPUTATION_MALWARE
Definition: reputation.h:63
main detection engine ctx
Definition: detect.h:720
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition: util-debug.c:631
#define SREP_SHORTNAME_LEN
Definition: reputation.c:337
SCRadixNode * SCRadixAddKeyIPV6String(const char *str, SCRadixTree *tree, void *user)
Adds a new IPV6/netblock to the Radix tree from a string.
SCRadixTree * srepIPV6_tree[SREP_MAX_CATS]
Definition: reputation.h:35
SCRadixNode * SCRadixAddKeyIPV4Netblock(uint8_t *key_stream, SCRadixTree *tree, void *user, uint8_t netmask)
Adds a new IPV4 netblock to the Radix tree.
#define SC_ATOMIC_INIT(name)
Initialize the previously declared atomic variable and it&#39;s lock.
Definition: util-atomic.h:82
void SCRadixReleaseRadixTree(SCRadixTree *tree)
Frees a Radix tree and all its nodes.
#define str(s)
#define SCMutexUnlock(mut)
uint8_t rep[SREP_MAX_CATS]
Definition: reputation.h:40
char family
Definition: decode.h:110
#define SCMutexInit(mut, mutattr)
#define GET_IPV6_DST_ADDR(p)
Definition: decode.h:219
SCRadixTree * reputationIPV6_tree
Definition: reputation.h:81
SCRadixNode * SCRadixAddKeyIPV4(uint8_t *key_stream, SCRadixTree *tree, void *user)
Adds a new IPV4 address to the Radix tree.
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
int SRepLoadFileFromFD(SRepCIDRTree *cidr_ctx, FILE *fp)
Definition: reputation.c:435
#define HostIncrUsecnt(h)
Definition: host.h:112
uint32_t version
Definition: reputation.h:39
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
SCRadixNode * SCRadixAddKeyIPV4String(const char *str, SCRadixTree *tree, void *user)
Adds a new IPV4/netblock to the Radix tree from a string.
const char * PrintInet(int af, const void *src, char *dst, socklen_t size)
Definition: util-print.c:267
Host * HostGetHostFromHash(Address *a)
Definition: host.c:500
#define HostDecrUsecnt(h)
Definition: host.h:114
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
int SRepLoadCatFileFromFD(FILE *fp)
Definition: reputation.c:368
SCRadixNode * SCRadixFindKeyIPV4BestMatch(uint8_t *key_stream, SCRadixTree *tree, void **user_data_result)
Checks if an IPV4 address is present in the tree under a netblock.
Definition: conf.h:32
#define SCMalloc(a)
Definition: util-mem.h:174
#define GET_IPV6_SRC_ADDR(p)
Definition: decode.h:218
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
Definition: util-atomic.h:208
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
void * iprep
Definition: host.h:69
uint8_t version
Definition: decode-gre.h:405
#define SCFree(a)
Definition: util-mem.h:236
Definition: host.h:58
void SRepReloadComplete(void)
Increment effective reputation version after a rule/reputatio reload is complete. ...
Definition: reputation.c:172
SCRadixNode * SCRadixFindKeyIPV6ExactMatch(uint8_t *key_stream, SCRadixTree *tree, void **user_data_result)
Checks if an IPV6 address is present in the tree.
SRepCIDRTree * srepCIDR_ctx
Definition: detect.h:733
int failure_fatal
Definition: detect.h:722
#define REPUTATION_DDOS
Definition: reputation.h:61
#define SCMutexLock(mut)
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself...
#define REPUTATION_PHISH
Definition: reputation.h:62
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:193
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:176
SCMutex reputationIPV6_lock
Definition: reputation.h:85
#define SCStrdup(a)
Definition: util-mem.h:220
#define REPUTATION_NUMBER
Definition: reputation.h:71
SCRadixNode * SCRadixAddKeyIPV6Netblock(uint8_t *key_stream, SCRadixTree *tree, void *user, uint8_t netmask)
Adds a new IPV6 netblock to the Radix tree.
SCMutex reputationIPV4_lock
Definition: reputation.h:84
uint8_t SRepCIDRGetIPRepDst(SRepCIDRTree *cidr_ctx, Packet *p, uint8_t cat, uint32_t version)
Definition: reputation.c:158
void SCRadixRemoveKeyIPV6Netblock(uint8_t *key_stream, SCRadixTree *tree, uint8_t netmask)
Removes an IPV6 netblock address key from the Radix tree.
SCRadixNode * SCRadixAddKeyIPV6(uint8_t *key_stream, SCRadixTree *tree, void *user)
Adds a new IPV6 address to the Radix tree.
uint8_t SRepCatGetByShortname(char *shortname)
Definition: reputation.c:340
SC_ATOMIC_DECLARE(uint32_t, srep_eversion)
void SCRadixRemoveKeyIPV4Netblock(uint8_t *key_stream, SCRadixTree *tree, uint8_t netmask)
Removes an IPV4 address netblock key from the Radix tree.
uint8_t len
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
void SRepResetVersion(void)
Definition: reputation.c:60
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Address src
Definition: decode.h:411
DetectEngineCtx * DetectEngineCtxInit(void)