From 1893c5edb1f239985ecaad8afafac08647034485 Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Thu, 5 Feb 2015 18:58:26 +0100 Subject: [PATCH] multi-detect: initial selectors for tenants The Detection Thread has the TenantGetId pointer which allows it to select a tenant id based on the packet. --- src/detect-engine.c | 121 +++++++++++++++++++++++++++++++++++++++++++- src/detect-engine.h | 3 -- src/detect.c | 5 +- src/detect.h | 28 ++++++++++ 4 files changed, 150 insertions(+), 7 deletions(-) diff --git a/src/detect-engine.c b/src/detect-engine.c index 3d5adde9fe..823bab5b22 100644 --- a/src/detect-engine.c +++ b/src/detect-engine.c @@ -103,7 +103,7 @@ static DetectEngineThreadCtx *DetectEngineThreadCtxInitForReload( 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); @@ -1474,6 +1474,11 @@ TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data) 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); @@ -1683,7 +1688,66 @@ void DetectEngineMultiTenantSetup(void) 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; } @@ -1910,8 +1974,12 @@ int DetectEngineReload(const char *filename) 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; @@ -1926,6 +1994,32 @@ static DetectEngineThreadCtx *DetectEngineThreadCtxInitForMT(ThreadVars *tv) 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); @@ -1947,6 +2041,23 @@ static DetectEngineThreadCtx *DetectEngineThreadCtxInitForMT(ThreadVars *tv) 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; @@ -1957,6 +2068,12 @@ int DetectEngineMTApply(void) 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) { diff --git a/src/detect-engine.h b/src/detect-engine.h index 42c4bef589..76253ab327 100644 --- a/src/detect-engine.h +++ b/src/detect-engine.h @@ -86,9 +86,6 @@ int DetectEngineReloadIsStart(void); void DetectEngineReloadSetDone(void); int DetectEngineReloadIsDone(void); -/* TODO move elsewhere? */ -uint32_t DetectEngineTentantGetIdFromPcap(DetectEngineThreadCtx *, const Packet *p); - /** * \brief Registers an app inspection engine. * diff --git a/src/detect.c b/src/detect.c index 906f79bc87..56dab7907b 100644 --- a/src/detect.c +++ b/src/detect.c @@ -1977,13 +1977,14 @@ TmEcode Detect(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQue } DetectEngineCtx *de_ctx = det_ctx->de_ctx; - if (de_ctx == NULL) { + + if (det_ctx->TenantGetId != NULL) { if (det_ctx->mt_det_ctxs == 0) { printf("ERROR: Detect has no detection engine ctx\n"); goto error; } - uint32_t tenant_id = DetectEngineTentantGetIdFromPcap(det_ctx, p); + uint32_t tenant_id = det_ctx->TenantGetId(det_ctx, p); if (tenant_id > 0 && tenant_id < det_ctx->mt_det_ctxs_cnt) { det_ctx = det_ctx->mt_det_ctxs[tenant_id]; BUG_ON(det_ctx == NULL); diff --git a/src/detect.h b/src/detect.h index 7095eec82c..985a8cf59a 100644 --- a/src/detect.h +++ b/src/detect.h @@ -769,6 +769,11 @@ typedef struct DetectEngineThreadCtx_ { 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: @@ -1044,6 +1049,22 @@ typedef struct SigGroupHead_ { * 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; @@ -1058,6 +1079,13 @@ typedef struct DetectEngineMasterCtx_ { * 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 */