91 #define DETECT_ENGINE_DEFAULT_INSPECTION_RECURSION_LIMIT 3000
98 static uint32_t TenantIdHash(
HashTable *h,
void *data, uint16_t data_len);
99 static char TenantIdCompare(
void *d1, uint16_t d1_len,
void *d2, uint16_t d2_len);
100 static void TenantIdFree(
void *d);
101 static uint32_t DetectEngineTenantGetIdFromLivedev(
const void *ctx,
const Packet *p);
102 static uint32_t DetectEngineTenantGetIdFromVlanId(
const void *ctx,
const Packet *p);
103 static uint32_t DetectEngineTenantGetIdFromPcap(
const void *ctx,
const Packet *p);
158 FatalError(
"failed to register inspect engine %s", name);
170 FatalError(
"failed to register inspect engine %s: %s", name, strerror(errno));
172 new_engine->
sm_list = (uint16_t)sm_list;
177 if (g_pkt_inspect_engines == NULL) {
178 g_pkt_inspect_engines = new_engine;
181 while (t->
next != NULL) {
185 t->
next = new_engine;
198 FatalError(
"failed to register inspect engine %s", name);
215 FatalError(
"failed to register inspect engine %s: %s", name, strerror(errno));
217 new_engine->
sm_list = (uint16_t)sm_list;
219 new_engine->
dir = direction;
224 if (g_frame_inspect_engines == NULL) {
225 g_frame_inspect_engines = new_engine;
228 while (t->
next != NULL) {
232 t->
next = new_engine;
240 AppProto alproto, uint32_t dir,
int progress,
249 FatalError(
"failed to register inspect engine %s", name);
256 (progress < 0 || progress >= SHRT_MAX) ||
262 SCLogError(
"Invalid arguments: must register "
263 "GetData with DetectEngineInspectBufferGeneric");
278 memset(new_engine, 0,
sizeof(*new_engine));
280 new_engine->
dir = direction;
281 new_engine->
sm_list = (uint16_t)sm_list;
283 new_engine->
progress = (int16_t)progress;
287 if (g_app_inspect_engines == NULL) {
288 g_app_inspect_engines = new_engine;
291 while (t->
next != NULL) {
295 t->
next = new_engine;
300 static void DetectAppLayerInspectEngineCopy(
302 int sm_list,
int new_list,
315 new_engine->
sm_list = (uint16_t)new_list;
319 new_engine->
v2 = t->
v2;
326 while (list->
next != NULL) {
330 list->
next = new_engine;
352 new_engine->
v2 = t->
v2;
357 list->
next = new_engine;
366 static void DetectPktInspectEngineCopy(
368 int sm_list,
int new_list,
379 new_engine->
sm_list = (uint16_t)new_list;
382 new_engine->
v1 = t->
v1;
389 while (list->
next != NULL) {
393 list->
next = new_engine;
412 new_engine->
v1 = t->
v1;
418 while (list->
next != NULL) {
422 list->
next = new_engine;
437 FatalError(
"failed to register inspect engine %s", name);
454 FatalError(
"failed to register inspect engine %s: %s", name, strerror(errno));
456 new_engine->
sm_list = (uint16_t)sm_list;
458 new_engine->
dir = direction;
467 while (list->
next != NULL) {
471 list->
next = new_engine;
490 new_engine->
sm_list = (uint16_t)new_list;
496 new_engine->
v1 = t->
v1;
501 while (list->
next != NULL) {
505 list->
next = new_engine;
527 new_engine->
v1 = t->
v1;
533 while (list->
next != NULL) {
537 list->
next = new_engine;
549 static void AppendStreamInspectEngine(
552 bool prepend =
false;
561 new_engine->
mpm =
true;
564 new_engine->
dir = direction;
565 new_engine->
stream =
true;
568 new_engine->
smd = stream;
576 }
else if (prepend) {
583 while (a->
next != NULL) {
587 a->
next = new_engine;
590 SCLogDebug(
"sid %u: engine %p/%u added", s->
id, new_engine, new_engine->
id);
597 bool prepend =
false;
620 new_engine->
mpm =
true;
626 new_engine->
smd = smd;
627 new_engine->
v1 = u->
v1;
633 }
else if (prepend) {
638 while (a->
next != NULL) {
642 a->
next = new_engine;
650 bool prepend =
false;
660 new_engine->
mpm =
true;
665 new_engine->
smd = smd;
666 new_engine->
v1 = e->
v1;
672 }
else if (prepend) {
677 while (a->
next != NULL) {
681 a->
next = new_engine;
687 const int mpm_list,
const int files_id, uint8_t *last_id,
bool *head_is_mpm)
701 SCLogDebug(
"app engine: t %p t->id %u => alproto:%s files:%s", t, t->
id,
709 bool prepend =
false;
714 new_engine->
mpm =
true;
721 new_engine->
smd = smd;
723 new_engine->
v2 = t->
v2;
729 if (new_engine->
sm_list == files_id) {
731 SCLogDebug(
"sid %u: engine %p/%u is FILE ENGINE", s->
id, new_engine, new_engine->
id);
734 SCLogDebug(
"sid %u: engine %p/%u %s", s->
id, new_engine, new_engine->
id,
742 if (new_engine->
sm_list == files_id) {
744 SCLogDebug(
"sid %u: engine %p/%u is FILE ENGINE", s->
id, new_engine, new_engine->
id);
746 new_engine->
id = ++(*last_id);
747 SCLogDebug(
"sid %u: engine %p/%u %s", s->
id, new_engine, new_engine->
id,
753 while (a->
next != NULL) {
761 a->
next = new_engine;
762 if (new_engine->
sm_list == files_id) {
764 SCLogDebug(
"sid %u: engine %p/%u is FILE ENGINE", s->
id, new_engine, new_engine->
id);
766 new_engine->
id = ++(*last_id);
767 SCLogDebug(
"sid %u: engine %p/%u %s", s->
id, new_engine, new_engine->
id,
772 SCLogDebug(
"sid %u: engine %p/%u added", s->
id, new_engine, new_engine->
id);
785 bool head_is_mpm =
false;
799 u != NULL; u = u->
next) {
801 AppendFrameInspectEngine(
de_ctx, u, s, smd, mpm_list);
810 AppendPacketInspectEngine(
de_ctx, e, s, smd, mpm_list);
819 AppendAppInspectEngine(
820 de_ctx, t, s, smd, mpm_list, files_id, &last_id, &head_is_mpm);
833 AppendStreamInspectEngine(s, stream, 0, last_id + 1);
835 AppendStreamInspectEngine(s, stream, 1, last_id + 1);
837 AppendStreamInspectEngine(s, stream, 0, last_id + 1);
838 AppendStreamInspectEngine(s, stream, 1, last_id + 1);
852 iter->
sm_list == mpm_list ?
"MPM" :
"");
903 for (
int i = 0; i < arrays; i++) {
904 if (bufs[i] == ie->
smd) {
910 bufs[arrays++] = ie->
smd;
920 for (
int i = 0; i < arrays; i++) {
921 if (bufs[i] == e->
smd) {
927 bufs[arrays++] = e->
smd;
937 for (
int i = 0; i < arrays; i++) {
938 if (bufs[i] == u->
smd) {
944 bufs[arrays++] = u->
smd;
950 for (
int i = 0; i < engines; i++) {
972 static int g_buffer_type_reg_closed = 0;
976 return g_buffer_type_id;
979 static uint32_t DetectBufferTypeHashNameFunc(
HashListTable *ht,
void *data, uint16_t datalen)
988 static uint32_t DetectBufferTypeHashIdFunc(
HashListTable *ht,
void *data, uint16_t datalen)
991 uint32_t hash = map->
id;
996 static char DetectBufferTypeCompareNameFunc(
void *data1, uint16_t len1,
void *data2, uint16_t len2)
1001 char r = (strcmp(map1->
name, map2->
name) == 0);
1006 static char DetectBufferTypeCompareIdFunc(
void *data1, uint16_t len1,
void *data2, uint16_t len2)
1010 return map1->
id == map2->
id;
1013 static void DetectBufferTypeFreeFunc(
void *data)
1026 SCLogError(
"%s allocates transform option memory but has no free routine",
1036 static int DetectBufferTypeInit(
void)
1038 BUG_ON(g_buffer_type_hash);
1040 DetectBufferTypeCompareNameFunc, DetectBufferTypeFreeFunc);
1041 if (g_buffer_type_hash == NULL)
1047 static void DetectBufferTypeFree(
void)
1049 if (g_buffer_type_hash == NULL)
1053 g_buffer_type_hash = NULL;
1057 static int DetectBufferTypeAdd(
const char *
string)
1059 BUG_ON(
string == NULL || strlen(
string) >= 32);
1066 map->
id = g_buffer_type_id++;
1076 memset(&map, 0,
sizeof(map));
1085 BUG_ON(g_buffer_type_reg_closed);
1086 if (g_buffer_type_hash == NULL)
1087 DetectBufferTypeInit();
1091 return DetectBufferTypeAdd(name);
1099 BUG_ON(g_buffer_type_reg_closed);
1104 SCLogDebug(
"%p %s -- %d supports multi instance", exists, name, exists->
id);
1109 BUG_ON(g_buffer_type_reg_closed);
1113 exists->
frame =
true;
1114 SCLogDebug(
"%p %s -- %d supports frame inspection", exists, name, exists->
id);
1119 BUG_ON(g_buffer_type_reg_closed);
1124 SCLogDebug(
"%p %s -- %d supports packet inspection", exists, name, exists->
id);
1129 BUG_ON(g_buffer_type_reg_closed);
1134 SCLogDebug(
"%p %s -- %d supports mpm", exists, name, exists->
id);
1139 BUG_ON(g_buffer_type_reg_closed);
1144 SCLogDebug(
"%p %s -- %d supports transformations", exists, name, exists->
id);
1160 memset(&map, 0,
sizeof(map));
1170 memset(&lookup, 0,
sizeof(lookup));
1180 return res ? res->
name : NULL;
1185 BUG_ON(
string == NULL || strlen(
string) >= 32);
1201 const int direction,
const AppProto alproto,
const uint8_t frame_type)
1208 const int buffer_id = DetectEngineBufferTypeAdd(
de_ctx, name);
1209 if (buffer_id < 0) {
1238 return DetectEngineBufferTypeAdd(
de_ctx, name);
1246 BUG_ON(desc == NULL || strlen(desc) >= 128);
1277 exists->
frame =
true;
1278 SCLogDebug(
"%p %s -- %d supports frame inspection", exists, name, exists->
id);
1286 SCLogDebug(
"%p %s -- %d supports packet inspection", exists, name, exists->
id);
1294 SCLogDebug(
"%p %s -- %d supports mpm", exists, name, exists->
id);
1302 SCLogDebug(
"%p %s -- %d supports transformations", exists, name, exists->
id);
1344 BUG_ON(g_buffer_type_reg_closed);
1360 bool (*ValidateCallback)(
const Signature *,
const char **sigerror))
1362 BUG_ON(g_buffer_type_reg_closed);
1415 SCLogError(
"Rule buffer cannot be reset after base64_data.");
1420 SCLogError(
"no matches following transform(s)");
1428 SCLogError(
"previous sticky buffer has no matches");
1438 if ((uint32_t)list == b->
id) {
1439 SCLogDebug(
"found buffer %p for list %d", b, list);
1442 SCLogDebug(
"sm_init was true for %p list %d", b, list);
1461 SCLogError(
"failed to expand rule buffer array");
1483 SCLogError(
"previous transforms not consumed "
1484 "(list: %u, transform_cnt %u)",
1489 SCLogDebug(
"buffer %d has transform(s) registered: %d",
1493 if (new_list == -1) {
1504 SCLogError(
"failed to expand rule buffer array");
1515 SCLogDebug(
"new list after applying transforms: %u", new_list);
1538 for (uint32_t x = 0; x <= mbuffer->
max; x++) {
1558 if (!buffer->
init) {
1579 if (local_id >= fb->
size) {
1580 uint32_t old_size = fb->
size;
1581 uint32_t new_size = local_id + 1;
1582 uint32_t grow_by = new_size - old_size;
1583 SCLogDebug(
"size is %u, need %u, so growing by %u", old_size, new_size, grow_by);
1591 SCLogDebug(
"ptr %p to_zero %p", ptr, to_zero);
1594 fb->
size = new_size;
1600 #ifdef DEBUG_VALIDATION
1601 buffer->multi =
true;
1608 memset(buffer, 0,
sizeof(*buffer));
1609 buffer->
buf =
SCCalloc(initial_size,
sizeof(uint8_t));
1610 if (buffer->
buf != NULL) {
1611 buffer->
size = initial_size;
1618 #ifdef DEBUG_VALIDATION
1630 const uint8_t *data,
const uint32_t data_len)
1632 #ifdef DEBUG_VALIDATION
1647 #ifdef DEBUG_VALIDATION
1651 if (buffer->
inspect == NULL) {
1653 if (det_ctx && list_id != -1)
1665 if (buffer->
buf != NULL) {
1668 memset(buffer, 0,
sizeof(*buffer));
1680 uint32_t new_size = (buffer->
size == 0) ? 4096 : buffer->
size;
1681 while (new_size < min_size) {
1688 buffer->
size = new_size;
1697 uint32_t copy_size =
MIN(buf_len, buffer->
size);
1698 memcpy(buffer->
buf, buf, copy_size);
1724 const uint8_t *content, uint16_t content_len,
const char **namestr)
1765 const int size = g_buffer_type_id;
1769 DetectBufferTypeCompareNameFunc, DetectBufferTypeFreeFunc);
1772 HashListTableInit(256, DetectBufferTypeHashIdFunc, DetectBufferTypeCompareIdFunc,
1784 memcpy(copy, map,
sizeof(*copy));
1790 SCLogDebug(
"name %s id %d mpm %s packet %s -- %s. "
1791 "Callbacks: Setup %p Validate %p",
1792 map->
name, map->
id, map->
mpm ?
"true" :
"false", map->
packet ?
"true" :
"false",
1799 DetectAppLayerInspectEngineCopyListToDetectCtx(
de_ctx);
1801 DetectFrameInspectEngineCopyListToDetectCtx(
de_ctx);
1803 DetectPktInspectEngineCopyListToDetectCtx(
de_ctx);
1845 while (framemlist) {
1856 BUG_ON(g_buffer_type_hash == NULL);
1858 g_buffer_type_reg_closed = 1;
1869 SCLogError(
"buffer '%s' does not support transformations", base_map->
name);
1876 memset(&t, 0,
sizeof(t));
1877 for (
int i = 0; i < transform_cnt; i++) {
1880 t.
cnt = transform_cnt;
1883 memset(&lookup_map, 0,
sizeof(lookup_map));
1901 map->
mpm = base_map->
mpm;
1908 }
else if (map->
packet) {
1918 SCLogDebug(
"buffer %s registered with id %d, parent %d", map->name, map->id, map->parent_id);
1922 DetectFrameInspectEngineCopy(
de_ctx, map->parent_id, map->id, &map->transforms);
1923 }
else if (map->packet) {
1924 DetectPktInspectEngineCopy(
de_ctx, map->parent_id, map->id, &map->transforms);
1926 DetectAppLayerInspectEngineCopy(
de_ctx, map->parent_id, map->id, &map->transforms);
1932 static int DetectEngineInspectRulePacketMatches(
1936 Packet *p, uint8_t *_alert_flags)
1944 SCLogDebug(
"running match functions, sm %p", smd);
1962 static int DetectEngineInspectRulePayloadMatches(
1985 SCLogDebug(
"no match in stream, fall back to packet payload");
2007 uint8_t *alert_flags)
2012 if (e->
v1.
Callback(det_ctx, e, s, p, alert_flags) ==
false) {
2013 SCLogDebug(
"sid %u: e %p Callback returned false", s->
id, e);
2016 SCLogDebug(
"sid %u: e %p Callback returned true", s->
id, e);
2035 e->
sm_list = (uint16_t)list_id;
2044 while (a->
next != NULL) {
2056 if (DetectEnginePktInspectionAppend(
2059 SCLogDebug(
"sid %u: DetectEngineInspectRulePayloadMatches appended", s->
id);
2063 if (DetectEnginePktInspectionAppend(
2066 SCLogDebug(
"sid %u: DetectEngineInspectRulePacketMatches appended", s->
id);
2148 uint8_t
flags,
void *alstate,
void *txv, uint64_t tx_id)
2151 SCLogDebug(
"running match functions, sm %p", smd);
2157 AppLayerTxMatch(det_ctx, f,
flags, alstate, txv, s, smd->
ctx);
2191 void *alstate,
void *txv, uint64_t tx_id)
2193 const int list_id = engine->
sm_list;
2194 SCLogDebug(
"running inspect on %d", list_id);
2208 f,
flags, txv, list_id);
2215 const uint8_t *data = buffer->
inspect;
2220 ci_flags |= buffer->
flags;
2231 (uint8_t *)data, data_len,
offset, ci_flags,
2257 const int list_id = engine->
sm_list;
2258 SCLogDebug(
"running inspect on %d", list_id);
2276 const uint8_t *data = buffer->
inspect;
2277 const uint64_t
offset = 0;
2280 ci_flags |= buffer->
flags;
2291 (uint8_t *)data, data_len,
offset, ci_flags,
2304 static void InjectPackets(
ThreadVars **detect_tvs,
2306 int no_of_detect_tvs)
2310 for (
int i = 0; i < no_of_detect_tvs; i++) {
2311 if (
SC_ATOMIC_GET(new_det_ctx[i]->so_far_used_by_detect) != 1) {
2312 if (detect_tvs[i]->inq != NULL) {
2349 if (no_of_detect_tvs == 0) {
2359 memset(detect_tvs, 0x00, (no_of_detect_tvs *
sizeof(
ThreadVars *)));
2384 if (new_det_ctx[i] == NULL) {
2386 "failure in live rule swap. Let's get out of here");
2390 SCLogDebug(
"live rule swap created new det_ctx - %p and de_ctx "
2391 "- %p\n", new_det_ctx[i], new_de_ctx);
2396 BUG_ON(i != no_of_detect_tvs);
2409 SCLogDebug(
"swapping new det_ctx - %p with older one - %p",
2420 SCLogDebug(
"Live rule swap has swapped %d old det_ctx's with new ones, "
2421 "along with the new de_ctx", no_of_detect_tvs);
2423 InjectPackets(detect_tvs, new_det_ctx, no_of_detect_tvs);
2427 uint32_t threads_done = 0;
2429 for (i = 0; i < no_of_detect_tvs; i++) {
2431 threads_done = no_of_detect_tvs;
2435 if (
SC_ATOMIC_GET(new_det_ctx[i]->so_far_used_by_detect) == 1) {
2436 SCLogDebug(
"new_det_ctx - %p used by detect engine", new_det_ctx[i]);
2439 TmThreadsCaptureBreakLoop(detect_tvs[i]);
2442 if (threads_done < no_of_detect_tvs) {
2453 if (i != no_of_detect_tvs) {
2466 for (i = 0; i < no_of_detect_tvs; i++) {
2467 SCLogDebug(
"Freeing old_det_ctx - %p used by detect",
2477 for (i = 0; i < no_of_detect_tvs; i++) {
2478 if (new_det_ctx[i] != NULL)
2502 if (prefix != NULL) {
2507 SCLogDebug(
"ConfGetBool could not load the value.");
2518 SCLogDebug(
"Unable to alloc SpmGlobalThreadCtx.");
2522 if (DetectEngineCtxLoadConf(
de_ctx) == -1) {
2532 DetectBufferTypeSetupDetectEngine(
de_ctx);
2580 if (prefix == NULL || strlen(prefix) == 0)
2618 #ifdef PROFILE_RULES
2619 if (
de_ctx->profile_ctx != NULL) {
2621 de_ctx->profile_ctx = NULL;
2657 DetectEngineCtxFreeThreadKeywordData(
de_ctx);
2659 DetectEngineCtxFreeFailedSigs(
de_ctx);
2679 DetectBufferTypeFreeDetectEngine(
de_ctx);
2697 const char *max_uniq_toclient_groups_str = NULL;
2698 const char *max_uniq_toserver_groups_str = NULL;
2699 const char *sgh_mpm_context = NULL;
2700 const char *de_ctx_profile = NULL;
2702 (void)
ConfGet(
"detect.profile", &de_ctx_profile);
2703 (void)
ConfGet(
"detect.sgh-mpm-context", &sgh_mpm_context);
2708 if (de_ctx_custom != NULL) {
2710 if (de_ctx_profile == NULL) {
2711 if (opt->
val && strcmp(opt->
val,
"profile") == 0) {
2712 de_ctx_profile = opt->head.tqh_first->
val;
2716 if (sgh_mpm_context == NULL) {
2717 if (opt->
val && strcmp(opt->
val,
"sgh-mpm-context") == 0) {
2718 sgh_mpm_context = opt->head.tqh_first->
val;
2724 if (de_ctx_profile != NULL) {
2725 if (strcmp(de_ctx_profile,
"low") == 0 ||
2726 strcmp(de_ctx_profile,
"lowest") == 0) {
2728 }
else if (strcmp(de_ctx_profile,
"medium") == 0) {
2730 }
else if (strcmp(de_ctx_profile,
"high") == 0 ||
2731 strcmp(de_ctx_profile,
"highest") == 0) {
2733 }
else if (strcmp(de_ctx_profile,
"custom") == 0) {
2736 SCLogError(
"invalid value for detect.profile: '%s'. "
2737 "Valid options: low, medium, high and custom.",
2742 SCLogDebug(
"Profile for detection engine groups is \"%s\"", de_ctx_profile);
2744 SCLogDebug(
"Profile for detection engine groups not provided "
2745 "at suricata.yaml. Using default (\"medium\").");
2749 if (sgh_mpm_context == NULL || strcmp(sgh_mpm_context,
"auto") == 0) {
2753 #ifdef BUILD_HYPERSCAN
2762 if (strcmp(sgh_mpm_context,
"single") == 0) {
2764 }
else if (strcmp(sgh_mpm_context,
"full") == 0) {
2768 "invalid conf value for detect-engine.sgh-mpm-context-"
2793 (void)
ConfGet(
"detect.custom-values.toclient-groups",
2794 &max_uniq_toclient_groups_str);
2795 (void)
ConfGet(
"detect.custom-values.toserver-groups",
2796 &max_uniq_toserver_groups_str);
2798 if (de_ctx_custom != NULL) {
2800 if (opt->
val && strcmp(opt->
val,
"custom-values") == 0) {
2801 if (max_uniq_toclient_groups_str == NULL) {
2803 (opt->head.tqh_first,
"toclient-sp-groups");
2805 if (max_uniq_toclient_groups_str == NULL) {
2807 (opt->head.tqh_first,
"toclient-groups");
2809 if (max_uniq_toserver_groups_str == NULL) {
2811 (opt->head.tqh_first,
"toserver-dp-groups");
2813 if (max_uniq_toserver_groups_str == NULL) {
2815 (opt->head.tqh_first,
"toserver-groups");
2820 if (max_uniq_toclient_groups_str != NULL) {
2822 (uint16_t)strlen(max_uniq_toclient_groups_str),
2823 (
const char *)max_uniq_toclient_groups_str) <= 0) {
2827 "toclient-groups failed, using %u",
2835 if (max_uniq_toserver_groups_str != NULL) {
2837 (uint16_t)strlen(max_uniq_toserver_groups_str),
2838 (
const char *)max_uniq_toserver_groups_str) <= 0) {
2842 "toserver-groups failed, using %u",
2861 if (
ConfGetInt(
"detect.inspection-recursion-limit", &value) == 1)
2863 if (value >= 0 && value <= INT_MAX) {
2869 ConfNode *insp_recursion_limit_node = NULL;
2870 char *insp_recursion_limit = NULL;
2872 if (de_ctx_custom != NULL) {
2875 if (opt->
val && strcmp(opt->
val,
"inspection-recursion-limit") != 0)
2879 if (insp_recursion_limit_node == NULL) {
2881 "entry for detect-engine:inspection-recursion-limit");
2884 insp_recursion_limit = insp_recursion_limit_node->
val;
2885 SCLogDebug(
"Found detect-engine.inspection-recursion-limit - %s:%s",
2886 insp_recursion_limit_node->
name, insp_recursion_limit_node->
val);
2890 if (insp_recursion_limit != NULL) {
2892 0, (
const char *)insp_recursion_limit) < 0) {
2894 "detect-engine.inspection-recursion-limit: %s "
2910 SCLogDebug(
"de_ctx->inspection_recursion_limit: %d",
2915 const char *ports = NULL;
2916 (void)
ConfGet(
"detect.grouping.tcp-whitelist", &ports);
2920 ports =
"53, 80, 139, 443, 445, 1433, 3306, 3389, 6666, 6667, 8080";
2921 SCLogConfig(
"grouping: tcp-whitelist (default) %s", ports);
2926 "for detect.grouping.tcp-whitelist",
2930 for ( ; x != NULL; x = x->
next) {
2933 "for detect.grouping.tcp-whitelist: only single ports allowed",
2942 (void)
ConfGet(
"detect.grouping.udp-whitelist", &ports);
2946 ports =
"53, 135, 5060";
2947 SCLogConfig(
"grouping: udp-whitelist (default) %s", ports);
2952 "for detect.grouping.udp-whitelist",
2958 "for detect.grouping.udp-whitelist: only single ports allowed",
2967 const char *pf_setting = NULL;
2968 if (
ConfGet(
"detect.prefilter.default", &pf_setting) == 1 && pf_setting) {
2969 if (strcasecmp(pf_setting,
"mpm") == 0) {
2971 }
else if (strcasecmp(pf_setting,
"auto") == 0) {
2980 SCLogConfig(
"prefilter engines: MPM and keywords");
3009 SCLogError(
"setting up thread local detect ctx");
3018 SCLogError(
"setting up thread local detect ctx "
3019 "for keyword \"%s\" failed",
3057 SCLogError(
"setting up thread local detect ctx");
3071 SCLogError(
"setting up thread local detect ctx "
3072 "for keyword \"%s\" failed",
3102 uint32_t map_array_size = 0;
3103 uint32_t map_cnt = 0;
3104 int max_tenant_id = 0;
3110 "set using multi-detect.selector");
3123 mt_det_ctxs_hash =
HashTableInit(tcnt * 2, TenantIdHash, TenantIdCompare, TenantIdFree);
3124 if (mt_det_ctxs_hash == NULL) {
3129 SCLogInfo(
"no tenants left, or none registered yet");
3140 map_array_size = map_cnt + 1;
3142 map_array =
SCCalloc(map_array_size,
sizeof(*map_array));
3143 if (map_array == NULL)
3150 if (map_cnt >= map_array_size) {
3162 list = master->
list;
3167 if (mt_det_ctx == NULL)
3169 if (
HashTableAdd(mt_det_ctxs_hash, mt_det_ctx, 0) != 0) {
3178 mt_det_ctxs_hash = NULL;
3190 det_ctx->
TenantGetId = DetectEngineTenantGetIdFromVlanId;
3194 det_ctx->
TenantGetId = DetectEngineTenantGetIdFromLivedev;
3198 det_ctx->
TenantGetId = DetectEngineTenantGetIdFromPcap;
3205 if (map_array != NULL)
3207 if (mt_det_ctxs_hash != NULL)
3292 DetectEngineThreadCtxInitKeywords(
de_ctx, det_ctx);
3293 DetectEngineThreadCtxInitGlobalKeywords(det_ctx);
3294 #ifdef PROFILE_RULES
3333 if (det_ctx->
de_ctx == NULL) {
3368 if (DetectEngineThreadCtxInitForMT(
tv, det_ctx) !=
TM_ECODE_OK) {
3375 *data = (
void *)det_ctx;
3400 if (det_ctx->
de_ctx == NULL) {
3432 if (DetectEngineThreadCtxInitForMT(
tv, det_ctx) !=
TM_ECODE_OK) {
3445 SCLogDebug(
"PACKET PKT_STREAM_ADD: %"PRIu64, det_ctx->pkt_stream_add_cnt);
3447 SCLogDebug(
"PAYLOAD MPM %"PRIu64
"/%"PRIu64, det_ctx->payload_mpm_cnt, det_ctx->payload_mpm_size);
3448 SCLogDebug(
"STREAM MPM %"PRIu64
"/%"PRIu64, det_ctx->stream_mpm_cnt, det_ctx->stream_mpm_size);
3450 SCLogDebug(
"PAYLOAD SIG %"PRIu64
"/%"PRIu64, det_ctx->payload_persig_cnt, det_ctx->payload_persig_size);
3451 SCLogDebug(
"STREAM SIG %"PRIu64
"/%"PRIu64, det_ctx->stream_persig_cnt, det_ctx->stream_persig_size);
3459 #ifdef PROFILE_RULES
3469 if (det_ctx->
de_ctx != NULL) {
3511 for (uint32_t x = 0; x < fb->
size; x++) {
3522 DetectEngineThreadCtxDeinitGlobalKeywords(det_ctx);
3523 if (det_ctx->
de_ctx != NULL) {
3524 DetectEngineThreadCtxDeinitKeywords(det_ctx->
de_ctx, det_ctx);
3542 if (det_ctx == NULL) {
3551 DetectEngineThreadCtxFree(det_ctx);
3563 static uint32_t DetectKeywordCtxHashFunc(
HashListTable *ht,
void *data, uint16_t datalen)
3566 const char *name = ctx->
name;
3567 uint64_t hash =
StringHashDjb2((
const uint8_t *)name, strlen(name)) + (uint64_t)ctx->
data;
3572 static char DetectKeywordCtxCompareFunc(
void *data1, uint16_t len1,
void *data2, uint16_t len2)
3576 const char *name1 = ctx1->
name;
3577 const char *name2 = ctx2->
name;
3578 return (strcmp(name1, name2) == 0 && ctx1->
data == ctx2->
data);
3581 static void DetectKeywordCtxFreeFunc(
void *ptr)
3604 BUG_ON(
de_ctx == NULL || InitFunc == NULL || FreeFunc == NULL);
3608 DetectKeywordCtxHashFunc, DetectKeywordCtxCompareFunc, DetectKeywordCtxFreeFunc);
3693 void *(*InitFunc)(
void *),
void *data,
void (*FreeFunc)(
void *))
3696 BUG_ON(InitFunc == NULL || FreeFunc == NULL);
3702 while (item != NULL) {
3703 if (strcmp(name, item->
name) == 0) {
3753 if (master->
list == NULL) {
3829 static int DetectEngineMultiTenantLoadTenant(uint32_t tenant_id,
const char *filename,
int loader_id)
3834 snprintf(prefix,
sizeof(prefix),
"multi-detect.%u", tenant_id);
3838 if(_stat(filename, &st) != 0) {
3841 if(stat(filename, &st) != 0) {
3843 SCLogError(
"failed to stat file %s", filename);
3849 SCLogError(
"tenant %u already registered", tenant_id);
3856 SCLogError(
"failed to properly setup yaml %s", filename);
3888 static int DetectEngineMultiTenantReloadTenant(uint32_t tenant_id,
const char *filename,
int reload_cnt)
3891 if (old_de_ctx == NULL) {
3892 SCLogError(
"tenant detect engine not found");
3897 snprintf(prefix,
sizeof(prefix),
"multi-detect.%u.reload.%d", tenant_id, reload_cnt);
3908 SCLogError(
"failed to properly setup yaml %s", filename);
3913 if (new_de_ctx == NULL) {
3948 static int DetectLoaderFuncLoadTenant(
void *vctx,
int loader_id)
3953 if (DetectEngineMultiTenantLoadTenant(ctx->
tenant_id, ctx->
yaml, loader_id) != 0) {
3959 static int DetectLoaderSetupLoadTenant(uint32_t tenant_id,
const char *yaml)
3971 static int DetectLoaderFuncReloadTenant(
void *vctx,
int loader_id)
3983 static int DetectLoaderSetupReloadTenant(uint32_t tenant_id,
const char *yaml,
int reload_cnt)
3986 if (old_de_ctx == NULL)
4008 int r = DetectLoaderSetupLoadTenant(tenant_id, yaml);
4022 int r = DetectLoaderSetupReloadTenant(tenant_id, yaml, reload_cnt);
4032 static int DetectEngineMultiTenantSetupLoadLivedevMappings(
const ConfNode *mappings_root_node,
4037 int mapping_cnt = 0;
4038 if (mappings_root_node != NULL) {
4041 if (tenant_id_node == NULL)
4044 if (device_node == NULL)
4047 uint32_t tenant_id = 0;
4049 tenant_id_node->
val) < 0) {
4052 tenant_id_node->
val);
4056 const char *dev = device_node->
val;
4075 SCLogConfig(
"device %s connected to tenant-id %u", dev, tenant_id);
4084 SCLogConfig(
"%d device - tenant-id mappings defined", mapping_cnt);
4091 static int DetectEngineMultiTenantSetupLoadVlanMappings(
const ConfNode *mappings_root_node,
4096 int mapping_cnt = 0;
4097 if (mappings_root_node != NULL) {
4100 if (tenant_id_node == NULL)
4103 if (vlan_id_node == NULL)
4106 uint32_t tenant_id = 0;
4108 tenant_id_node->
val) < 0) {
4111 tenant_id_node->
val);
4115 uint16_t vlan_id = 0;
4117 &vlan_id, 10, (uint16_t)strlen(vlan_id_node->
val), vlan_id_node->
val) < 0) {
4123 if (vlan_id == 0 || vlan_id >= 4095) {
4125 "of %s is invalid. Valid range 1-4094.",
4133 SCLogConfig(
"vlan %u connected to tenant-id %u", vlan_id, tenant_id);
4159 int failure_fatal = 0;
4160 (void)
ConfGetBool(
"engine.init-failure-fatal", &failure_fatal);
4163 (void)
ConfGetBool(
"multi-detect.enabled", &enabled);
4173 const char *handler = NULL;
4174 if (
ConfGet(
"multi-detect.selector", &handler) == 1) {
4175 SCLogConfig(
"multi-tenant selector type %s", handler);
4177 if (strcmp(handler,
"vlan") == 0) {
4181 if ((
ConfGetBool(
"vlan.use-for-tracking", &vlanbool)) == 1 && vlanbool == 0) {
4183 "can't use multi-detect selector 'vlan'");
4188 }
else if (strcmp(handler,
"direct") == 0) {
4190 }
else if (strcmp(handler,
"device") == 0) {
4193 SCLogWarning(
"multi-tenant 'device' mode not supported for IPS");
4200 "multi-detect.selector",
4207 SCLogConfig(
"multi-detect is enabled (multi tenancy). Selector: %s", handler);
4213 int mapping_cnt = DetectEngineMultiTenantSetupLoadVlanMappings(mappings_root_node,
4215 if (mapping_cnt == 0) {
4221 SCLogNotice(
"no tenant traffic mappings defined, "
4222 "tenants won't be used until mappings are added");
4224 if (failure_fatal) {
4225 SCLogError(
"no multi-detect mappings defined");
4233 int mapping_cnt = DetectEngineMultiTenantSetupLoadLivedevMappings(mappings_root_node,
4235 if (mapping_cnt == 0) {
4236 if (failure_fatal) {
4237 SCLogError(
"no multi-detect mappings defined");
4249 if (tenants_root_node != NULL) {
4252 if (id_node == NULL) {
4256 if (yaml_node == NULL) {
4260 uint32_t tenant_id = 0;
4262 &tenant_id, 10, (uint16_t)strlen(id_node->
val), id_node->
val) < 0) {
4273 snprintf(prefix,
sizeof(prefix),
"multi-detect.%u", tenant_id);
4279 int r = DetectLoaderSetupLoadTenant(tenant_id, yaml_node->
val);
4300 SCLogDebug(
"multi-detect not enabled (multi tenancy)");
4307 static uint32_t DetectEngineTenantGetIdFromVlanId(
const void *ctx,
const Packet *p)
4311 uint32_t vlan_id = 0;
4331 static uint32_t DetectEngineTenantGetIdFromLivedev(
const void *ctx,
const Packet *p)
4336 if (ld == NULL || det_ctx == NULL)
4343 static int DetectEngineTenantRegisterSelector(
4350 SCLogInfo(
"conflicting selector already set");
4357 if (
m->traffic_id == traffic_id) {
4358 SCLogInfo(
"traffic id already registered");
4379 SCLogDebug(
"tenant handler %u %u %u registered", selector, tenant_id, traffic_id);
4384 static int DetectEngineTenantUnregisterSelector(
4408 SCLogInfo(
"tenant handler %u %u %u unregistered", selector, tenant_id, traffic_id);
4422 return DetectEngineTenantRegisterSelector(
4433 return DetectEngineTenantUnregisterSelector(
TENANT_SELECTOR_VLAN, tenant_id, (uint32_t)vlan_id);
4448 static uint32_t DetectEngineTenantGetIdFromPcap(
const void *ctx,
const Packet *p)
4458 if (master->
list == NULL) {
4481 BUG_ON((*de_ctx)->ref_cnt == 0);
4482 (*de_ctx)->ref_cnt--;
4490 if (instance == NULL)
4493 if (master->
list == NULL) {
4494 master->
list = instance;
4497 master->
list = instance;
4514 r = DetectEngineAddToList(
de_ctx);
4525 if (instance == NULL) {
4531 if (instance ==
de_ctx) {
4535 instance = instance->
next;
4540 if (instance ==
de_ctx) {
4548 if (instance == NULL) {
4555 instance->
next = NULL;
4589 SCLogDebug(
"freeing detect engine %p", instance);
4600 static int reloads = 0;
4615 memset(prefix, 0,
sizeof(prefix));
4620 snprintf(prefix,
sizeof(prefix),
"detect-engine-reloads.%d", reloads++);
4647 if (old_de_ctx == NULL)
4649 SCLogDebug(
"get ref to old_de_ctx %p", old_de_ctx);
4663 if (new_de_ctx == NULL) {
4675 SCLogDebug(
"set up new_de_ctx %p", new_de_ctx);
4684 SCLogDebug(
"going to reload the threads to use new_de_ctx %p", new_de_ctx);
4686 DetectEngineReloadThreads(new_de_ctx);
4687 SCLogDebug(
"threads now run new_de_ctx %p", new_de_ctx);
4696 SCLogDebug(
"old_de_ctx should have been freed");
4702 static uint32_t TenantIdHash(
HashTable *h,
void *data, uint16_t data_len)
4708 static char TenantIdCompare(
void *d1, uint16_t d1_len,
void *d2, uint16_t d2_len)
4715 static void TenantIdFree(
void *d)
4717 DetectEngineThreadCtxFree(d);
4733 for ( ; list != NULL; list = list->
next) {
4744 if (stub_de_ctx == NULL) {
4746 if (stub_de_ctx == NULL) {
4751 if (master->
list == NULL) {
4752 master->
list = stub_de_ctx;
4755 master->
list = stub_de_ctx;
4761 DetectEngineReloadThreads(stub_de_ctx);
4771 SCLogDebug(
"old_de_ctx should have been freed");
4775 static int g_parse_metadata = 0;
4779 g_parse_metadata = 1;
4784 g_parse_metadata = 0;
4789 return g_parse_metadata;
4798 return "packet/stream payload";
4804 return "base64_data";
4807 return "post-match";
4815 return "max (internal)";
4836 if (*event_id == -1) {
4838 "det_ctx's enum map table.",
4852 static int DetectEngineInitYamlConf(
const char *conf)
4859 static void DetectEngineDeInitYamlConf(
void)
4867 static int DetectEngineTest01(
void)
4873 " - profile: medium\n"
4874 " - custom-values:\n"
4875 " toclient_src_groups: 2\n"
4876 " toclient_dst_groups: 2\n"
4877 " toclient_sp_groups: 2\n"
4878 " toclient_dp_groups: 3\n"
4879 " toserver_src_groups: 2\n"
4880 " toserver_dst_groups: 4\n"
4881 " toserver_sp_groups: 2\n"
4882 " toserver_dp_groups: 25\n"
4883 " - inspection-recursion-limit: 0\n";
4885 FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
4894 DetectEngineDeInitYamlConf();
4899 static int DetectEngineTest02(
void)
4905 " - profile: medium\n"
4906 " - custom-values:\n"
4907 " toclient_src_groups: 2\n"
4908 " toclient_dst_groups: 2\n"
4909 " toclient_sp_groups: 2\n"
4910 " toclient_dp_groups: 3\n"
4911 " toserver_src_groups: 2\n"
4912 " toserver_dst_groups: 4\n"
4913 " toserver_sp_groups: 2\n"
4914 " toserver_dp_groups: 25\n"
4915 " - inspection-recursion-limit:\n";
4917 FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
4927 DetectEngineDeInitYamlConf();
4932 static int DetectEngineTest03(
void)
4938 " - profile: medium\n"
4939 " - custom-values:\n"
4940 " toclient_src_groups: 2\n"
4941 " toclient_dst_groups: 2\n"
4942 " toclient_sp_groups: 2\n"
4943 " toclient_dp_groups: 3\n"
4944 " toserver_src_groups: 2\n"
4945 " toserver_dst_groups: 4\n"
4946 " toserver_sp_groups: 2\n"
4947 " toserver_dp_groups: 25\n";
4949 FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
4959 DetectEngineDeInitYamlConf();
4964 static int DetectEngineTest04(
void)
4970 " - profile: medium\n"
4971 " - custom-values:\n"
4972 " toclient_src_groups: 2\n"
4973 " toclient_dst_groups: 2\n"
4974 " toclient_sp_groups: 2\n"
4975 " toclient_dp_groups: 3\n"
4976 " toserver_src_groups: 2\n"
4977 " toserver_dst_groups: 4\n"
4978 " toserver_sp_groups: 2\n"
4979 " toserver_dp_groups: 25\n"
4980 " - inspection-recursion-limit: 10\n";
4982 FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
4991 DetectEngineDeInitYamlConf();
4996 static int DetectEngineTest08(
void)
5002 " - profile: custom\n"
5003 " - custom-values:\n"
5004 " toclient-groups: 23\n"
5005 " toserver-groups: 27\n";
5007 FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
5017 DetectEngineDeInitYamlConf();
5023 static int DetectEngineTest09(
void)
5029 " - profile: custom\n"
5030 " - custom-values:\n"
5031 " toclient-groups: BA\n"
5032 " toserver-groups: BA\n"
5033 " - inspection-recursion-limit: 10\n";
5035 FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
5045 DetectEngineDeInitYamlConf();