]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
multi-detect: initial selectors for tenants
authorVictor Julien <victor@inliniac.net>
Thu, 5 Feb 2015 17:58:26 +0000 (18:58 +0100)
committerVictor Julien <victor@inliniac.net>
Thu, 23 Jul 2015 17:36:14 +0000 (19:36 +0200)
The Detection Thread has the TenantGetId pointer which allows it
to select a tenant id based on the packet.

src/detect-engine.c
src/detect-engine.h
src/detect.c
src/detect.h

index 3d5adde9fec2b3b70f25114e6ecec70ea8f09d26..823bab5b224d8addb7a7d893b5b20acf780eef2f 100644 (file)
@@ -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) {
index 42c4bef58911a3cc7f8e5079a345471e53b75eb9..76253ab3272c9b7e2fc28b50a1bc51f79ddd4126 100644 (file)
@@ -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.
  *
index 906f79bc87c65cde3b5ad191e7a27eca1ba198af..56dab7907bfe356019104bc0bec778cc412518e2 100644 (file)
@@ -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);
index 7095eec82ca71dbb68db31674730f44cf298dfd3..985a8cf59a3fd9958aea2aad23fc7ffa4828b11c 100644 (file)
@@ -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 */