static uint8_t DetectEngineCtxLoadConf(DetectEngineCtx *);
-static DetectEngineMasterCtx g_master_de_ctx = { SCMUTEX_INITIALIZER, 0, NULL, NULL, };
+static DetectEngineMasterCtx g_master_de_ctx = { SCMUTEX_INITIALIZER, 0, NULL, NULL, TENANT_SELECTOR_UNKNOWN, NULL,};
static DetectEngineThreadCtx *DetectEngineThreadCtxInitForMT(ThreadVars *tv);
det_ctx->mt_det_ctxs = NULL;
}
+ if (det_ctx->tenant_array != NULL) {
+ SCFree(det_ctx->tenant_array);
+ det_ctx->tenant_array = NULL;
+ }
+
#ifdef PROFILING
SCProfilingRuleThreadCleanup(det_ctx);
SCProfilingKeywordThreadCleanup(det_ctx);
master->multi_tenant_enabled ? "enabled" : "disabled");
}
-uint32_t DetectEngineTentantGetIdFromPcap(DetectEngineThreadCtx *det_ctx, const Packet *p)
+uint32_t DetectEngineTentantGetIdFromVlanId(const void *ctx, const Packet *p)
+{
+ const DetectEngineThreadCtx *det_ctx = ctx;
+ uint32_t x = 0;
+ uint32_t vlan_id = 0;
+
+ if (p->vlan_idx == 0)
+ return 0;
+
+ vlan_id = p->vlan_id[0];
+
+ if (det_ctx == NULL || det_ctx->tenant_array == NULL || det_ctx->tenant_array_size == 0)
+ return 0;
+
+ /* not very efficient, but for now we're targeting only limited amounts.
+ * Can use hash/tree approach later. */
+ for (x = 0; x < det_ctx->tenant_array_size; x++) {
+ if (det_ctx->tenant_array[x].traffic_id == vlan_id)
+ return det_ctx->tenant_array[x].tenant_id;
+ }
+
+ return 0;
+}
+
+static int DetectEngineTentantRegisterSelector(enum DetectEngineTenantSelectors selector,
+ uint32_t tenant_id, uint32_t traffic_id)
+{
+ DetectEngineMasterCtx *master = &g_master_de_ctx;
+ SCMutexLock(&master->lock);
+
+ if (!(master->tenant_selector == TENANT_SELECTOR_UNKNOWN || master->tenant_selector == selector)) {
+ SCLogInfo("conflicting selector already set");
+ SCMutexUnlock(&master->lock);
+ return -1;
+ }
+
+ DetectEngineTenantMapping *map = SCCalloc(1, sizeof(*map));
+ if (map == NULL) {
+ SCLogInfo("memory fail");
+ SCMutexUnlock(&master->lock);
+ return -1;
+ }
+ map->traffic_id = traffic_id;
+ map->tenant_id = tenant_id;
+
+ map->next = master->tenant_mapping_list;
+ master->tenant_mapping_list = map;
+
+ master->tenant_selector = selector;
+
+ SCMutexUnlock(&master->lock);
+ return 0;
+}
+
+int DetectEngineTentantRegisterVlanId(uint32_t tenant_id, uint16_t vlan_id)
+{
+ return DetectEngineTentantRegisterSelector(TENANT_SELECTOR_VLAN, tenant_id, (uint32_t)vlan_id);
+}
+
+uint32_t DetectEngineTentantGetIdFromPcap(const void *ctx, const Packet *p)
{
return p->pcap_v.tenant_id;
}
static DetectEngineThreadCtx *DetectEngineThreadCtxInitForMT(ThreadVars *tv)
{
DetectEngineMasterCtx *master = &g_master_de_ctx;
+ DetectEngineTenantMapping *map_array = NULL;
+ uint32_t map_array_size = 0;
+ uint32_t map_cnt = 0;
int max_tenant_id = 0;
DetectEngineCtx *list = master->list;
+
while (list) {
if (list->tenant_id > max_tenant_id)
max_tenant_id = list->tenant_id;
max_tenant_id++;
+ DetectEngineTenantMapping *map = master->tenant_mapping_list;
+ while (map) {
+ map_cnt++;
+ map = map->next;
+ }
+
+ if (map_cnt > 0) {
+ map_array_size = map_cnt + 1;
+
+ map_array = SCCalloc(map_array_size, sizeof(*map_array));
+ if (map_array == NULL)
+ goto error;
+
+ /* fill the array */
+ map_cnt = 0;
+ map = master->tenant_mapping_list;
+ while (map) {
+ BUG_ON(map_cnt > map_array_size);
+ map_array[map_cnt].traffic_id = map->traffic_id;
+ map_array[map_cnt].tenant_id = map->tenant_id;
+ map_cnt++;
+ map = map->next;
+ }
+
+ }
+
DetectEngineThreadCtx **tenant_det_ctxs = SCCalloc(max_tenant_id, sizeof(DetectEngineThreadCtx *));
BUG_ON(tenant_det_ctxs == NULL);
det_ctx->mt_det_ctxs = tenant_det_ctxs;
det_ctx->mt_det_ctxs_cnt = max_tenant_id;
+ det_ctx->tenant_array = map_array;
+ det_ctx->tenant_array_size = map_array_size;
+
+ switch (master->tenant_selector) {
+ case TENANT_SELECTOR_UNKNOWN:
+ SCLogDebug("TENANT_SELECTOR_UNKNOWN");
+ break;
+ case TENANT_SELECTOR_VLAN:
+ det_ctx->TenantGetId = DetectEngineTentantGetIdFromVlanId;
+ SCLogDebug("TENANT_SELECTOR_VLAN");
+ break;
+ case TENANT_SELECTOR_DIRECT:
+ det_ctx->TenantGetId = DetectEngineTentantGetIdFromPcap;
+ SCLogDebug("TENANT_SELECTOR_DIRECT");
+ break;
+ }
+
return det_ctx;
error:
return NULL;
DetectEngineMasterCtx *master = &g_master_de_ctx;
SCMutexLock(&master->lock);
+ if (master->tenant_selector == TENANT_SELECTOR_UNKNOWN) {
+ SCLogInfo("error, no tenant selector");
+ SCMutexUnlock(&master->lock);
+ return -1;
+ }
+
DetectEngineCtx *minimal_de_ctx = NULL;
/* if we have no tenants, we need a minimal on */
if (master->list == NULL) {
uint32_t mt_det_ctxs_cnt;
struct DetectEngineThreadCtx_ **mt_det_ctxs;
+ struct DetectEngineTenantMapping_ *tenant_array;
+ uint32_t tenant_array_size;
+
+ uint32_t (*TenantGetId)(const void *, const Packet *p);
+
/* detection engine variables */
/** offset into the payload of the last match by:
* deal with both cases */
#define SIGMATCH_OPTIONAL_OPT (1 << 5)
+enum DetectEngineTenantSelectors
+{
+ TENANT_SELECTOR_UNKNOWN = 0, /**< not set */
+ TENANT_SELECTOR_DIRECT, /**< method provides direct tenant id */
+ TENANT_SELECTOR_VLAN, /**< map vlan to tenant id */
+};
+
+typedef struct DetectEngineTenantMapping_ {
+ uint32_t tenant_id;
+
+ /* traffic id that maps to the tenant id */
+ uint32_t traffic_id;
+
+ struct DetectEngineTenantMapping_ *next;
+} DetectEngineTenantMapping;
+
typedef struct DetectEngineMasterCtx_ {
SCMutex lock;
* still be referenced by det_ctx's. Freed as soon as all references are
* gone. */
DetectEngineCtx *free_list;
+
+ enum DetectEngineTenantSelectors tenant_selector;
+
+ /** list of tenant mappings. Updated under lock. Used to generate lookup
+ * structures. */
+ DetectEngineTenantMapping *tenant_mapping_list;
+
} DetectEngineMasterCtx;
/** \brief Signature loader statistics */