92 #define DETECT_ENGINE_DEFAULT_INSPECTION_RECURSION_LIMIT 3000
99 static uint32_t TenantIdHash(
HashTable *h,
void *
data, uint16_t data_len);
100 static char TenantIdCompare(
void *d1, uint16_t d1_len,
void *d2, uint16_t d2_len);
101 static void TenantIdFree(
void *d);
102 static uint32_t DetectEngineTenantGetIdFromLivedev(
const void *
ctx,
const Packet *p);
103 static uint32_t DetectEngineTenantGetIdFromVlanId(
const void *
ctx,
const Packet *p);
104 static uint32_t DetectEngineTenantGetIdFromPcap(
const void *
ctx,
const Packet *p);
135 FatalError(
"failed to register inspect engine %s", name);
147 FatalError(
"failed to register inspect engine %s: %s", name, strerror(errno));
149 new_engine->
sm_list = (uint16_t)sm_list;
154 if (g_pkt_inspect_engines == NULL) {
155 g_pkt_inspect_engines = new_engine;
158 while (t->
next != NULL) {
162 t->
next = new_engine;
169 static void AppLayerInspectEngineRegisterInternal(
const char *name,
AppProto alproto, uint32_t dir,
178 FatalError(
"failed to register inspect engine %s", name);
184 (progress < 0 || progress >= SHRT_MAX) || (Callback == NULL)) {
188 SCLogError(
"Invalid arguments: must register "
189 "GetData with DetectEngineInspectBufferGeneric");
192 SCLogError(
"Invalid arguments: must register "
193 "GetData with DetectEngineInspectMultiBufferGeneric");
205 AppLayerInspectEngineRegisterInternal(
206 name,
ALPROTO_DOH2, dir, progress, Callback, GetData, GetMultiData);
215 new_engine->
dir = direction;
216 new_engine->
sm_list = (uint16_t)sm_list;
218 new_engine->
progress = (int16_t)progress;
226 if (g_app_inspect_engines == NULL) {
227 g_app_inspect_engines = new_engine;
230 while (t->
next != NULL) {
234 t->
next = new_engine;
241 AppLayerInspectEngineRegisterInternal(name, alproto, dir, progress, Callback, GetData, NULL);
245 static void DetectAppLayerInspectEngineCopy(
247 int sm_list,
int new_list,
260 new_engine->
sm_list = (uint16_t)new_list;
264 new_engine->
v2 = t->
v2;
271 while (list->
next != NULL) {
275 list->
next = new_engine;
297 new_engine->
v2 = t->
v2;
302 list->
next = new_engine;
311 static void DetectPktInspectEngineCopy(
313 int sm_list,
int new_list,
324 new_engine->
sm_list = (uint16_t)new_list;
327 new_engine->
v1 = t->
v1;
334 while (list->
next != NULL) {
338 list->
next = new_engine;
357 new_engine->
v1 = t->
v1;
363 while (list->
next != NULL) {
367 list->
next = new_engine;
382 FatalError(
"failed to register inspect engine %s", name);
399 FatalError(
"failed to register inspect engine %s: %s", name, strerror(errno));
401 new_engine->
sm_list = (uint16_t)sm_list;
403 new_engine->
dir = direction;
412 while (list->
next != NULL) {
416 list->
next = new_engine;
435 new_engine->
sm_list = (uint16_t)new_list;
441 new_engine->
v1 = t->
v1;
446 while (list->
next != NULL) {
450 list->
next = new_engine;
472 new_engine->
v1 = t->
v1;
478 while (list->
next != NULL) {
482 list->
next = new_engine;
494 static void AppendStreamInspectEngine(
497 bool prepend =
false;
506 new_engine->
mpm =
true;
509 new_engine->
dir = direction;
510 new_engine->
stream =
true;
513 new_engine->
smd = stream;
521 }
else if (prepend) {
528 while (a->
next != NULL) {
532 a->
next = new_engine;
535 SCLogDebug(
"sid %u: engine %p/%u added", s->
id, new_engine, new_engine->
id);
542 bool prepend =
false;
565 new_engine->
mpm =
true;
571 new_engine->
smd = smd;
572 new_engine->
v1 = u->
v1;
578 }
else if (prepend) {
583 while (a->
next != NULL) {
587 a->
next = new_engine;
595 bool prepend =
false;
605 new_engine->
mpm =
true;
610 new_engine->
smd = smd;
611 new_engine->
v1 = e->
v1;
617 }
else if (prepend) {
622 while (a->
next != NULL) {
626 a->
next = new_engine;
632 const int mpm_list,
const int files_id, uint8_t *last_id,
bool *head_is_mpm)
646 SCLogDebug(
"app engine: t %p t->id %u => alproto:%s files:%s", t, t->
id,
654 bool prepend =
false;
659 new_engine->
mpm =
true;
666 new_engine->
smd = smd;
668 new_engine->
v2 = t->
v2;
674 if (new_engine->
sm_list == files_id) {
676 SCLogDebug(
"sid %u: engine %p/%u is FILE ENGINE", s->
id, new_engine, new_engine->
id);
679 SCLogDebug(
"sid %u: engine %p/%u %s", s->
id, new_engine, new_engine->
id,
687 if (new_engine->
sm_list == files_id) {
689 SCLogDebug(
"sid %u: engine %p/%u is FILE ENGINE", s->
id, new_engine, new_engine->
id);
691 new_engine->
id = ++(*last_id);
692 SCLogDebug(
"sid %u: engine %p/%u %s", s->
id, new_engine, new_engine->
id,
698 while (a->
next != NULL) {
706 a->
next = new_engine;
707 if (new_engine->
sm_list == files_id) {
709 SCLogDebug(
"sid %u: engine %p/%u is FILE ENGINE", s->
id, new_engine, new_engine->
id);
711 new_engine->
id = ++(*last_id);
712 SCLogDebug(
"sid %u: engine %p/%u %s", s->
id, new_engine, new_engine->
id,
717 SCLogDebug(
"sid %u: engine %p/%u added", s->
id, new_engine, new_engine->
id);
730 bool head_is_mpm =
false;
744 u != NULL; u = u->
next) {
746 AppendFrameInspectEngine(
de_ctx, u, s, smd, mpm_list);
755 AppendPacketInspectEngine(
de_ctx, e, s, smd, mpm_list);
764 AppendAppInspectEngine(
765 de_ctx, t, s, smd, mpm_list, files_id, &last_id, &head_is_mpm);
778 AppendStreamInspectEngine(s, stream, 0, last_id + 1);
780 AppendStreamInspectEngine(s, stream, 1, last_id + 1);
782 AppendStreamInspectEngine(s, stream, 0, last_id + 1);
783 AppendStreamInspectEngine(s, stream, 1, last_id + 1);
797 iter->
sm_list == mpm_list ?
"MPM" :
"");
848 for (
int i = 0; i < arrays; i++) {
849 if (bufs[i] == ie->
smd) {
855 bufs[arrays++] = ie->
smd;
865 for (
int i = 0; i < arrays; i++) {
866 if (bufs[i] == e->
smd) {
872 bufs[arrays++] = e->
smd;
882 for (
int i = 0; i < arrays; i++) {
883 if (bufs[i] == u->
smd) {
889 bufs[arrays++] = u->
smd;
895 for (
int i = 0; i < engines; i++) {
917 static int g_buffer_type_reg_closed = 0;
921 return g_buffer_type_id;
924 static uint32_t DetectBufferTypeHashNameFunc(
HashListTable *ht,
void *data, uint16_t datalen)
933 static uint32_t DetectBufferTypeHashIdFunc(
HashListTable *ht,
void *data, uint16_t datalen)
936 uint32_t hash = map->
id;
941 static char DetectBufferTypeCompareNameFunc(
void *data1, uint16_t len1,
void *data2, uint16_t len2)
946 char r = (strcmp(map1->
name, map2->
name) == 0);
951 static char DetectBufferTypeCompareIdFunc(
void *data1, uint16_t len1,
void *data2, uint16_t len2)
955 return map1->
id == map2->
id;
958 static void DetectBufferTypeFreeFunc(
void *data)
971 SCLogError(
"%s allocates transform option memory but has no free routine",
981 static int DetectBufferTypeInit(
void)
983 BUG_ON(g_buffer_type_hash);
985 DetectBufferTypeCompareNameFunc, DetectBufferTypeFreeFunc);
986 if (g_buffer_type_hash == NULL)
992 static void DetectBufferTypeFree(
void)
994 if (g_buffer_type_hash == NULL)
998 g_buffer_type_hash = NULL;
1001 static int DetectBufferTypeAdd(
const char *
string)
1003 BUG_ON(
string == NULL || strlen(
string) >= 32);
1010 map->
id = g_buffer_type_id++;
1020 memset(&map, 0,
sizeof(map));
1029 BUG_ON(g_buffer_type_reg_closed);
1030 if (g_buffer_type_hash == NULL)
1031 DetectBufferTypeInit();
1035 return DetectBufferTypeAdd(name);
1043 BUG_ON(g_buffer_type_reg_closed);
1048 SCLogDebug(
"%p %s -- %d supports multi instance", exists, name, exists->
id);
1053 BUG_ON(g_buffer_type_reg_closed);
1057 exists->
frame =
true;
1058 SCLogDebug(
"%p %s -- %d supports frame inspection", exists, name, exists->
id);
1063 BUG_ON(g_buffer_type_reg_closed);
1068 SCLogDebug(
"%p %s -- %d supports packet inspection", exists, name, exists->
id);
1073 BUG_ON(g_buffer_type_reg_closed);
1078 SCLogDebug(
"%p %s -- %d supports mpm", exists, name, exists->
id);
1083 BUG_ON(g_buffer_type_reg_closed);
1088 SCLogDebug(
"%p %s -- %d supports transformations", exists, name, exists->
id);
1104 memset(&map, 0,
sizeof(map));
1114 memset(&lookup, 0,
sizeof(lookup));
1124 return res ? res->
name : NULL;
1129 BUG_ON(
string == NULL || strlen(
string) >= 32);
1145 const int direction,
const AppProto alproto,
const uint8_t frame_type)
1152 const int buffer_id = DetectEngineBufferTypeAdd(
de_ctx, name);
1153 if (buffer_id < 0) {
1182 return DetectEngineBufferTypeAdd(
de_ctx, name);
1190 BUG_ON(desc == NULL || strlen(desc) >= 128);
1221 exists->
frame =
true;
1222 SCLogDebug(
"%p %s -- %d supports frame inspection", exists, name, exists->
id);
1230 SCLogDebug(
"%p %s -- %d supports packet inspection", exists, name, exists->
id);
1238 SCLogDebug(
"%p %s -- %d supports mpm", exists, name, exists->
id);
1246 SCLogDebug(
"%p %s -- %d supports transformations", exists, name, exists->
id);
1288 BUG_ON(g_buffer_type_reg_closed);
1304 bool (*ValidateCallback)(
const Signature *,
const char **sigerror))
1306 BUG_ON(g_buffer_type_reg_closed);
1359 SCLogError(
"Rule buffer cannot be reset after base64_data.");
1364 SCLogError(
"no matches following transform(s)");
1372 SCLogError(
"previous sticky buffer has no matches");
1382 if ((uint32_t)list == b->
id) {
1383 SCLogDebug(
"found buffer %p for list %d", b, list);
1386 SCLogDebug(
"sm_init was true for %p list %d", b, list);
1405 SCLogError(
"failed to expand rule buffer array");
1429 SCLogError(
"previous transforms not consumed "
1430 "(list: %u, transform_cnt %u)",
1435 SCLogDebug(
"buffer %d has transform(s) registered: %d",
1439 if (new_list == -1) {
1451 SCLogError(
"failed to expand rule buffer array");
1464 SCLogDebug(
"new list after applying transforms: %u", new_list);
1487 for (uint32_t x = 0; x <= mbuffer->
max; x++) {
1507 if (!buffer->
init) {
1528 if (local_id >= fb->
size) {
1529 uint32_t old_size = fb->
size;
1530 uint32_t new_size = local_id + 1;
1531 uint32_t grow_by = new_size - old_size;
1532 SCLogDebug(
"size is %u, need %u, so growing by %u", old_size, new_size, grow_by);
1540 SCLogDebug(
"ptr %p to_zero %p", ptr, to_zero);
1543 fb->
size = new_size;
1549 #ifdef DEBUG_VALIDATION
1550 buffer->multi =
true;
1557 memset(buffer, 0,
sizeof(*buffer));
1558 buffer->
buf =
SCCalloc(initial_size,
sizeof(uint8_t));
1559 if (buffer->
buf != NULL) {
1560 buffer->
size = initial_size;
1567 #ifdef DEBUG_VALIDATION
1579 const uint8_t *data,
const uint32_t data_len)
1581 #ifdef DEBUG_VALIDATION
1596 #ifdef DEBUG_VALIDATION
1600 if (buffer->
inspect == NULL) {
1602 if (det_ctx && list_id != -1)
1614 if (buffer->
buf != NULL) {
1617 memset(buffer, 0,
sizeof(*buffer));
1629 uint32_t new_size = (buffer->
size == 0) ? 4096 : buffer->
size;
1630 while (new_size < min_size) {
1637 buffer->
size = new_size;
1646 uint32_t copy_size =
MIN(buf_len, buffer->
size);
1647 memcpy(buffer->
buf, buf, copy_size);
1673 const uint8_t *content, uint16_t content_len,
const char **namestr)
1714 const int size = g_buffer_type_id;
1718 DetectBufferTypeCompareNameFunc, DetectBufferTypeFreeFunc);
1721 HashListTableInit(256, DetectBufferTypeHashIdFunc, DetectBufferTypeCompareIdFunc,
1733 memcpy(copy, map,
sizeof(*copy));
1739 SCLogDebug(
"name %s id %d mpm %s packet %s -- %s. "
1740 "Callbacks: Setup %p Validate %p",
1741 map->
name, map->
id, map->
mpm ?
"true" :
"false", map->
packet ?
"true" :
"false",
1748 DetectAppLayerInspectEngineCopyListToDetectCtx(
de_ctx);
1750 DetectFrameInspectEngineCopyListToDetectCtx(
de_ctx);
1752 DetectPktInspectEngineCopyListToDetectCtx(
de_ctx);
1794 while (framemlist) {
1805 BUG_ON(g_buffer_type_hash == NULL);
1807 g_buffer_type_reg_closed = 1;
1818 SCLogError(
"buffer '%s' does not support transformations", base_map->
name);
1825 memset(&t, 0,
sizeof(t));
1826 for (
int i = 0; i < transform_cnt; i++) {
1829 t.
cnt = transform_cnt;
1832 memset(&lookup_map, 0,
sizeof(lookup_map));
1850 map->
mpm = base_map->
mpm;
1857 }
else if (map->
packet) {
1867 SCLogDebug(
"buffer %s registered with id %d, parent %d", map->name, map->id, map->parent_id);
1870 DetectFrameInspectEngineCopy(
de_ctx, map->parent_id, map->id, &map->transforms);
1871 }
else if (map->packet) {
1872 DetectPktInspectEngineCopy(
de_ctx, map->parent_id, map->id, &map->transforms);
1874 DetectAppLayerInspectEngineCopy(
de_ctx, map->parent_id, map->id, &map->transforms);
1880 static int DetectEngineInspectRulePacketMatches(
1884 Packet *p, uint8_t *_alert_flags)
1892 SCLogDebug(
"running match functions, sm %p", smd);
1910 static int DetectEngineInspectRulePayloadMatches(
1932 SCLogDebug(
"no match in stream, fall back to packet payload");
1940 SCLogDebug(
"SIG_FLAG_REQUIRE_STREAM_ONLY, so no match");
1958 uint8_t *alert_flags)
1964 SCLogDebug(
"sid %u: e %p Callback returned no match", s->
id, e);
1967 SCLogDebug(
"sid %u: e %p Callback returned true", s->
id, e);
1986 e->
sm_list = (uint16_t)list_id;
1995 while (a->
next != NULL) {
2007 if (DetectEnginePktInspectionAppend(
2010 SCLogDebug(
"sid %u: DetectEngineInspectRulePayloadMatches appended", s->
id);
2014 if (DetectEnginePktInspectionAppend(
2017 SCLogDebug(
"sid %u: DetectEngineInspectRulePacketMatches appended", s->
id);
2099 uint8_t
flags,
void *alstate,
void *txv, uint64_t tx_id)
2102 SCLogDebug(
"running match functions, sm %p", smd);
2108 AppLayerTxMatch(det_ctx, f,
flags, alstate, txv, s, smd->
ctx);
2142 void *alstate,
void *txv, uint64_t tx_id)
2144 const int list_id = engine->
sm_list;
2145 SCLogDebug(
"running inspect on %d", list_id);
2159 f,
flags, txv, list_id);
2166 const uint8_t *data = buffer->
inspect;
2171 ci_flags |= buffer->
flags;
2190 AppLayerInspectEngineRegisterInternal(
2193 alproto, tx_min_progress);
2198 const Signature *s,
Flow *f, uint8_t
flags,
void *alstate,
void *txv, uint64_t tx_id)
2200 uint32_t local_id = 0;
2208 det_ctx, transforms, f,
flags, txv, engine->
sm_list, local_id);
2210 if (buffer == NULL || buffer->
inspect == NULL)
2241 const int list_id = engine->
sm_list;
2242 SCLogDebug(
"running inspect on %d", list_id);
2260 ci_flags |= buffer->
flags;
2278 static void InjectPackets(
ThreadVars **detect_tvs,
2280 int no_of_detect_tvs)
2284 for (
int i = 0; i < no_of_detect_tvs; i++) {
2285 if (
SC_ATOMIC_GET(new_det_ctx[i]->so_far_used_by_detect) != 1) {
2286 if (detect_tvs[i]->inq != NULL) {
2323 if (no_of_detect_tvs == 0) {
2333 memset(detect_tvs, 0x00, (no_of_detect_tvs *
sizeof(
ThreadVars *)));
2358 if (new_det_ctx[i] == NULL) {
2360 "failure in live rule swap. Let's get out of here");
2364 SCLogDebug(
"live rule swap created new det_ctx - %p and de_ctx "
2365 "- %p\n", new_det_ctx[i], new_de_ctx);
2370 BUG_ON(i != no_of_detect_tvs);
2383 SCLogDebug(
"swapping new det_ctx - %p with older one - %p",
2394 SCLogDebug(
"Live rule swap has swapped %d old det_ctx's with new ones, "
2395 "along with the new de_ctx", no_of_detect_tvs);
2397 InjectPackets(detect_tvs, new_det_ctx, no_of_detect_tvs);
2401 uint32_t threads_done = 0;
2403 for (i = 0; i < no_of_detect_tvs; i++) {
2405 threads_done = no_of_detect_tvs;
2409 if (
SC_ATOMIC_GET(new_det_ctx[i]->so_far_used_by_detect) == 1) {
2410 SCLogDebug(
"new_det_ctx - %p used by detect engine", new_det_ctx[i]);
2413 TmThreadsCaptureBreakLoop(detect_tvs[i]);
2416 if (threads_done < no_of_detect_tvs) {
2427 if (i != no_of_detect_tvs) {
2440 for (i = 0; i < no_of_detect_tvs; i++) {
2441 SCLogDebug(
"Freeing old_det_ctx - %p used by detect",
2451 for (i = 0; i < no_of_detect_tvs; i++) {
2452 if (new_det_ctx[i] != NULL)
2478 if (prefix != NULL) {
2482 int failure_fatal = 0;
2483 if (
ConfGetBool(
"engine.init-failure-fatal", (
int *)&failure_fatal) != 1) {
2484 SCLogDebug(
"ConfGetBool could not load the value.");
2496 SCLogDebug(
"Unable to alloc SpmGlobalThreadCtx.");
2508 if (DetectEngineCtxLoadConf(
de_ctx) == -1) {
2517 DetectBufferTypeSetupDetectEngine(
de_ctx);
2565 if (prefix == NULL || strlen(prefix) == 0)
2603 #ifdef PROFILE_RULES
2604 if (
de_ctx->profile_ctx != NULL) {
2606 de_ctx->profile_ctx = NULL;
2646 DetectEngineCtxFreeThreadKeywordData(
de_ctx);
2648 DetectEngineCtxFreeFailedSigs(
de_ctx);
2668 DetectBufferTypeFreeDetectEngine(
de_ctx);
2694 const char *max_uniq_toclient_groups_str = NULL;
2695 const char *max_uniq_toserver_groups_str = NULL;
2696 const char *sgh_mpm_context = NULL;
2697 const char *de_ctx_profile = NULL;
2699 (void)
ConfGet(
"detect.profile", &de_ctx_profile);
2700 (void)
ConfGet(
"detect.sgh-mpm-context", &sgh_mpm_context);
2705 if (de_ctx_custom != NULL) {
2707 if (de_ctx_profile == NULL) {
2708 if (opt->
val && strcmp(opt->
val,
"profile") == 0) {
2709 de_ctx_profile = opt->head.tqh_first->
val;
2713 if (sgh_mpm_context == NULL) {
2714 if (opt->
val && strcmp(opt->
val,
"sgh-mpm-context") == 0) {
2715 sgh_mpm_context = opt->head.tqh_first->
val;
2721 if (de_ctx_profile != NULL) {
2722 if (strcmp(de_ctx_profile,
"low") == 0 ||
2723 strcmp(de_ctx_profile,
"lowest") == 0) {
2725 }
else if (strcmp(de_ctx_profile,
"medium") == 0) {
2727 }
else if (strcmp(de_ctx_profile,
"high") == 0 ||
2728 strcmp(de_ctx_profile,
"highest") == 0) {
2730 }
else if (strcmp(de_ctx_profile,
"custom") == 0) {
2733 SCLogError(
"invalid value for detect.profile: '%s'. "
2734 "Valid options: low, medium, high and custom.",
2739 SCLogDebug(
"Profile for detection engine groups is \"%s\"", de_ctx_profile);
2741 SCLogDebug(
"Profile for detection engine groups not provided "
2742 "at suricata.yaml. Using default (\"medium\").");
2746 if (sgh_mpm_context == NULL || strcmp(sgh_mpm_context,
"auto") == 0) {
2756 if (strcmp(sgh_mpm_context,
"single") == 0) {
2758 }
else if (strcmp(sgh_mpm_context,
"full") == 0) {
2762 "invalid conf value for detect-engine.sgh-mpm-context-"
2787 (void)
ConfGet(
"detect.custom-values.toclient-groups",
2788 &max_uniq_toclient_groups_str);
2789 (void)
ConfGet(
"detect.custom-values.toserver-groups",
2790 &max_uniq_toserver_groups_str);
2792 if (de_ctx_custom != NULL) {
2794 if (opt->
val && strcmp(opt->
val,
"custom-values") == 0) {
2795 if (max_uniq_toclient_groups_str == NULL) {
2797 (opt->head.tqh_first,
"toclient-sp-groups");
2799 if (max_uniq_toclient_groups_str == NULL) {
2801 (opt->head.tqh_first,
"toclient-groups");
2803 if (max_uniq_toserver_groups_str == NULL) {
2805 (opt->head.tqh_first,
"toserver-dp-groups");
2807 if (max_uniq_toserver_groups_str == NULL) {
2809 (opt->head.tqh_first,
"toserver-groups");
2814 if (max_uniq_toclient_groups_str != NULL) {
2816 (uint16_t)strlen(max_uniq_toclient_groups_str),
2817 (
const char *)max_uniq_toclient_groups_str) <= 0) {
2821 "toclient-groups failed, using %u",
2829 if (max_uniq_toserver_groups_str != NULL) {
2831 (uint16_t)strlen(max_uniq_toserver_groups_str),
2832 (
const char *)max_uniq_toserver_groups_str) <= 0) {
2836 "toserver-groups failed, using %u",
2855 if (
ConfGetInt(
"detect.inspection-recursion-limit", &value) == 1)
2857 if (value >= 0 && value <= INT_MAX) {
2863 ConfNode *insp_recursion_limit_node = NULL;
2864 char *insp_recursion_limit = NULL;
2866 if (de_ctx_custom != NULL) {
2869 if (opt->
val && strcmp(opt->
val,
"inspection-recursion-limit") != 0)
2873 if (insp_recursion_limit_node == NULL) {
2875 "entry for detect-engine:inspection-recursion-limit");
2878 insp_recursion_limit = insp_recursion_limit_node->
val;
2879 SCLogDebug(
"Found detect-engine.inspection-recursion-limit - %s:%s",
2880 insp_recursion_limit_node->
name, insp_recursion_limit_node->
val);
2884 if (insp_recursion_limit != NULL) {
2886 0, (
const char *)insp_recursion_limit) < 0) {
2888 "detect-engine.inspection-recursion-limit: %s "
2904 SCLogDebug(
"de_ctx->inspection_recursion_limit: %d",
2909 if (
ConfGetInt(
"detect.stream-tx-log-limit", &value) == 1) {
2910 if (value >= 0 && value <= UINT8_MAX) {
2913 SCLogWarning(
"Invalid value for detect-engine.stream-tx-log-limit: must be between 0 "
2914 "and 255, will default to 4");
2920 const char *ports = NULL;
2921 (void)
ConfGet(
"detect.grouping.tcp-whitelist", &ports);
2925 ports =
"53, 80, 139, 443, 445, 1433, 3306, 3389, 6666, 6667, 8080";
2926 SCLogConfig(
"grouping: tcp-whitelist (default) %s", ports);
2931 "for detect.grouping.tcp-whitelist",
2935 for ( ; x != NULL; x = x->
next) {
2938 "for detect.grouping.tcp-whitelist: only single ports allowed",
2947 (void)
ConfGet(
"detect.grouping.udp-whitelist", &ports);
2951 ports =
"53, 135, 5060";
2952 SCLogConfig(
"grouping: udp-whitelist (default) %s", ports);
2957 "for detect.grouping.udp-whitelist",
2963 "for detect.grouping.udp-whitelist: only single ports allowed",
2972 const char *pf_setting = NULL;
2973 if (
ConfGet(
"detect.prefilter.default", &pf_setting) == 1 && pf_setting) {
2974 if (strcasecmp(pf_setting,
"mpm") == 0) {
2976 }
else if (strcasecmp(pf_setting,
"auto") == 0) {
2985 SCLogConfig(
"prefilter engines: MPM and keywords");
3014 SCLogError(
"setting up thread local detect ctx");
3023 SCLogError(
"setting up thread local detect ctx "
3024 "for keyword \"%s\" failed",
3062 SCLogError(
"setting up thread local detect ctx");
3074 SCLogError(
"setting up thread local detect ctx "
3075 "for keyword \"%s\" failed",
3105 uint32_t map_array_size = 0;
3106 uint32_t map_cnt = 0;
3107 uint32_t max_tenant_id = 0;
3113 "set using multi-detect.selector");
3126 mt_det_ctxs_hash =
HashTableInit(tcnt * 2, TenantIdHash, TenantIdCompare, TenantIdFree);
3127 if (mt_det_ctxs_hash == NULL) {
3132 SCLogInfo(
"no tenants left, or none registered yet");
3143 map_array_size = map_cnt + 1;
3145 map_array =
SCCalloc(map_array_size,
sizeof(*map_array));
3146 if (map_array == NULL)
3153 if (map_cnt >= map_array_size) {
3165 list = master->
list;
3170 if (mt_det_ctx == NULL)
3172 if (
HashTableAdd(mt_det_ctxs_hash, mt_det_ctx, 0) != 0) {
3181 mt_det_ctxs_hash = NULL;
3193 det_ctx->
TenantGetId = DetectEngineTenantGetIdFromVlanId;
3197 det_ctx->
TenantGetId = DetectEngineTenantGetIdFromLivedev;
3201 det_ctx->
TenantGetId = DetectEngineTenantGetIdFromPcap;
3208 if (map_array != NULL)
3210 if (mt_det_ctxs_hash != NULL)
3291 DetectEngineThreadCtxInitKeywords(
de_ctx, det_ctx);
3292 DetectEngineThreadCtxInitGlobalKeywords(det_ctx);
3293 #ifdef PROFILE_RULES
3331 if (det_ctx->
de_ctx == NULL) {
3381 if (DetectEngineThreadCtxInitForMT(
tv, det_ctx) !=
TM_ECODE_OK) {
3388 *data = (
void *)det_ctx;
3412 if (det_ctx->
de_ctx == NULL) {
3444 if (DetectEngineThreadCtxInitForMT(
tv, det_ctx) !=
TM_ECODE_OK) {
3457 SCLogDebug(
"PACKET PKT_STREAM_ADD: %"PRIu64, det_ctx->pkt_stream_add_cnt);
3459 SCLogDebug(
"PAYLOAD MPM %"PRIu64
"/%"PRIu64, det_ctx->payload_mpm_cnt, det_ctx->payload_mpm_size);
3460 SCLogDebug(
"STREAM MPM %"PRIu64
"/%"PRIu64, det_ctx->stream_mpm_cnt, det_ctx->stream_mpm_size);
3462 SCLogDebug(
"PAYLOAD SIG %"PRIu64
"/%"PRIu64, det_ctx->payload_persig_cnt, det_ctx->payload_persig_size);
3463 SCLogDebug(
"STREAM SIG %"PRIu64
"/%"PRIu64, det_ctx->stream_persig_cnt, det_ctx->stream_persig_size);
3471 #ifdef PROFILE_RULES
3481 if (det_ctx->
de_ctx != NULL) {
3521 for (uint32_t x = 0; x < fb->
size; x++) {
3532 DetectEngineThreadCtxDeinitGlobalKeywords(det_ctx);
3533 if (det_ctx->
de_ctx != NULL) {
3534 DetectEngineThreadCtxDeinitKeywords(det_ctx->
de_ctx, det_ctx);
3554 if (det_ctx == NULL) {
3563 DetectEngineThreadCtxFree(det_ctx);
3568 static uint32_t DetectKeywordCtxHashFunc(
HashListTable *ht,
void *data, uint16_t datalen)
3571 const char *name =
ctx->name;
3572 uint64_t hash =
StringHashDjb2((
const uint8_t *)name, strlen(name)) + (ptrdiff_t)
ctx->data;
3577 static char DetectKeywordCtxCompareFunc(
void *data1, uint16_t len1,
void *data2, uint16_t len2)
3581 const char *name1 = ctx1->
name;
3582 const char *name2 = ctx2->
name;
3583 return (strcmp(name1, name2) == 0 && ctx1->
data == ctx2->
data);
3586 static void DetectKeywordCtxFreeFunc(
void *ptr)
3609 BUG_ON(
de_ctx == NULL || InitFunc == NULL || FreeFunc == NULL);
3613 DetectKeywordCtxHashFunc, DetectKeywordCtxCompareFunc, DetectKeywordCtxFreeFunc);
3698 void *(*InitFunc)(
void *),
void *data,
void (*FreeFunc)(
void *))
3701 BUG_ON(InitFunc == NULL || FreeFunc == NULL);
3707 while (item != NULL) {
3708 if (strcmp(name, item->
name) == 0) {
3758 if (master->
list == NULL) {
3834 static int DetectEngineMultiTenantLoadTenant(uint32_t tenant_id,
const char *filename,
int loader_id)
3839 snprintf(prefix,
sizeof(prefix),
"multi-detect.%u", tenant_id);
3842 if (
SCStatFn(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);
3893 static int DetectEngineMultiTenantReloadTenant(uint32_t tenant_id,
const char *filename,
int reload_cnt)
3896 if (old_de_ctx == NULL) {
3897 SCLogError(
"tenant detect engine not found");
3901 if (filename == NULL)
3905 snprintf(prefix,
sizeof(prefix),
"multi-detect.%u.reload.%d", tenant_id, reload_cnt);
3916 SCLogError(
"failed to properly setup yaml %s", filename);
3921 if (new_de_ctx == NULL) {
3934 goto new_de_ctx_error;
3939 goto new_de_ctx_error;
3964 static void DetectLoaderFreeTenant(
void *
ctx)
3967 if (t->
yaml != NULL) {
3973 static int DetectLoaderFuncLoadTenant(
void *vctx,
int loader_id)
3978 if (DetectEngineMultiTenantLoadTenant(
ctx->tenant_id,
ctx->yaml, loader_id) != 0) {
3984 static int DetectLoaderSetupLoadTenant(uint32_t tenant_id,
const char *yaml)
3992 if (t->
yaml == NULL) {
4000 static int DetectLoaderFuncReloadTenant(
void *vctx,
int loader_id)
4006 if (DetectEngineMultiTenantReloadTenant(
ctx->tenant_id,
ctx->yaml,
ctx->reload_cnt) != 0) {
4012 static int DetectLoaderSetupReloadTenants(
const int reload_cnt)
4031 loader_id, DetectLoaderFuncReloadTenant, t, DetectLoaderFreeTenant);
4045 static int DetectLoaderSetupReloadTenant(uint32_t tenant_id,
const char *yaml,
int reload_cnt)
4048 if (old_de_ctx == NULL)
4060 if (t->
yaml == NULL) {
4070 loader_id, DetectLoaderFuncReloadTenant, t, DetectLoaderFreeTenant);
4077 int r = DetectLoaderSetupLoadTenant(tenant_id, yaml);
4091 int r = DetectLoaderSetupReloadTenant(tenant_id, yaml, reload_cnt);
4105 int r = DetectLoaderSetupReloadTenants(reload_cnt);
4115 static int DetectEngineMultiTenantSetupLoadLivedevMappings(
const ConfNode *mappings_root_node,
4120 int mapping_cnt = 0;
4121 if (mappings_root_node != NULL) {
4124 if (tenant_id_node == NULL)
4127 if (device_node == NULL)
4130 uint32_t tenant_id = 0;
4132 tenant_id_node->
val) < 0) {
4135 tenant_id_node->
val);
4139 const char *dev = device_node->
val;
4158 SCLogConfig(
"device %s connected to tenant-id %u", dev, tenant_id);
4167 SCLogConfig(
"%d device - tenant-id mappings defined", mapping_cnt);
4174 static int DetectEngineMultiTenantSetupLoadVlanMappings(
const ConfNode *mappings_root_node,
4179 int mapping_cnt = 0;
4180 if (mappings_root_node != NULL) {
4183 if (tenant_id_node == NULL)
4186 if (vlan_id_node == NULL)
4189 uint32_t tenant_id = 0;
4191 tenant_id_node->
val) < 0) {
4194 tenant_id_node->
val);
4198 uint16_t vlan_id = 0;
4200 &vlan_id, 10, (uint16_t)strlen(vlan_id_node->
val), vlan_id_node->
val) < 0) {
4206 if (vlan_id == 0 || vlan_id >= 4095) {
4208 "of %s is invalid. Valid range 1-4094.",
4216 SCLogConfig(
"vlan %u connected to tenant-id %u", vlan_id, tenant_id);
4242 int failure_fatal = 0;
4243 (void)
ConfGetBool(
"engine.init-failure-fatal", &failure_fatal);
4246 (void)
ConfGetBool(
"multi-detect.enabled", &enabled);
4256 const char *handler = NULL;
4257 if (
ConfGet(
"multi-detect.selector", &handler) == 1) {
4258 SCLogConfig(
"multi-tenant selector type %s", handler);
4260 if (strcmp(handler,
"vlan") == 0) {
4264 if ((
ConfGetBool(
"vlan.use-for-tracking", &vlanbool)) == 1 && vlanbool == 0) {
4266 "can't use multi-detect selector 'vlan'");
4271 }
else if (strcmp(handler,
"direct") == 0) {
4273 }
else if (strcmp(handler,
"device") == 0) {
4276 SCLogWarning(
"multi-tenant 'device' mode not supported for IPS");
4283 "multi-detect.selector",
4290 SCLogConfig(
"multi-detect is enabled (multi tenancy). Selector: %s", handler);
4296 int mapping_cnt = DetectEngineMultiTenantSetupLoadVlanMappings(mappings_root_node,
4298 if (mapping_cnt == 0) {
4304 SCLogNotice(
"no tenant traffic mappings defined, "
4305 "tenants won't be used until mappings are added");
4307 if (failure_fatal) {
4308 SCLogError(
"no multi-detect mappings defined");
4316 int mapping_cnt = DetectEngineMultiTenantSetupLoadLivedevMappings(mappings_root_node,
4318 if (mapping_cnt == 0) {
4319 if (failure_fatal) {
4320 SCLogError(
"no multi-detect mappings defined");
4332 if (tenants_root_node != NULL) {
4333 const char *path = NULL;
4336 path = path_node->
val;
4342 if (id_node == NULL) {
4346 if (yaml_node == NULL) {
4350 uint32_t tenant_id = 0;
4352 &tenant_id, 10, (uint16_t)strlen(id_node->
val), id_node->
val) < 0) {
4360 char yaml_path[PATH_MAX] =
"";
4364 strlcpy(yaml_path, yaml_node->
val,
sizeof(yaml_path));
4371 snprintf(prefix,
sizeof(prefix),
"multi-detect.%u", tenant_id);
4373 SCLogError(
"failed to load yaml %s", yaml_path);
4377 int r = DetectLoaderSetupLoadTenant(tenant_id, yaml_path);
4398 SCLogDebug(
"multi-detect not enabled (multi tenancy)");
4405 static uint32_t DetectEngineTenantGetIdFromVlanId(
const void *
ctx,
const Packet *p)
4409 uint32_t vlan_id = 0;
4429 static uint32_t DetectEngineTenantGetIdFromLivedev(
const void *
ctx,
const Packet *p)
4434 if (ld == NULL || det_ctx == NULL)
4441 static int DetectEngineTenantRegisterSelector(
4448 SCLogInfo(
"conflicting selector already set");
4455 if (
m->traffic_id == traffic_id) {
4456 SCLogInfo(
"traffic id already registered");
4477 SCLogDebug(
"tenant handler %u %u %u registered", selector, tenant_id, traffic_id);
4482 static int DetectEngineTenantUnregisterSelector(
4506 SCLogInfo(
"tenant handler %u %u %u unregistered", selector, tenant_id, traffic_id);
4520 return DetectEngineTenantRegisterSelector(
4531 return DetectEngineTenantUnregisterSelector(
TENANT_SELECTOR_VLAN, tenant_id, (uint32_t)vlan_id);
4546 static uint32_t DetectEngineTenantGetIdFromPcap(
const void *
ctx,
const Packet *p)
4556 if (master->
list == NULL) {
4579 BUG_ON((*de_ctx)->ref_cnt == 0);
4580 (*de_ctx)->ref_cnt--;
4588 if (instance == NULL)
4591 if (master->
list == NULL) {
4592 master->
list = instance;
4595 master->
list = instance;
4612 r = DetectEngineAddToList(
de_ctx);
4620 if (instance == NULL) {
4625 if (instance ==
de_ctx) {
4629 instance = instance->
next;
4634 if (instance ==
de_ctx) {
4642 if (instance == NULL) {
4648 instance->
next = NULL;
4666 ret = DetectEngineMoveToFreeListNoLock(master,
de_ctx);
4690 SCLogDebug(
"freeing detect engine %p", instance);
4712 DetectEngineMoveToFreeListNoLock(master, instance);
4719 static int reloads = 0;
4734 memset(prefix, 0,
sizeof(prefix));
4739 snprintf(prefix,
sizeof(prefix),
"detect-engine-reloads.%d", reloads++);
4766 if (old_de_ctx == NULL)
4768 SCLogDebug(
"get ref to old_de_ctx %p", old_de_ctx);
4782 if (new_de_ctx == NULL) {
4794 SCLogDebug(
"set up new_de_ctx %p", new_de_ctx);
4803 SCLogDebug(
"going to reload the threads to use new_de_ctx %p", new_de_ctx);
4805 DetectEngineReloadThreads(new_de_ctx);
4806 SCLogDebug(
"threads now run new_de_ctx %p", new_de_ctx);
4815 SCLogDebug(
"old_de_ctx should have been freed");
4819 #ifdef HAVE_MALLOC_TRIM
4830 static uint32_t TenantIdHash(
HashTable *h,
void *data, uint16_t data_len)
4836 static char TenantIdCompare(
void *d1, uint16_t d1_len,
void *d2, uint16_t d2_len)
4843 static void TenantIdFree(
void *d)
4845 DetectEngineThreadCtxFree(d);
4861 for ( ; list != NULL; list = list->
next) {
4872 if (stub_de_ctx == NULL) {
4874 if (stub_de_ctx == NULL) {
4879 if (master->
list == NULL) {
4880 master->
list = stub_de_ctx;
4883 master->
list = stub_de_ctx;
4889 DetectEngineReloadThreads(stub_de_ctx);
4899 SCLogDebug(
"old_de_ctx should have been freed");
4903 static int g_parse_metadata = 0;
4907 g_parse_metadata = 1;
4912 g_parse_metadata = 0;
4917 return g_parse_metadata;
4926 return "packet/stream payload";
4932 return "base64_data";
4935 return "post-match";
4943 return "max (internal)";
4959 static int DetectEngineInitYamlConf(
const char *conf)
4966 static void DetectEngineDeInitYamlConf(
void)
4972 static int DetectEngineTest01(
void)
4978 " - profile: medium\n"
4979 " - custom-values:\n"
4980 " toclient_src_groups: 2\n"
4981 " toclient_dst_groups: 2\n"
4982 " toclient_sp_groups: 2\n"
4983 " toclient_dp_groups: 3\n"
4984 " toserver_src_groups: 2\n"
4985 " toserver_dst_groups: 4\n"
4986 " toserver_sp_groups: 2\n"
4987 " toserver_dp_groups: 25\n"
4988 " - inspection-recursion-limit: 0\n";
4990 FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
4999 DetectEngineDeInitYamlConf();
5004 static int DetectEngineTest02(
void)
5010 " - profile: medium\n"
5011 " - custom-values:\n"
5012 " toclient_src_groups: 2\n"
5013 " toclient_dst_groups: 2\n"
5014 " toclient_sp_groups: 2\n"
5015 " toclient_dp_groups: 3\n"
5016 " toserver_src_groups: 2\n"
5017 " toserver_dst_groups: 4\n"
5018 " toserver_sp_groups: 2\n"
5019 " toserver_dp_groups: 25\n"
5020 " - inspection-recursion-limit:\n";
5022 FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
5032 DetectEngineDeInitYamlConf();
5037 static int DetectEngineTest03(
void)
5043 " - profile: medium\n"
5044 " - custom-values:\n"
5045 " toclient_src_groups: 2\n"
5046 " toclient_dst_groups: 2\n"
5047 " toclient_sp_groups: 2\n"
5048 " toclient_dp_groups: 3\n"
5049 " toserver_src_groups: 2\n"
5050 " toserver_dst_groups: 4\n"
5051 " toserver_sp_groups: 2\n"
5052 " toserver_dp_groups: 25\n";
5054 FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
5064 DetectEngineDeInitYamlConf();
5069 static int DetectEngineTest04(
void)
5075 " - profile: medium\n"
5076 " - custom-values:\n"
5077 " toclient_src_groups: 2\n"
5078 " toclient_dst_groups: 2\n"
5079 " toclient_sp_groups: 2\n"
5080 " toclient_dp_groups: 3\n"
5081 " toserver_src_groups: 2\n"
5082 " toserver_dst_groups: 4\n"
5083 " toserver_sp_groups: 2\n"
5084 " toserver_dp_groups: 25\n"
5085 " - inspection-recursion-limit: 10\n";
5087 FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
5096 DetectEngineDeInitYamlConf();
5101 static int DetectEngineTest08(
void)
5107 " - profile: custom\n"
5108 " - custom-values:\n"
5109 " toclient-groups: 23\n"
5110 " toserver-groups: 27\n";
5112 FAIL_IF(DetectEngineInitYamlConf(conf) == -1);