suricata
datasets.c
Go to the documentation of this file.
1 /* Copyright (C) 2017-2024 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  */
23 
24 #include "suricata-common.h"
25 #include "suricata.h"
26 #include "rust.h"
27 #include "conf.h"
28 #include "datasets.h"
29 #include "datasets-string.h"
30 #include "datasets-ipv4.h"
31 #include "datasets-ipv6.h"
32 #include "datasets-md5.h"
33 #include "datasets-sha256.h"
34 #include "datasets-reputation.h"
35 #include "datasets-context-json.h"
36 #include "util-conf.h"
37 #include "util-thash.h"
38 #include "util-print.h"
39 #include "util-byte.h"
40 #include "util-misc.h"
41 #include "util-path.h"
42 #include "util-debug.h"
43 #include "util-validate.h"
44 
46 static Dataset *sets = NULL;
47 static uint32_t set_ids = 0;
48 
49 uint32_t dataset_max_one_hashsize = 65536;
50 uint32_t dataset_max_total_hashsize = 16777216;
51 uint32_t dataset_used_hashsize = 0;
52 
53 int DatasetAddwRep(Dataset *set, const uint8_t *data, const uint32_t data_len, DataRepType *rep);
54 static void DatasetUpdateHashsize(const char *name, uint32_t hash_size);
55 
56 static inline void DatasetUnlockData(THashData *d)
57 {
58  (void) THashDecrUsecnt(d);
59  THashDataUnlock(d);
60 }
61 static bool DatasetIsStatic(const char *save, const char *load);
62 
63 enum DatasetTypes DatasetGetTypeFromString(const char *s)
64 {
65  if (strcasecmp("md5", s) == 0)
66  return DATASET_TYPE_MD5;
67  if (strcasecmp("sha256", s) == 0)
68  return DATASET_TYPE_SHA256;
69  if (strcasecmp("string", s) == 0)
70  return DATASET_TYPE_STRING;
71  if (strcasecmp("ipv4", s) == 0)
72  return DATASET_TYPE_IPV4;
73  if (strcasecmp("ip", s) == 0)
74  return DATASET_TYPE_IPV6;
75  return DATASET_TYPE_NOTSET;
76 }
77 
79 {
80 
81  if (set->hash == NULL) {
82  return -1;
83  }
84 
85  if (SC_ATOMIC_GET(set->hash->memcap_reached)) {
86  SCLogError("dataset too large for set memcap");
87  return -1;
88  }
89 
90  SCLogDebug(
91  "set %p/%s type %u save %s load %s", set, set->name, set->type, set->save, set->load);
92 
93  set->next = sets;
94  sets = set;
95 
96  /* hash size accounting */
97  DatasetUpdateHashsize(set->name, set->hash->config.hash_size);
98  return 0;
99 }
100 
101 void DatasetLock(void)
102 {
104 }
105 
106 void DatasetUnlock(void)
107 {
109 }
110 
111 Dataset *DatasetAlloc(const char *name)
112 {
113  Dataset *set = SCCalloc(1, sizeof(*set));
114  if (set) {
115  set->id = set_ids++;
116  }
117  return set;
118 }
119 
121 {
122  Dataset *set = sets;
123  while (set) {
124  if (strcasecmp(name, set->name) == 0 && !set->hidden) {
125  return set;
126  }
127  set = set->next;
128  }
129  return NULL;
130 }
131 
132 static int DatasetLoadIPv4(Dataset *set)
133 {
134  if (strlen(set->load) == 0)
135  return 0;
136 
137  SCLogConfig("dataset: %s loading from '%s'", set->name, set->load);
138  const char *fopen_mode = "r";
139  if (strlen(set->save) > 0 && strcmp(set->save, set->load) == 0) {
140  fopen_mode = "a+";
141  }
142 
143  int retval = ParseDatasets(set, set->name, set->load, fopen_mode, DSIpv4);
144  if (retval == -2) {
145  FatalErrorOnInit("dataset %s could not be processed", set->name);
146  } else if (retval == -1) {
147  return -1;
148  }
149 
151 
152  return 0;
153 }
154 
155 int DatasetParseIpv6String(Dataset *set, const char *line, struct in6_addr *in6)
156 {
157  /* Checking IPv6 case */
158  const char *got_colon = strchr(line, ':');
159  if (got_colon) {
160  uint32_t ip6addr[4];
161  if (inet_pton(AF_INET6, line, in6) != 1) {
162  FatalErrorOnInit("dataset data parse failed %s/%s: %s", set->name, set->load, line);
163  return -1;
164  }
165  memcpy(&ip6addr, in6->s6_addr, sizeof(ip6addr));
166  /* IPv4 in IPv6 notation needs transformation to internal Suricata storage */
167  if (ip6addr[0] == 0 && ip6addr[1] == 0 && ip6addr[2] == 0xFFFF0000) {
168  ip6addr[0] = ip6addr[3];
169  ip6addr[2] = 0;
170  ip6addr[3] = 0;
171  memcpy(in6, ip6addr, sizeof(struct in6_addr));
172  }
173  } else {
174  /* IPv4 case */
175  struct in_addr in;
176  if (inet_pton(AF_INET, line, &in) != 1) {
177  FatalErrorOnInit("dataset data parse failed %s/%s: %s", set->name, set->load, line);
178  return -1;
179  }
180  memset(in6, 0, sizeof(struct in6_addr));
181  memcpy(in6, &in, sizeof(struct in_addr));
182  }
183  return 0;
184 }
185 
186 static int DatasetLoadIPv6(Dataset *set)
187 {
188  if (strlen(set->load) == 0)
189  return 0;
190 
191  SCLogConfig("dataset: %s loading from '%s'", set->name, set->load);
192  const char *fopen_mode = "r";
193  if (strlen(set->save) > 0 && strcmp(set->save, set->load) == 0) {
194  fopen_mode = "a+";
195  }
196 
197  int retval = ParseDatasets(set, set->name, set->load, fopen_mode, DSIpv6);
198  if (retval == -2) {
199  FatalErrorOnInit("dataset %s could not be processed", set->name);
200  } else if (retval == -1) {
201  return -1;
202  }
203 
205 
206  return 0;
207 }
208 
209 static int DatasetLoadMd5(Dataset *set)
210 {
211  if (strlen(set->load) == 0)
212  return 0;
213 
214  SCLogConfig("dataset: %s loading from '%s'", set->name, set->load);
215  const char *fopen_mode = "r";
216  if (strlen(set->save) > 0 && strcmp(set->save, set->load) == 0) {
217  fopen_mode = "a+";
218  }
219 
220  int retval = ParseDatasets(set, set->name, set->load, fopen_mode, DSMd5);
221  if (retval == -2) {
222  FatalErrorOnInit("dataset %s could not be processed", set->name);
223  } else if (retval == -1) {
224  return -1;
225  }
226 
228 
229  return 0;
230 }
231 
232 static int DatasetLoadSha256(Dataset *set)
233 {
234  if (strlen(set->load) == 0)
235  return 0;
236 
237  SCLogConfig("dataset: %s loading from '%s'", set->name, set->load);
238  const char *fopen_mode = "r";
239  if (strlen(set->save) > 0 && strcmp(set->save, set->load) == 0) {
240  fopen_mode = "a+";
241  }
242 
243  int retval = ParseDatasets(set, set->name, set->load, fopen_mode, DSSha256);
244  if (retval == -2) {
245  FatalErrorOnInit("dataset %s could not be processed", set->name);
246  } else if (retval == -1) {
247  return -1;
248  }
249 
251 
252  return 0;
253 }
254 
255 static int DatasetLoadString(Dataset *set)
256 {
257  if (strlen(set->load) == 0)
258  return 0;
259 
260  SCLogConfig("dataset: %s loading from '%s'", set->name, set->load);
261 
262  const char *fopen_mode = "r";
263  if (strlen(set->save) > 0 && strcmp(set->save, set->load) == 0) {
264  fopen_mode = "a+";
265  }
266 
267  int retval = ParseDatasets(set, set->name, set->load, fopen_mode, DSString);
268  if (retval == -2) {
269  FatalErrorOnInit("dataset %s could not be processed", set->name);
270  } else if (retval == -1) {
271  return -1;
272  }
273 
275 
276  return 0;
277 }
278 
279 extern bool g_system;
280 
284 };
285 
286 static void DatasetGetPath(
287  const char *in_path, char *out_path, size_t out_size, enum DatasetGetPathType type)
288 {
289  char path[PATH_MAX];
290  struct stat st;
291 
292  if (PathIsAbsolute(in_path)) {
293  strlcpy(path, in_path, sizeof(path));
294  strlcpy(out_path, path, out_size);
295  return;
296  }
297 
298  const char *data_dir = ConfigGetDataDirectory();
299  if (stat(data_dir, &st) != 0) {
300  SCLogDebug("data-dir '%s': %s", data_dir, strerror(errno));
301  return;
302  }
303 
304  snprintf(path, sizeof(path), "%s/%s", data_dir, in_path); // TODO WINDOWS
305 
306  if (type == TYPE_LOAD) {
307  if (stat(path, &st) != 0) {
308  SCLogDebug("path %s: %s", path, strerror(errno));
309  if (!g_system) {
310  snprintf(path, sizeof(path), "%s", in_path);
311  }
312  }
313  }
314  strlcpy(out_path, path, out_size);
315  SCLogDebug("in_path \'%s\' => \'%s\'", in_path, out_path);
316 }
317 
318 /** \brief look for set by name without creating it */
320 {
321  DatasetLock();
323  if (set) {
324  if (set->type != type) {
325  DatasetUnlock();
326  return NULL;
327  }
328  }
329  DatasetUnlock();
330  return set;
331 }
332 
333 static bool DatasetCheckHashsize(const char *name, uint32_t hash_size)
334 {
335  if (dataset_max_one_hashsize > 0 && hash_size > dataset_max_one_hashsize) {
336  SCLogError("hashsize %u in dataset '%s' exceeds configured 'single-hashsize' limit (%u)",
337  hash_size, name, dataset_max_one_hashsize);
338  return false;
339  }
340  // we cannot underflow as we know from conf loading that
341  // dataset_max_total_hashsize >= dataset_max_one_hashsize if dataset_max_total_hashsize > 0
342  if (dataset_max_total_hashsize > 0 &&
344  SCLogError("hashsize %u in dataset '%s' exceeds configured 'total-hashsizes' limit (%u, in "
345  "use %u)",
347  return false;
348  }
349 
350  return true;
351 }
352 
353 static void DatasetUpdateHashsize(const char *name, uint32_t hash_size)
354 {
355  if (dataset_max_total_hashsize > 0) {
356  dataset_used_hashsize += hash_size;
357  SCLogDebug("set %s adding with hash_size %u", name, hash_size);
358  }
359 }
360 
361 /**
362  * \return -1 on error
363  * \return 0 on successful creation
364  * \return 1 if the dataset already exists
365  *
366  * Calling function is responsible for locking via DatasetLock()
367  */
368 int DatasetGetOrCreate(const char *name, enum DatasetTypes type, const char *save, const char *load,
369  uint64_t *memcap, uint32_t *hashsize, Dataset **ret_set)
370 {
371  uint64_t default_memcap = 0;
372  uint32_t default_hashsize = 0;
373  if (strlen(name) > DATASET_NAME_MAX_LEN) {
374  return -1;
375  }
376 
378  if (set) {
379  if (type != DATASET_TYPE_NOTSET && set->type != type) {
380  SCLogError("dataset %s already "
381  "exists and is of type %u",
382  set->name, set->type);
383  return -1;
384  }
385 
386  if ((save == NULL || strlen(save) == 0) &&
387  (load == NULL || strlen(load) == 0)) {
388  // OK, rule keyword doesn't have to set state/load,
389  // even when yaml set has set it.
390  } else {
391  if ((save == NULL && strlen(set->save) > 0) ||
392  (save != NULL && strcmp(set->save, save) != 0)) {
393  SCLogError("dataset %s save mismatch: %s != %s", set->name, set->save, save);
394  DatasetUnlock();
395  return -1;
396  }
397  if ((load == NULL && strlen(set->load) > 0) ||
398  (load != NULL && strcmp(set->load, load) != 0)) {
399  SCLogError("dataset %s load mismatch: %s != %s", set->name, set->load, load);
400  return -1;
401  }
402  }
403 
404  *ret_set = set;
405  return 1;
406  }
407 
408  if (type == DATASET_TYPE_NOTSET) {
409  SCLogError("dataset %s not defined", name);
410  goto out_err;
411  }
412 
413  DatasetGetDefaultMemcap(&default_memcap, &default_hashsize);
414  if (*hashsize == 0) {
415  *hashsize = default_hashsize;
416  }
417  if (*memcap == 0) {
418  *memcap = default_memcap;
419  }
420 
421  if (!DatasetCheckHashsize(name, *hashsize)) {
422  goto out_err;
423  }
424 
425  set = DatasetAlloc(name);
426  if (set == NULL) {
427  goto out_err;
428  }
429 
430  strlcpy(set->name, name, sizeof(set->name));
431  set->type = type;
432  if (save && strlen(save)) {
433  strlcpy(set->save, save, sizeof(set->save));
434  SCLogDebug("name %s save '%s'", name, set->save);
435  }
436  if (load && strlen(load)) {
437  strlcpy(set->load, load, sizeof(set->load));
438  SCLogDebug("set \'%s\' loading \'%s\' from \'%s\'", set->name, load, set->load);
439  }
440 
441  *ret_set = set;
442  return 0;
443 out_err:
444  if (set) {
445  SCFree(set);
446  }
447  return -1;
448 }
449 
450 Dataset *DatasetGet(const char *name, enum DatasetTypes type, const char *save, const char *load,
451  uint64_t memcap, uint32_t hashsize)
452 {
453  Dataset *set = NULL;
454 
455  DatasetLock();
456  int ret = DatasetGetOrCreate(name, type, save, load, &memcap, &hashsize, &set);
457  if (ret < 0) {
458  SCLogError("dataset %s creation failed", name);
459  DatasetUnlock();
460  return NULL;
461  }
462  if (ret == 1) {
463  SCLogDebug("dataset %s already exists", name);
464  DatasetUnlock();
465  return set;
466  }
467 
468  char cnf_name[128];
469  snprintf(cnf_name, sizeof(cnf_name), "datasets.%s.hash", name);
470  switch (type) {
471  case DATASET_TYPE_MD5:
472  set->hash = THashInit(cnf_name, sizeof(Md5Type), Md5StrSet, Md5StrFree, Md5StrHash,
473  Md5StrCompare, NULL, NULL, load != NULL ? 1 : 0, memcap, hashsize);
474  if (set->hash == NULL)
475  goto out_err;
476  if (DatasetLoadMd5(set) < 0)
477  goto out_err;
478  break;
479  case DATASET_TYPE_STRING:
480  set->hash = THashInit(cnf_name, sizeof(StringType), StringSet, StringFree, StringHash,
481  StringCompare, NULL, StringGetLength, load != NULL ? 1 : 0, memcap, hashsize);
482  if (set->hash == NULL)
483  goto out_err;
484  if (DatasetLoadString(set) < 0)
485  goto out_err;
486  break;
487  case DATASET_TYPE_SHA256:
488  set->hash = THashInit(cnf_name, sizeof(Sha256Type), Sha256StrSet, Sha256StrFree,
489  Sha256StrHash, Sha256StrCompare, NULL, NULL, load != NULL ? 1 : 0, memcap,
490  hashsize);
491  if (set->hash == NULL)
492  goto out_err;
493  if (DatasetLoadSha256(set) < 0)
494  goto out_err;
495  break;
496  case DATASET_TYPE_IPV4:
497  set->hash = THashInit(cnf_name, sizeof(IPv4Type), IPv4Set, IPv4Free, IPv4Hash,
498  IPv4Compare, NULL, NULL, load != NULL ? 1 : 0, memcap, hashsize);
499  if (set->hash == NULL)
500  goto out_err;
501  if (DatasetLoadIPv4(set) < 0)
502  goto out_err;
503  break;
504  case DATASET_TYPE_IPV6:
505  set->hash = THashInit(cnf_name, sizeof(IPv6Type), IPv6Set, IPv6Free, IPv6Hash,
506  IPv6Compare, NULL, NULL, load != NULL ? 1 : 0, memcap, hashsize);
507  if (set->hash == NULL)
508  goto out_err;
509  if (DatasetLoadIPv6(set) < 0)
510  goto out_err;
511  break;
512  }
513 
514  if (DatasetAppendSet(set) < 0) {
515  SCLogError("dataset %s append failed", name);
516  goto out_err;
517  }
518 
519  DatasetUnlock();
520  return set;
521 out_err:
522  if (set->hash) {
523  THashShutdown(set->hash);
524  }
525  SCFree(set);
526  DatasetUnlock();
527  return NULL;
528 }
529 
530 static bool DatasetIsStatic(const char *save, const char *load)
531 {
532  /* A set is static if it does not have any dynamic properties like
533  * save and/or state defined but has load defined.
534  * */
535  return (load != NULL && strlen(load) > 0) && (save == NULL || strlen(save) == 0);
536 }
537 
538 void DatasetReload(void)
539 {
540  /* In order to reload the datasets, just mark the current sets as hidden
541  * and clean them up later.
542  * New datasets shall be created with the rule reload and do not require
543  * any intervention.
544  * */
545  DatasetLock();
546  Dataset *set = sets;
547  while (set) {
548  if (!DatasetIsStatic(set->save, set->load) || set->from_yaml) {
549  SCLogDebug("Not a static set, skipping %s", set->name);
550  set = set->next;
551  continue;
552  }
553  set->hidden = true;
554  if (dataset_max_total_hashsize > 0) {
557  }
558  SCLogDebug("Set %s at %p hidden successfully", set->name, set);
559  set = set->next;
560  }
561  DatasetUnlock();
562 }
563 
565 {
566  DatasetLock();
567  SCLogDebug("Post Reload Cleanup starting.. Hidden sets will be removed");
568  Dataset *cur = sets;
569  Dataset *prev = NULL;
570  while (cur) {
571  Dataset *next = cur->next;
572  if (!cur->hidden) {
573  prev = cur;
574  cur = next;
575  continue;
576  }
577  // Delete the set in case it was hidden
578  if (prev != NULL) {
579  prev->next = next;
580  } else {
581  sets = next;
582  }
583  THashShutdown(cur->hash);
584  SCFree(cur);
585  cur = next;
586  }
587  DatasetUnlock();
588 }
589 
590 /* Value reflects THASH_DEFAULT_HASHSIZE which is what the default was earlier,
591  * despite 2048 commented out in the default yaml. */
592 #define DATASETS_HASHSIZE_DEFAULT 4096
593 
594 void DatasetGetDefaultMemcap(uint64_t *memcap, uint32_t *hashsize)
595 {
596  const char *str = NULL;
597  if (SCConfGetNonNull("datasets.defaults.memcap", &str) == 1) {
598  if (ParseSizeStringU64(str, memcap) < 0) {
599  SCLogWarning("memcap value cannot be deduced: %s,"
600  " resetting to default",
601  str);
602  *memcap = 0;
603  }
604  }
605 
606  *hashsize = (uint32_t)DATASETS_HASHSIZE_DEFAULT;
607  if (SCConfGetNonNull("datasets.defaults.hashsize", &str) == 1) {
608  if (ParseSizeStringU32(str, hashsize) < 0) {
609  *hashsize = (uint32_t)DATASETS_HASHSIZE_DEFAULT;
610  SCLogWarning("hashsize value cannot be deduced: %s,"
611  " resetting to default: %u",
612  str, *hashsize);
613  }
614  }
615 }
616 
617 int DatasetsInit(void)
618 {
619  SCLogDebug("datasets start");
620  SCConfNode *datasets = SCConfGetNode("datasets");
621  uint64_t default_memcap = 0;
622  uint32_t default_hashsize = 0;
623  DatasetGetDefaultMemcap(&default_memcap, &default_hashsize);
624  if (datasets != NULL) {
625  const char *str = NULL;
626  if (SCConfGetNonNull("datasets.limits.total-hashsizes", &str) == 1) {
628  FatalError("failed to parse datasets.limits.total-hashsizes value: %s", str);
629  }
630  }
631  if (SCConfGetNonNull("datasets.limits.single-hashsize", &str) == 1) {
633  FatalError("failed to parse datasets.limits.single-hashsize value: %s", str);
634  }
635  }
636  if (dataset_max_total_hashsize > 0 &&
638  FatalError("total-hashsizes (%u) cannot be smaller than single-hashsize (%u)",
640  }
642  // the total limit also applies for single limit
644  }
645 
646  int list_pos = 0;
647  SCConfNode *iter = NULL;
648  TAILQ_FOREACH(iter, &datasets->head, next) {
649  if (iter->name == NULL) {
650  list_pos++;
651  continue;
652  }
653 
654  char save[PATH_MAX] = "";
655  char load[PATH_MAX] = "";
656  uint64_t memcap = 0;
657  uint32_t hashsize = 0;
658 
659  const char *set_name = iter->name;
660  if (strlen(set_name) > DATASET_NAME_MAX_LEN) {
662  "set name '%s' too long, max %d chars", set_name, DATASET_NAME_MAX_LEN);
663  continue;
664  }
665 
666  SCConfNode *set_type = SCConfNodeLookupChild(iter, "type");
667  if (set_type == NULL) {
668  list_pos++;
669  continue;
670  }
671 
672  SCConfNode *set_save = SCConfNodeLookupChild(iter, "state");
673  if (set_save) {
674  DatasetGetPath(set_save->val, save, sizeof(save), TYPE_STATE);
675  strlcpy(load, save, sizeof(load));
676  } else {
677  SCConfNode *set_load = SCConfNodeLookupChild(iter, "load");
678  if (set_load) {
679  DatasetGetPath(set_load->val, load, sizeof(load), TYPE_LOAD);
680  }
681  }
682 
683  SCConfNode *set_memcap = SCConfNodeLookupChild(iter, "memcap");
684  if (set_memcap) {
685  if (ParseSizeStringU64(set_memcap->val, &memcap) < 0) {
686  SCLogWarning("memcap value cannot be"
687  " deduced: %s, resetting to default",
688  set_memcap->val);
689  memcap = 0;
690  }
691  }
692  SCConfNode *set_hashsize = SCConfNodeLookupChild(iter, "hashsize");
693  if (set_hashsize) {
694  if (ParseSizeStringU32(set_hashsize->val, &hashsize) < 0) {
695  SCLogWarning("hashsize value cannot be"
696  " deduced: %s, resetting to default",
697  set_hashsize->val);
698  hashsize = 0;
699  }
700  }
701  char conf_str[1024];
702  snprintf(conf_str, sizeof(conf_str), "datasets.%d.%s", list_pos, set_name);
703 
704  SCLogDebug("set %s type %s. Conf %s", set_name, set_type->val, conf_str);
705 
706  if (strcmp(set_type->val, "md5") == 0) {
707  Dataset *dset = DatasetGet(set_name, DATASET_TYPE_MD5, save, load,
708  memcap > 0 ? memcap : default_memcap,
709  hashsize > 0 ? hashsize : default_hashsize);
710  if (dset == NULL) {
711  FatalErrorOnInit("failed to setup dataset for %s", set_name);
712  continue;
713  }
714  SCLogDebug("dataset %s: id %u type %s", set_name, dset->id, set_type->val);
715  dset->from_yaml = true;
716 
717  } else if (strcmp(set_type->val, "sha256") == 0) {
718  Dataset *dset = DatasetGet(set_name, DATASET_TYPE_SHA256, save, load,
719  memcap > 0 ? memcap : default_memcap,
720  hashsize > 0 ? hashsize : default_hashsize);
721  if (dset == NULL) {
722  FatalErrorOnInit("failed to setup dataset for %s", set_name);
723  continue;
724  }
725  SCLogDebug("dataset %s: id %u type %s", set_name, dset->id, set_type->val);
726  dset->from_yaml = true;
727 
728  } else if (strcmp(set_type->val, "string") == 0) {
729  Dataset *dset = DatasetGet(set_name, DATASET_TYPE_STRING, save, load,
730  memcap > 0 ? memcap : default_memcap,
731  hashsize > 0 ? hashsize : default_hashsize);
732  if (dset == NULL) {
733  FatalErrorOnInit("failed to setup dataset for %s", set_name);
734  continue;
735  }
736  SCLogDebug("dataset %s: id %u type %s", set_name, dset->id, set_type->val);
737  dset->from_yaml = true;
738 
739  } else if (strcmp(set_type->val, "ipv4") == 0) {
740  Dataset *dset = DatasetGet(set_name, DATASET_TYPE_IPV4, save, load,
741  memcap > 0 ? memcap : default_memcap,
742  hashsize > 0 ? hashsize : default_hashsize);
743  if (dset == NULL) {
744  FatalErrorOnInit("failed to setup dataset for %s", set_name);
745  continue;
746  }
747  SCLogDebug("dataset %s: id %u type %s", set_name, dset->id, set_type->val);
748  dset->from_yaml = true;
749 
750  } else if (strcmp(set_type->val, "ip") == 0) {
751  Dataset *dset = DatasetGet(set_name, DATASET_TYPE_IPV6, save, load,
752  memcap > 0 ? memcap : default_memcap,
753  hashsize > 0 ? hashsize : default_hashsize);
754  if (dset == NULL) {
755  FatalErrorOnInit("failed to setup dataset for %s", set_name);
756  continue;
757  }
758  SCLogDebug("dataset %s: id %u type %s", set_name, dset->id, set_type->val);
759  dset->from_yaml = true;
760  }
761 
762  list_pos++;
763  }
764  }
765  SCLogDebug("datasets done: %p", datasets);
766  return 0;
767 }
768 
769 void DatasetsDestroy(void)
770 {
771  DatasetLock();
772  SCLogDebug("destroying datasets: %p", sets);
773  Dataset *set = sets;
774  while (set) {
775  SCLogDebug("destroying set %s", set->name);
776  Dataset *next = set->next;
777  THashShutdown(set->hash);
778  SCFree(set);
779  set = next;
780  }
781  sets = NULL;
782  // these resets are useful for stateless fuzzing
784  set_ids = 0;
785  DatasetUnlock();
786  SCLogDebug("destroying datasets done: %p", sets);
787 }
788 
789 static int SaveCallback(void *ctx, const uint8_t *data, const uint32_t data_len)
790 {
791  FILE *fp = ctx;
792  //PrintRawDataFp(fp, data, data_len);
793  if (fp) {
794  return (int)fwrite(data, data_len, 1, fp);
795  }
796  return 0;
797 }
798 
799 static int Md5AsAscii(const void *s, char *out, size_t out_size)
800 {
801  const Md5Type *md5 = s;
802  char str[256];
803  PrintHexString(str, sizeof(str), (uint8_t *)md5->md5, sizeof(md5->md5));
804  strlcat(out, str, out_size);
805  strlcat(out, "\n", out_size);
806  return (int)strlen(out);
807 }
808 
809 static int Sha256AsAscii(const void *s, char *out, size_t out_size)
810 {
811  const Sha256Type *sha = s;
812  char str[256];
813  PrintHexString(str, sizeof(str), (uint8_t *)sha->sha256, sizeof(sha->sha256));
814  strlcat(out, str, out_size);
815  strlcat(out, "\n", out_size);
816  return (int)strlen(out);
817 }
818 
819 static int IPv4AsAscii(const void *s, char *out, size_t out_size)
820 {
821  const IPv4Type *ip4 = s;
822  char str[256];
823  PrintInet(AF_INET, ip4->ipv4, str, sizeof(str));
824  strlcat(out, str, out_size);
825  strlcat(out, "\n", out_size);
826  return (int)strlen(out);
827 }
828 
829 static int IPv6AsAscii(const void *s, char *out, size_t out_size)
830 {
831  const IPv6Type *ip6 = s;
832  char str[256];
833  bool is_ipv4 = true;
834  for (int i = 4; i <= 15; i++) {
835  if (ip6->ipv6[i] != 0) {
836  is_ipv4 = false;
837  break;
838  }
839  }
840  if (is_ipv4) {
841  PrintInet(AF_INET, ip6->ipv6, str, sizeof(str));
842  } else {
843  PrintInet(AF_INET6, ip6->ipv6, str, sizeof(str));
844  }
845  strlcat(out, str, out_size);
846  strlcat(out, "\n", out_size);
847  return (int)strlen(out);
848 }
849 
850 void DatasetsSave(void)
851 {
852  DatasetLock();
853  SCLogDebug("saving datasets: %p", sets);
854  Dataset *set = sets;
855  while (set) {
856  if (strlen(set->save) == 0)
857  goto next;
858 
859  FILE *fp = fopen(set->save, "w");
860  if (fp == NULL)
861  goto next;
862 
863  SCLogDebug("dumping %s to %s", set->name, set->save);
864 
865  switch (set->type) {
866  case DATASET_TYPE_STRING:
867  THashWalk(set->hash, StringAsBase64, SaveCallback, fp);
868  break;
869  case DATASET_TYPE_MD5:
870  THashWalk(set->hash, Md5AsAscii, SaveCallback, fp);
871  break;
872  case DATASET_TYPE_SHA256:
873  THashWalk(set->hash, Sha256AsAscii, SaveCallback, fp);
874  break;
875  case DATASET_TYPE_IPV4:
876  THashWalk(set->hash, IPv4AsAscii, SaveCallback, fp);
877  break;
878  case DATASET_TYPE_IPV6:
879  THashWalk(set->hash, IPv6AsAscii, SaveCallback, fp);
880  break;
881  }
882 
883  fclose(fp);
884 
885  next:
886  set = set->next;
887  }
888  DatasetUnlock();
889 }
890 
891 static int DatasetLookupString(Dataset *set, const uint8_t *data, const uint32_t data_len)
892 {
893  if (set == NULL)
894  return -1;
895 
896  StringType lookup = { .ptr = (uint8_t *)data, .len = data_len, .rep = 0 };
897  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
898  if (rdata) {
899  DatasetUnlockData(rdata);
900  return 1;
901  }
902  return 0;
903 }
904 
905 static DataRepResultType DatasetLookupStringwRep(Dataset *set,
906  const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
907 {
908  DataRepResultType rrep = { .found = false, .rep = 0 };
909 
910  if (set == NULL)
911  return rrep;
912 
913  StringType lookup = { .ptr = (uint8_t *)data, .len = data_len, .rep = *rep };
914  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
915  if (rdata) {
916  StringType *found = rdata->data;
917  rrep.found = true;
918  rrep.rep = found->rep;
919  DatasetUnlockData(rdata);
920  return rrep;
921  }
922  return rrep;
923 }
924 
925 static int DatasetLookupIPv4(Dataset *set, const uint8_t *data, const uint32_t data_len)
926 {
927  if (set == NULL)
928  return -1;
929 
930  if (data_len != 4)
931  return -1;
932 
933  IPv4Type lookup = { .rep = 0 };
934  memcpy(lookup.ipv4, data, 4);
935  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
936  if (rdata) {
937  DatasetUnlockData(rdata);
938  return 1;
939  }
940  return 0;
941 }
942 
943 static DataRepResultType DatasetLookupIPv4wRep(
944  Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
945 {
946  DataRepResultType rrep = { .found = false, .rep = 0 };
947 
948  if (set == NULL)
949  return rrep;
950 
951  if (data_len != 4)
952  return rrep;
953 
954  IPv4Type lookup = { .rep = 0 };
955  memcpy(lookup.ipv4, data, data_len);
956  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
957  if (rdata) {
958  IPv4Type *found = rdata->data;
959  rrep.found = true;
960  rrep.rep = found->rep;
961  DatasetUnlockData(rdata);
962  return rrep;
963  }
964  return rrep;
965 }
966 
967 static int DatasetLookupIPv6(Dataset *set, const uint8_t *data, const uint32_t data_len)
968 {
969  if (set == NULL)
970  return -1;
971 
972  if (data_len != 16 && data_len != 4)
973  return -1;
974 
975  IPv6Type lookup = { .rep = 0 };
976  memcpy(lookup.ipv6, data, data_len);
977  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
978  if (rdata) {
979  DatasetUnlockData(rdata);
980  return 1;
981  }
982  return 0;
983 }
984 
985 static DataRepResultType DatasetLookupIPv6wRep(
986  Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
987 {
988  DataRepResultType rrep = { .found = false, .rep = 0 };
989 
990  if (set == NULL)
991  return rrep;
992 
993  if (data_len != 16 && data_len != 4)
994  return rrep;
995 
996  IPv6Type lookup = { .rep = 0 };
997  memcpy(lookup.ipv6, data, data_len);
998  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
999  if (rdata) {
1000  IPv6Type *found = rdata->data;
1001  rrep.found = true;
1002  rrep.rep = found->rep;
1003  DatasetUnlockData(rdata);
1004  return rrep;
1005  }
1006  return rrep;
1007 }
1008 
1009 static int DatasetLookupMd5(Dataset *set, const uint8_t *data, const uint32_t data_len)
1010 {
1011  if (set == NULL)
1012  return -1;
1013 
1014  if (data_len != 16)
1015  return -1;
1016 
1017  Md5Type lookup = { .rep = 0 };
1018  memcpy(lookup.md5, data, data_len);
1019  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1020  if (rdata) {
1021  DatasetUnlockData(rdata);
1022  return 1;
1023  }
1024  return 0;
1025 }
1026 
1027 static DataRepResultType DatasetLookupMd5wRep(Dataset *set,
1028  const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1029 {
1030  DataRepResultType rrep = { .found = false, .rep = 0 };
1031 
1032  if (set == NULL)
1033  return rrep;
1034 
1035  if (data_len != 16)
1036  return rrep;
1037 
1038  Md5Type lookup = { .rep = 0 };
1039  memcpy(lookup.md5, data, data_len);
1040  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1041  if (rdata) {
1042  Md5Type *found = rdata->data;
1043  rrep.found = true;
1044  rrep.rep = found->rep;
1045  DatasetUnlockData(rdata);
1046  return rrep;
1047  }
1048  return rrep;
1049 }
1050 
1051 static int DatasetLookupSha256(Dataset *set, const uint8_t *data, const uint32_t data_len)
1052 {
1053  if (set == NULL)
1054  return -1;
1055 
1056  if (data_len != 32)
1057  return -1;
1058 
1059  Sha256Type lookup = { .rep = 0 };
1060  memcpy(lookup.sha256, data, data_len);
1061  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1062  if (rdata) {
1063  DatasetUnlockData(rdata);
1064  return 1;
1065  }
1066  return 0;
1067 }
1068 
1069 static DataRepResultType DatasetLookupSha256wRep(Dataset *set,
1070  const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1071 {
1072  DataRepResultType rrep = { .found = false, .rep = 0 };
1073 
1074  if (set == NULL)
1075  return rrep;
1076 
1077  if (data_len != 32)
1078  return rrep;
1079 
1080  Sha256Type lookup = { .rep = 0 };
1081  memcpy(lookup.sha256, data, data_len);
1082  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1083  if (rdata) {
1084  Sha256Type *found = rdata->data;
1085  rrep.found = true;
1086  rrep.rep = found->rep;
1087  DatasetUnlockData(rdata);
1088  return rrep;
1089  }
1090  return rrep;
1091 }
1092 
1093 /**
1094  * \brief see if \a data is part of the set
1095  * \param set dataset
1096  * \param data data to look up
1097  * \param data_len length in bytes of \a data
1098  * \retval -1 error
1099  * \retval 0 not found
1100  * \retval 1 found
1101  */
1102 int DatasetLookup(Dataset *set, const uint8_t *data, const uint32_t data_len)
1103 {
1104  if (set == NULL)
1105  return -1;
1106 
1107  switch (set->type) {
1108  case DATASET_TYPE_STRING:
1109  return DatasetLookupString(set, data, data_len);
1110  case DATASET_TYPE_MD5:
1111  return DatasetLookupMd5(set, data, data_len);
1112  case DATASET_TYPE_SHA256:
1113  return DatasetLookupSha256(set, data, data_len);
1114  case DATASET_TYPE_IPV4:
1115  return DatasetLookupIPv4(set, data, data_len);
1116  case DATASET_TYPE_IPV6:
1117  return DatasetLookupIPv6(set, data, data_len);
1118  }
1119  return -1;
1120 }
1121 
1122 DataRepResultType DatasetLookupwRep(Dataset *set, const uint8_t *data, const uint32_t data_len,
1123  const DataRepType *rep)
1124 {
1125  DataRepResultType rrep = { .found = false, .rep = 0 };
1126  if (set == NULL)
1127  return rrep;
1128 
1129  switch (set->type) {
1130  case DATASET_TYPE_STRING:
1131  return DatasetLookupStringwRep(set, data, data_len, rep);
1132  case DATASET_TYPE_MD5:
1133  return DatasetLookupMd5wRep(set, data, data_len, rep);
1134  case DATASET_TYPE_SHA256:
1135  return DatasetLookupSha256wRep(set, data, data_len, rep);
1136  case DATASET_TYPE_IPV4:
1137  return DatasetLookupIPv4wRep(set, data, data_len, rep);
1138  case DATASET_TYPE_IPV6:
1139  return DatasetLookupIPv6wRep(set, data, data_len, rep);
1140  }
1141  return rrep;
1142 }
1143 
1144 /**
1145  * \retval 1 data was added to the hash
1146  * \retval 0 data was not added to the hash as it is already there
1147  * \retval -1 failed to add data to the hash
1148  */
1149 static int DatasetAddString(Dataset *set, const uint8_t *data, const uint32_t data_len)
1150 {
1151  if (set == NULL)
1152  return -1;
1153 
1154  StringType lookup = { .ptr = (uint8_t *)data, .len = data_len, .rep = 0 };
1155  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1156  if (res.data) {
1157  DatasetUnlockData(res.data);
1158  return res.is_new ? 1 : 0;
1159  }
1160  return -1;
1161 }
1162 
1163 /**
1164  * \retval 1 data was added to the hash
1165  * \retval 0 data was not added to the hash as it is already there
1166  * \retval -1 failed to add data to the hash
1167  */
1168 static int DatasetAddStringwRep(
1169  Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1170 {
1171  if (set == NULL)
1172  return -1;
1173 
1174  StringType lookup = { .ptr = (uint8_t *)data, .len = data_len,
1175  .rep = *rep };
1176  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1177  if (res.data) {
1178  DatasetUnlockData(res.data);
1179  return res.is_new ? 1 : 0;
1180  }
1181  return -1;
1182 }
1183 
1184 static int DatasetAddIPv4(Dataset *set, const uint8_t *data, const uint32_t data_len)
1185 {
1186  if (set == NULL) {
1187  return -1;
1188  }
1189 
1190  if (data_len < 4) {
1191  return -2;
1192  }
1193 
1194  IPv4Type lookup = { .rep = 0 };
1195  memcpy(lookup.ipv4, data, 4);
1196  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1197  if (res.data) {
1198  DatasetUnlockData(res.data);
1199  return res.is_new ? 1 : 0;
1200  }
1201  return -1;
1202 }
1203 
1204 static int DatasetAddIPv6(Dataset *set, const uint8_t *data, const uint32_t data_len)
1205 {
1206  if (set == NULL) {
1207  return -1;
1208  }
1209 
1210  if (data_len != 16 && data_len != 4) {
1211  return -2;
1212  }
1213 
1214  IPv6Type lookup = { .rep = 0 };
1215  memcpy(lookup.ipv6, data, data_len);
1216  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1217  if (res.data) {
1218  DatasetUnlockData(res.data);
1219  return res.is_new ? 1 : 0;
1220  }
1221  return -1;
1222 }
1223 
1224 static int DatasetAddIPv4wRep(
1225  Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1226 {
1227  if (set == NULL)
1228  return -1;
1229 
1230  if (data_len < 4)
1231  return -2;
1232 
1233  IPv4Type lookup = { .rep = *rep };
1234  memcpy(lookup.ipv4, data, 4);
1235  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1236  if (res.data) {
1237  DatasetUnlockData(res.data);
1238  return res.is_new ? 1 : 0;
1239  }
1240  return -1;
1241 }
1242 
1243 static int DatasetAddIPv6wRep(
1244  Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1245 {
1246  if (set == NULL)
1247  return -1;
1248 
1249  if (data_len != 16)
1250  return -2;
1251 
1252  IPv6Type lookup = { .rep = *rep };
1253  memcpy(lookup.ipv6, data, 16);
1254  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1255  if (res.data) {
1256  DatasetUnlockData(res.data);
1257  return res.is_new ? 1 : 0;
1258  }
1259  return -1;
1260 }
1261 
1262 static int DatasetAddMd5(Dataset *set, const uint8_t *data, const uint32_t data_len)
1263 {
1264  if (set == NULL)
1265  return -1;
1266 
1267  if (data_len != 16)
1268  return -2;
1269 
1270  Md5Type lookup = { .rep = 0 };
1271  memcpy(lookup.md5, data, 16);
1272  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1273  if (res.data) {
1274  DatasetUnlockData(res.data);
1275  return res.is_new ? 1 : 0;
1276  }
1277  return -1;
1278 }
1279 
1280 static int DatasetAddMd5wRep(
1281  Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1282 {
1283  if (set == NULL)
1284  return -1;
1285 
1286  if (data_len != 16)
1287  return -2;
1288 
1289  Md5Type lookup = { .rep = *rep };
1290  memcpy(lookup.md5, data, 16);
1291  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1292  if (res.data) {
1293  DatasetUnlockData(res.data);
1294  return res.is_new ? 1 : 0;
1295  }
1296  return -1;
1297 }
1298 
1299 static int DatasetAddSha256wRep(
1300  Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1301 {
1302  if (set == NULL)
1303  return -1;
1304 
1305  if (data_len != 32)
1306  return -2;
1307 
1308  Sha256Type lookup = { .rep = *rep };
1309  memcpy(lookup.sha256, data, 32);
1310  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1311  if (res.data) {
1312  DatasetUnlockData(res.data);
1313  return res.is_new ? 1 : 0;
1314  }
1315  return -1;
1316 }
1317 
1318 static int DatasetAddSha256(Dataset *set, const uint8_t *data, const uint32_t data_len)
1319 {
1320  if (set == NULL)
1321  return -1;
1322 
1323  if (data_len != 32)
1324  return -2;
1325 
1326  Sha256Type lookup = { .rep = 0 };
1327  memcpy(lookup.sha256, data, 32);
1328  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1329  if (res.data) {
1330  DatasetUnlockData(res.data);
1331  return res.is_new ? 1 : 0;
1332  }
1333  return -1;
1334 }
1335 
1336 int SCDatasetAdd(Dataset *set, const uint8_t *data, const uint32_t data_len)
1337 {
1338  if (set == NULL)
1339  return -1;
1340 
1341  switch (set->type) {
1342  case DATASET_TYPE_STRING:
1343  return DatasetAddString(set, data, data_len);
1344  case DATASET_TYPE_MD5:
1345  return DatasetAddMd5(set, data, data_len);
1346  case DATASET_TYPE_SHA256:
1347  return DatasetAddSha256(set, data, data_len);
1348  case DATASET_TYPE_IPV4:
1349  return DatasetAddIPv4(set, data, data_len);
1350  case DATASET_TYPE_IPV6:
1351  return DatasetAddIPv6(set, data, data_len);
1352  }
1353  return -1;
1354 }
1355 
1357  Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1358 {
1359  if (set == NULL)
1360  return -1;
1361 
1362  switch (set->type) {
1363  case DATASET_TYPE_STRING:
1364  return DatasetAddStringwRep(set, data, data_len, rep);
1365  case DATASET_TYPE_MD5:
1366  return DatasetAddMd5wRep(set, data, data_len, rep);
1367  case DATASET_TYPE_SHA256:
1368  return DatasetAddSha256wRep(set, data, data_len, rep);
1369  case DATASET_TYPE_IPV4:
1370  return DatasetAddIPv4wRep(set, data, data_len, rep);
1371  case DATASET_TYPE_IPV6:
1372  return DatasetAddIPv6wRep(set, data, data_len, rep);
1373  }
1374  return -1;
1375 }
1376 
1377 typedef int (*DatasetOpFunc)(Dataset *set, const uint8_t *data, const uint32_t data_len);
1378 
1379 static int DatasetOpSerialized(Dataset *set, const char *string, DatasetOpFunc DatasetOpString,
1380  DatasetOpFunc DatasetOpMd5, DatasetOpFunc DatasetOpSha256, DatasetOpFunc DatasetOpIPv4,
1381  DatasetOpFunc DatasetOpIPv6)
1382 {
1383  if (set == NULL)
1384  return -1;
1385  if (strlen(string) == 0)
1386  return -1;
1387 
1388  switch (set->type) {
1389  case DATASET_TYPE_STRING: {
1390  if (strlen(string) > UINT16_MAX) {
1391  // size check before cast and stack allocation
1392  return -1;
1393  }
1394  uint32_t decoded_size = SCBase64DecodeBufferSize((uint32_t)strlen(string));
1395  uint8_t decoded[decoded_size];
1396  uint32_t num_decoded = SCBase64Decode(
1397  (const uint8_t *)string, strlen(string), SCBase64ModeStrict, decoded);
1398  if (num_decoded == 0) {
1399  return -2;
1400  }
1401 
1402  return DatasetOpString(set, decoded, num_decoded);
1403  }
1404  case DATASET_TYPE_MD5: {
1405  if (strlen(string) != 32)
1406  return -2;
1407  uint8_t hash[16];
1408  if (HexToRaw((const uint8_t *)string, 32, hash, sizeof(hash)) < 0)
1409  return -2;
1410  return DatasetOpMd5(set, hash, 16);
1411  }
1412  case DATASET_TYPE_SHA256: {
1413  if (strlen(string) != 64)
1414  return -2;
1415  uint8_t hash[32];
1416  if (HexToRaw((const uint8_t *)string, 64, hash, sizeof(hash)) < 0)
1417  return -2;
1418  return DatasetOpSha256(set, hash, 32);
1419  }
1420  case DATASET_TYPE_IPV4: {
1421  struct in_addr in;
1422  if (inet_pton(AF_INET, string, &in) != 1)
1423  return -2;
1424  return DatasetOpIPv4(set, (uint8_t *)&in.s_addr, 4);
1425  }
1426  case DATASET_TYPE_IPV6: {
1427  struct in6_addr in6;
1428  if (DatasetParseIpv6String(set, string, &in6) != 0) {
1429  SCLogError("Dataset failed to import %s as IPv6", string);
1430  return -2;
1431  }
1432  return DatasetOpIPv6(set, (uint8_t *)&in6.s6_addr, 16);
1433  }
1434  }
1435  return -1;
1436 }
1437 
1438 /** \brief add serialized data to set
1439  * \retval int 1 added
1440  * \retval int 0 already in hash
1441  * \retval int -1 API error (not added)
1442  * \retval int -2 DATA error
1443  */
1444 int DatasetAddSerialized(Dataset *set, const char *string)
1445 {
1446  return DatasetOpSerialized(set, string, DatasetAddString, DatasetAddMd5, DatasetAddSha256,
1447  DatasetAddIPv4, DatasetAddIPv6);
1448 }
1449 
1450 /** \brief add serialized data to set
1451  * \retval int 1 added
1452  * \retval int 0 already in hash
1453  * \retval int -1 API error (not added)
1454  * \retval int -2 DATA error
1455  */
1456 int DatasetLookupSerialized(Dataset *set, const char *string)
1457 {
1458  return DatasetOpSerialized(set, string, DatasetLookupString, DatasetLookupMd5,
1459  DatasetLookupSha256, DatasetLookupIPv4, DatasetLookupIPv6);
1460 }
1461 
1462 /**
1463  * \retval 1 data was removed from the hash
1464  * \retval 0 data not removed (busy)
1465  * \retval -1 data not found
1466  */
1467 static int DatasetRemoveString(Dataset *set, const uint8_t *data, const uint32_t data_len)
1468 {
1469  if (set == NULL)
1470  return -1;
1471 
1472  StringType lookup = { .ptr = (uint8_t *)data, .len = data_len, .rep = 0 };
1473  return THashRemoveFromHash(set->hash, &lookup);
1474 }
1475 
1476 static int DatasetRemoveIPv4(Dataset *set, const uint8_t *data, const uint32_t data_len)
1477 {
1478  if (set == NULL)
1479  return -1;
1480 
1481  if (data_len != 4)
1482  return -2;
1483 
1484  IPv4Type lookup = { .rep = 0 };
1485  memcpy(lookup.ipv4, data, 4);
1486  return THashRemoveFromHash(set->hash, &lookup);
1487 }
1488 
1489 static int DatasetRemoveIPv6(Dataset *set, const uint8_t *data, const uint32_t data_len)
1490 {
1491  if (set == NULL)
1492  return -1;
1493 
1494  if (data_len != 16)
1495  return -2;
1496 
1497  IPv6Type lookup = { .rep = 0 };
1498  memcpy(lookup.ipv6, data, 16);
1499  return THashRemoveFromHash(set->hash, &lookup);
1500 }
1501 
1502 static int DatasetRemoveMd5(Dataset *set, const uint8_t *data, const uint32_t data_len)
1503 {
1504  if (set == NULL)
1505  return -1;
1506 
1507  if (data_len != 16)
1508  return -2;
1509 
1510  Md5Type lookup = { .rep = 0 };
1511  memcpy(lookup.md5, data, 16);
1512  return THashRemoveFromHash(set->hash, &lookup);
1513 }
1514 
1515 static int DatasetRemoveSha256(Dataset *set, const uint8_t *data, const uint32_t data_len)
1516 {
1517  if (set == NULL)
1518  return -1;
1519 
1520  if (data_len != 32)
1521  return -2;
1522 
1523  Sha256Type lookup = { .rep = 0 };
1524  memcpy(lookup.sha256, data, 32);
1525  return THashRemoveFromHash(set->hash, &lookup);
1526 }
1527 
1528 /** \brief remove serialized data from set
1529  * \retval int 1 removed
1530  * \retval int 0 found but busy (not removed)
1531  * \retval int -1 API error (not removed)
1532  * \retval int -2 DATA error */
1533 int DatasetRemoveSerialized(Dataset *set, const char *string)
1534 {
1535  return DatasetOpSerialized(set, string, DatasetRemoveString, DatasetRemoveMd5,
1536  DatasetRemoveSha256, DatasetRemoveIPv4, DatasetRemoveIPv6);
1537 }
1538 
1539 int DatasetRemove(Dataset *set, const uint8_t *data, const uint32_t data_len)
1540 {
1541  if (set == NULL)
1542  return -1;
1543 
1544  switch (set->type) {
1545  case DATASET_TYPE_STRING:
1546  return DatasetRemoveString(set, data, data_len);
1547  case DATASET_TYPE_MD5:
1548  return DatasetRemoveMd5(set, data, data_len);
1549  case DATASET_TYPE_SHA256:
1550  return DatasetRemoveSha256(set, data, data_len);
1551  case DATASET_TYPE_IPV4:
1552  return DatasetRemoveIPv4(set, data, data_len);
1553  case DATASET_TYPE_IPV6:
1554  return DatasetRemoveIPv6(set, data, data_len);
1555  }
1556  return -1;
1557 }
dataset_used_hashsize
uint32_t dataset_used_hashsize
Definition: datasets.c:51
util-byte.h
sets_lock
SCMutex sets_lock
Definition: datasets.c:45
StringType::rep
DataRepType rep
Definition: datasets-string.h:33
len
uint8_t len
Definition: app-layer-dnp3.h:2
datasets-string.h
DataRepResultType::rep
DataRepType rep
Definition: datasets-reputation.h:31
THashDataGetResult::data
THashData * data
Definition: util-thash.h:192
datasets-md5.h
Dataset::name
char name[DATASET_NAME_MAX_LEN+1]
Definition: datasets.h:56
DatasetAlloc
Dataset * DatasetAlloc(const char *name)
Definition: datasets.c:111
Dataset::id
uint32_t id
Definition: datasets.h:58
Dataset::save
char save[PATH_MAX]
Definition: datasets.h:65
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
ParseSizeStringU64
int ParseSizeStringU64(const char *size, uint64_t *res)
Definition: util-misc.c:190
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
datasets-sha256.h
IPv6Compare
bool IPv6Compare(void *a, void *b)
Definition: datasets-ipv6.c:56
name
const char * name
Definition: detect-engine-proto.c:47
HexToRaw
int HexToRaw(const uint8_t *in, size_t ins, uint8_t *out, size_t outs)
Definition: util-byte.c:770
THashRemoveFromHash
int THashRemoveFromHash(THashTableContext *ctx, void *data)
Definition: util-thash.c:890
TYPE_STATE
@ TYPE_STATE
Definition: datasets.c:282
Md5Type
Definition: datasets-md5.h:30
Dataset::hash
THashTableContext * hash
Definition: datasets.h:62
type
uint8_t type
Definition: decode-sctp.h:0
ctx
struct Thresholds ctx
IPv4Hash
uint32_t IPv4Hash(uint32_t hash_seed, void *s)
Definition: datasets-ipv4.c:63
Sha256Type::sha256
uint8_t sha256[32]
Definition: datasets-sha256.h:31
Md5Type::rep
DataRepType rep
Definition: datasets-md5.h:33
DataRepResultType::found
bool found
Definition: datasets-reputation.h:30
PrintHexString
void PrintHexString(char *str, size_t size, uint8_t *buf, size_t buf_len)
Definition: util-print.c:262
Dataset::type
enum DatasetTypes type
Definition: datasets.h:57
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
THashConsolidateMemcap
void THashConsolidateMemcap(THashTableContext *ctx)
Definition: util-thash.c:345
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
rust.h
DATASET_TYPE_SHA256
@ DATASET_TYPE_SHA256
Definition: datasets.h:49
Sha256Type::rep
DataRepType rep
Definition: datasets-sha256.h:33
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:122
datasets-reputation.h
DatasetAddwRep
int DatasetAddwRep(Dataset *set, const uint8_t *data, const uint32_t data_len, DataRepType *rep)
ConfigGetDataDirectory
const char * ConfigGetDataDirectory(void)
Definition: util-conf.c:85
Md5Type::md5
uint8_t md5[16]
Definition: datasets-md5.h:31
DATASET_TYPE_IPV6
@ DATASET_TYPE_IPV6
Definition: datasets.h:51
Md5StrCompare
bool Md5StrCompare(void *a, void *b)
Definition: datasets-md5.c:57
DatasetLookupSerialized
int DatasetLookupSerialized(Dataset *set, const char *string)
add serialized data to set
Definition: datasets.c:1456
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
DataRepResultType
Definition: datasets-reputation.h:29
DatasetGet
Dataset * DatasetGet(const char *name, enum DatasetTypes type, const char *save, const char *load, uint64_t memcap, uint32_t hashsize)
Definition: datasets.c:450
dataset_max_one_hashsize
uint32_t dataset_max_one_hashsize
Definition: datasets.c:49
StringSet
int StringSet(void *dst, void *src)
Definition: datasets-string.c:62
DatasetRemove
int DatasetRemove(Dataset *set, const uint8_t *data, const uint32_t data_len)
Definition: datasets.c:1539
DatasetGetDefaultMemcap
void DatasetGetDefaultMemcap(uint64_t *memcap, uint32_t *hashsize)
Definition: datasets.c:594
THashDataConfig_::hash_size
uint32_t hash_size
Definition: util-thash.h:127
datasets.h
IPv6Set
int IPv6Set(void *dst, void *src)
Definition: datasets-ipv6.c:33
util-debug.h
TYPE_LOAD
@ TYPE_LOAD
Definition: datasets.c:283
strlcat
size_t strlcat(char *, const char *src, size_t siz)
Definition: util-strlcatu.c:45
DatasetGetOrCreate
int DatasetGetOrCreate(const char *name, enum DatasetTypes type, const char *save, const char *load, uint64_t *memcap, uint32_t *hashsize, Dataset **ret_set)
Definition: datasets.c:368
DATASETS_HASHSIZE_DEFAULT
#define DATASETS_HASHSIZE_DEFAULT
Definition: datasets.c:592
StringAsBase64
int StringAsBase64(const void *s, char *out, size_t out_size)
Definition: datasets-string.c:46
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:120
datasets-ipv6.h
IPv6Type::ipv6
uint8_t ipv6[16]
Definition: datasets-ipv6.h:31
DATASET_TYPE_NOTSET
#define DATASET_TYPE_NOTSET
Definition: datasets.h:46
IPv6Type::rep
DataRepType rep
Definition: datasets-ipv6.h:33
util-print.h
DatasetPostReloadCleanup
void DatasetPostReloadCleanup(void)
Definition: datasets.c:564
SCConfGetNonNull
int SCConfGetNonNull(const char *name, const char **vptr)
Retrieve the non-null value of a configuration node.
Definition: conf.c:380
PrintInet
const char * PrintInet(int af, const void *src, char *dst, socklen_t size)
Definition: util-print.c:238
DatasetOpFunc
int(* DatasetOpFunc)(Dataset *set, const uint8_t *data, const uint32_t data_len)
Definition: datasets.c:1377
datasets-ipv4.h
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:262
StringGetLength
uint32_t StringGetLength(void *s)
Definition: datasets-string.c:114
Sha256StrSet
int Sha256StrSet(void *dst, void *src)
Definition: datasets-sha256.c:32
DatasetsDestroy
void DatasetsDestroy(void)
Definition: datasets.c:769
Md5StrHash
uint32_t Md5StrHash(uint32_t hash_seed, void *s)
Definition: datasets-md5.c:65
THashDataGetResult
Definition: util-thash.h:191
StringType
Definition: datasets-string.h:30
IPv4Set
int IPv4Set(void *dst, void *src)
Definition: datasets-ipv4.c:32
SCDatasetAdd
int SCDatasetAdd(Dataset *set, const uint8_t *data, const uint32_t data_len)
Definition: datasets.c:1336
DatasetsSave
void DatasetsSave(void)
Definition: datasets.c:850
conf.h
DatasetLock
void DatasetLock(void)
Definition: datasets.c:101
IPv6Type
Definition: datasets-ipv6.h:30
DatasetLookup
int DatasetLookup(Dataset *set, const uint8_t *data, const uint32_t data_len)
see if data is part of the set
Definition: datasets.c:1102
DATASET_TYPE_IPV4
@ DATASET_TYPE_IPV4
Definition: datasets.h:50
StringType::ptr
uint8_t * ptr
Definition: datasets-string.h:36
DatasetRemoveSerialized
int DatasetRemoveSerialized(Dataset *set, const char *string)
remove serialized data from set
Definition: datasets.c:1533
dataset_max_total_hashsize
uint32_t dataset_max_total_hashsize
Definition: datasets.c:50
g_system
bool g_system
Definition: suricata.c:196
THashShutdown
void THashShutdown(THashTableContext *ctx)
shutdown the flow engine
Definition: util-thash.c:354
SCConfNodeLookupChild
SCConfNode * SCConfNodeLookupChild(const SCConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:849
DatasetTypes
DatasetTypes
Definition: datasets.h:45
Dataset::next
struct Dataset * next
Definition: datasets.h:67
THashData_::data
void * data
Definition: util-thash.h:92
util-conf.h
Sha256Type
Definition: datasets-sha256.h:30
Sha256StrFree
void Sha256StrFree(void *s)
Definition: datasets-sha256.c:70
THashData_
Definition: util-thash.h:85
IPv4Free
void IPv4Free(void *s)
Definition: datasets-ipv4.c:70
suricata-common.h
util-path.h
datasets-context-json.h
FatalErrorOnInit
#define FatalErrorOnInit(...)
Fatal error IF we're starting up, and configured to consider errors to be fatal errors.
Definition: util-debug.h:526
DATASET_NAME_MAX_LEN
#define DATASET_NAME_MAX_LEN
Definition: datasets.h:54
PathIsAbsolute
int PathIsAbsolute(const char *path)
Check if a path is absolute.
Definition: util-path.c:44
Md5StrSet
int Md5StrSet(void *dst, void *src)
Definition: datasets-md5.c:34
StringCompare
bool StringCompare(void *a, void *b)
Definition: datasets-string.c:97
THashGetFromHash
struct THashDataGetResult THashGetFromHash(THashTableContext *ctx, void *data)
Definition: util-thash.c:637
FatalError
#define FatalError(...)
Definition: util-debug.h:517
hashsize
#define hashsize(n)
Definition: util-hash-lookup3.h:40
THashLookupFromHash
THashData * THashLookupFromHash(THashTableContext *ctx, void *data)
look up data in the hash
Definition: util-thash.c:747
IPv4Type
Definition: datasets-ipv4.h:30
ParseSizeStringU32
int ParseSizeStringU32(const char *size, uint32_t *res)
Definition: util-misc.c:173
THashDecrUsecnt
#define THashDecrUsecnt(h)
Definition: util-thash.h:170
IPv4Compare
bool IPv4Compare(void *a, void *b)
Definition: datasets-ipv4.c:55
DatasetFind
Dataset * DatasetFind(const char *name, enum DatasetTypes type)
look for set by name without creating it
Definition: datasets.c:319
util-validate.h
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
IPv6Hash
uint32_t IPv6Hash(uint32_t hash_seed, void *s)
Definition: datasets-ipv6.c:64
DatasetsInit
int DatasetsInit(void)
Definition: datasets.c:617
str
#define str(s)
Definition: suricata-common.h:313
DatasetGetTypeFromString
enum DatasetTypes DatasetGetTypeFromString(const char *s)
Definition: datasets.c:63
SCConfGetNode
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
Definition: conf.c:183
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
THashWalk
int THashWalk(THashTableContext *ctx, THashFormatFunc FormatterFunc, THashOutputFunc OutputterFunc, void *output_ctx)
Walk the hash.
Definition: util-thash.c:388
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Dataset::hidden
bool hidden
Definition: datasets.h:60
DatasetReload
void DatasetReload(void)
Definition: datasets.c:538
DatasetGetPathType
DatasetGetPathType
Definition: datasets.c:281
Sha256StrCompare
bool Sha256StrCompare(void *a, void *b)
Definition: datasets-sha256.c:55
StringHash
uint32_t StringHash(uint32_t hash_seed, void *s)
Definition: datasets-string.c:108
DataRepType
uint16_t DataRepType
Definition: datasets.h:22
DATASET_TYPE_MD5
@ DATASET_TYPE_MD5
Definition: datasets.h:48
DATASET_TYPE_STRING
@ DATASET_TYPE_STRING
Definition: datasets.h:47
DatasetUnlock
void DatasetUnlock(void)
Definition: datasets.c:106
THashDataGetResult::is_new
bool is_new
Definition: util-thash.h:193
IPv6Free
void IPv6Free(void *s)
Definition: datasets-ipv6.c:71
suricata.h
THashInit
THashTableContext * THashInit(const char *cnf_prefix, uint32_t data_size, int(*DataSet)(void *, void *), void(*DataFree)(void *), uint32_t(*DataHash)(uint32_t, void *), bool(*DataCompare)(void *, void *), bool(*DataExpired)(void *, SCTime_t), uint32_t(*DataSize)(void *), bool reset_memcap, uint64_t memcap, uint32_t hashsize)
Definition: util-thash.c:302
DatasetSearchByName
Dataset * DatasetSearchByName(const char *name)
Definition: datasets.c:120
SCConfNode_::name
char * name
Definition: conf.h:38
IPv4Type::ipv4
uint8_t ipv4[4]
Definition: datasets-ipv4.h:31
DatasetAddSerialized
int DatasetAddSerialized(Dataset *set, const char *string)
add serialized data to set
Definition: datasets.c:1444
Dataset
Definition: datasets.h:55
Dataset::from_yaml
bool from_yaml
Definition: datasets.h:59
IPv4Type::rep
DataRepType rep
Definition: datasets-ipv4.h:33
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:375
util-misc.h
util-thash.h
Dataset::load
char load[PATH_MAX]
Definition: datasets.h:64
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SCConfNode_
Definition: conf.h:37
Sha256StrHash
uint32_t Sha256StrHash(uint32_t hash_seed, void *s)
Definition: datasets-sha256.c:63
SCConfNode_::val
char * val
Definition: conf.h:39
Md5StrFree
void Md5StrFree(void *s)
Definition: datasets-md5.c:72
SCMutex
#define SCMutex
Definition: threads-debug.h:114
DatasetAppendSet
int DatasetAppendSet(Dataset *set)
Definition: datasets.c:78
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:109
StringFree
void StringFree(void *s)
Definition: datasets-string.c:121
SCDatasetAddwRep
int SCDatasetAddwRep(Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
Definition: datasets.c:1356
DatasetParseIpv6String
int DatasetParseIpv6String(Dataset *set, const char *line, struct in6_addr *in6)
Definition: datasets.c:155
DatasetLookupwRep
DataRepResultType DatasetLookupwRep(Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
Definition: datasets.c:1122
THashTableContext_::config
THashConfig config
Definition: util-thash.h:151