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