multi-tenant: introduce device selector

Add device to tenant mapping support:

  mappings:
  - device: ens5f0
    tenant-id: 1
  - device: ens5f1
    tenant-id: 23

Implemented by assigning the tenant id to the 'livedev', which means
it's only supported for capture methods that use the livedev API.

It's also currently not supported for IPS. In a case like 'eth0 -> eth1'
it's unclear which tenant should be used for the return traffic in a
flow, where the incoming device is 'eth1'.
pull/3447/head
Victor Julien 9 years ago
parent a337908c78
commit 12fec46d13

@ -73,7 +73,7 @@
#include "util-magic.h"
#include "util-signal.h"
#include "util-spm.h"
#include "util-device.h"
#include "util-var-name.h"
#include "tm-threads.h"
@ -98,6 +98,7 @@ static DetectEngineMasterCtx g_master_de_ctx = { SCMUTEX_INITIALIZER,
static uint32_t TenantIdHash(HashTable *h, void *data, uint16_t data_len);
static char TenantIdCompare(void *d1, uint16_t d1_len, void *d2, uint16_t d2_len);
static void TenantIdFree(void *d);
static uint32_t DetectEngineTentantGetIdFromLivedev(const void *ctx, const Packet *p);
static uint32_t DetectEngineTentantGetIdFromVlanId(const void *ctx, const Packet *p);
static uint32_t DetectEngineTentantGetIdFromPcap(const void *ctx, const Packet *p);
@ -2168,6 +2169,10 @@ static TmEcode DetectEngineThreadCtxInitForMT(ThreadVars *tv, DetectEngineThread
det_ctx->TenantGetId = DetectEngineTentantGetIdFromVlanId;
SCLogDebug("TENANT_SELECTOR_VLAN");
break;
case TENANT_SELECTOR_LIVEDEV:
det_ctx->TenantGetId = DetectEngineTentantGetIdFromLivedev;
SCLogDebug("TENANT_SELECTOR_LIVEDEV");
break;
case TENANT_SELECTOR_DIRECT:
det_ctx->TenantGetId = DetectEngineTentantGetIdFromPcap;
SCLogDebug("TENANT_SELECTOR_DIRECT");
@ -2932,63 +2937,69 @@ int DetectEngineReloadTenantBlocking(uint32_t tenant_id, const char *yaml, int r
return 0;
}
/**
* \brief setup multi-detect / multi-tenancy
*
* See if MT is enabled. If so, setup the selector, tenants and mappings.
* Tenants and mappings are optional, and can also dynamically be added
* and removed from the unix socket.
*/
int DetectEngineMultiTenantSetup(void)
static int DetectEngineMultiTenantSetupLoadLivedevMappings(const ConfNode *mappings_root_node,
bool failure_fatal)
{
enum DetectEngineTenantSelectors tenant_selector = TENANT_SELECTOR_UNKNOWN;
DetectEngineMasterCtx *master = &g_master_de_ctx;
int unix_socket = ConfUnixSocketIsEnable();
ConfNode *mapping_node = NULL;
int failure_fatal = 0;
(void)ConfGetBool("engine.init-failure-fatal", &failure_fatal);
int mapping_cnt = 0;
if (mappings_root_node != NULL) {
TAILQ_FOREACH(mapping_node, &mappings_root_node->head, next) {
ConfNode *tenant_id_node = ConfNodeLookupChild(mapping_node, "tenant-id");
if (tenant_id_node == NULL)
goto bad_mapping;
ConfNode *device_node = ConfNodeLookupChild(mapping_node, "device");
if (device_node == NULL)
goto bad_mapping;
int enabled = 0;
(void)ConfGetBool("multi-detect.enabled", &enabled);
if (enabled == 1) {
DetectLoadersInit();
TmModuleDetectLoaderRegister();
DetectLoaderThreadSpawn();
TmThreadContinueDetectLoaderThreads();
uint32_t tenant_id = 0;
if (ByteExtractStringUint32(&tenant_id, 10, strlen(tenant_id_node->val),
tenant_id_node->val) == -1)
{
SCLogError(SC_ERR_INVALID_ARGUMENT, "tenant-id "
"of %s is invalid", tenant_id_node->val);
goto bad_mapping;
}
SCMutexLock(&master->lock);
master->multi_tenant_enabled = 1;
const char *dev = device_node->val;
LiveDevice *ld = LiveGetDevice(dev);
if (ld == NULL) {
SCLogWarning(SC_ERR_MT_NO_MAPPING, "device %s not found", dev);
goto bad_mapping;
}
const char *handler = NULL;
if (ConfGet("multi-detect.selector", &handler) == 1) {
SCLogConfig("multi-tenant selector type %s", handler);
if (ld->tenant_id_set) {
SCLogWarning(SC_ERR_MT_NO_MAPPING, "device %s already mapped to tenant-id %u",
dev, ld->tenant_id);
goto bad_mapping;
}
if (strcmp(handler, "vlan") == 0) {
tenant_selector = master->tenant_selector = TENANT_SELECTOR_VLAN;
ld->tenant_id = tenant_id;
ld->tenant_id_set = true;
int vlanbool = 0;
if ((ConfGetBool("vlan.use-for-tracking", &vlanbool)) == 1 && vlanbool == 0) {
SCLogError(SC_ERR_INVALID_VALUE, "vlan tracking is disabled, "
"can't use multi-detect selector 'vlan'");
SCMutexUnlock(&master->lock);
if (DetectEngineTentantRegisterLivedev(tenant_id, ld->id) != 0) {
goto error;
}
} else if (strcmp(handler, "direct") == 0) {
tenant_selector = master->tenant_selector = TENANT_SELECTOR_DIRECT;
} else {
SCLogError(SC_ERR_INVALID_VALUE, "unknown value %s "
"multi-detect.selector", handler);
SCMutexUnlock(&master->lock);
SCLogConfig("device %s connected to tenant-id %u", dev, tenant_id);
mapping_cnt++;
continue;
bad_mapping:
if (failure_fatal)
goto error;
}
}
SCMutexUnlock(&master->lock);
SCLogConfig("multi-detect is enabled (multi tenancy). Selector: %s", handler);
SCLogConfig("%d device - tenant-id mappings defined", mapping_cnt);
return mapping_cnt;
/* traffic -- tenant mappings */
ConfNode *mappings_root_node = ConfGetNode("multi-detect.mappings");
error:
return 0;
}
static int DetectEngineMultiTenantSetupLoadVlanMappings(const ConfNode *mappings_root_node,
bool failure_fatal)
{
ConfNode *mapping_node = NULL;
int mapping_cnt = 0;
@ -3036,8 +3047,83 @@ int DetectEngineMultiTenantSetup(void)
goto error;
}
}
return mapping_cnt;
if (tenant_selector == TENANT_SELECTOR_VLAN && mapping_cnt == 0) {
error:
return 0;
}
/**
* \brief setup multi-detect / multi-tenancy
*
* See if MT is enabled. If so, setup the selector, tenants and mappings.
* Tenants and mappings are optional, and can also dynamically be added
* and removed from the unix socket.
*/
int DetectEngineMultiTenantSetup(void)
{
enum DetectEngineTenantSelectors tenant_selector = TENANT_SELECTOR_UNKNOWN;
DetectEngineMasterCtx *master = &g_master_de_ctx;
int unix_socket = ConfUnixSocketIsEnable();
int failure_fatal = 0;
(void)ConfGetBool("engine.init-failure-fatal", &failure_fatal);
int enabled = 0;
(void)ConfGetBool("multi-detect.enabled", &enabled);
if (enabled == 1) {
DetectLoadersInit();
TmModuleDetectLoaderRegister();
DetectLoaderThreadSpawn();
TmThreadContinueDetectLoaderThreads();
SCMutexLock(&master->lock);
master->multi_tenant_enabled = 1;
const char *handler = NULL;
if (ConfGet("multi-detect.selector", &handler) == 1) {
SCLogConfig("multi-tenant selector type %s", handler);
if (strcmp(handler, "vlan") == 0) {
tenant_selector = master->tenant_selector = TENANT_SELECTOR_VLAN;
int vlanbool = 0;
if ((ConfGetBool("vlan.use-for-tracking", &vlanbool)) == 1 && vlanbool == 0) {
SCLogError(SC_ERR_INVALID_VALUE, "vlan tracking is disabled, "
"can't use multi-detect selector 'vlan'");
SCMutexUnlock(&master->lock);
goto error;
}
} else if (strcmp(handler, "direct") == 0) {
tenant_selector = master->tenant_selector = TENANT_SELECTOR_DIRECT;
} else if (strcmp(handler, "device") == 0) {
tenant_selector = master->tenant_selector = TENANT_SELECTOR_LIVEDEV;
if (EngineModeIsIPS()) {
SCLogWarning(SC_ERR_MT_NO_MAPPING,
"multi-tenant 'device' mode not supported for IPS");
SCMutexUnlock(&master->lock);
goto error;
}
} else {
SCLogError(SC_ERR_INVALID_VALUE, "unknown value %s "
"multi-detect.selector", handler);
SCMutexUnlock(&master->lock);
goto error;
}
}
SCMutexUnlock(&master->lock);
SCLogConfig("multi-detect is enabled (multi tenancy). Selector: %s", handler);
/* traffic -- tenant mappings */
ConfNode *mappings_root_node = ConfGetNode("multi-detect.mappings");
if (tenant_selector == TENANT_SELECTOR_VLAN) {
int mapping_cnt = DetectEngineMultiTenantSetupLoadVlanMappings(mappings_root_node,
failure_fatal);
if (mapping_cnt == 0) {
/* no mappings are valid when we're in unix socket mode,
* they can be added on the fly. Otherwise warn/error
* depending on failure_fatal */
@ -3054,6 +3140,18 @@ int DetectEngineMultiTenantSetup(void)
}
}
}
} else if (tenant_selector == TENANT_SELECTOR_LIVEDEV) {
int mapping_cnt = DetectEngineMultiTenantSetupLoadLivedevMappings(mappings_root_node,
failure_fatal);
if (mapping_cnt == 0) {
if (failure_fatal) {
SCLogError(SC_ERR_MT_NO_MAPPING, "no multi-detect mappings defined");
goto error;
} else {
SCLogWarning(SC_ERR_MT_NO_MAPPING, "no multi-detect mappings defined");
}
}
}
/* tenants */
ConfNode *tenants_root_node = ConfGetNode("multi-detect.tenants");
@ -3141,6 +3239,18 @@ static uint32_t DetectEngineTentantGetIdFromVlanId(const void *ctx, const Packet
return 0;
}
static uint32_t DetectEngineTentantGetIdFromLivedev(const void *ctx, const Packet *p)
{
const DetectEngineThreadCtx *det_ctx = ctx;
const LiveDevice *ld = p->livedev;
if (ld == NULL || det_ctx == NULL)
return 0;
SCLogDebug("using tenant-id %u for packet on device %s", ld->tenant_id, ld->dev);
return ld->tenant_id;
}
static int DetectEngineTentantRegisterSelector(enum DetectEngineTenantSelectors selector,
uint32_t tenant_id, uint32_t traffic_id)
{
@ -3218,6 +3328,11 @@ static int DetectEngineTentantUnregisterSelector(enum DetectEngineTenantSelector
return -1;
}
int DetectEngineTentantRegisterLivedev(uint32_t tenant_id, int device_id)
{
return DetectEngineTentantRegisterSelector(TENANT_SELECTOR_LIVEDEV, tenant_id, (uint32_t)device_id);
}
int DetectEngineTentantRegisterVlanId(uint32_t tenant_id, uint16_t vlan_id)
{
return DetectEngineTentantRegisterSelector(TENANT_SELECTOR_VLAN, tenant_id, (uint32_t)vlan_id);

@ -102,6 +102,7 @@ int DetectEngineReloadIsIdle(void);
int DetectEngineLoadTenantBlocking(uint32_t tenant_id, const char *yaml);
int DetectEngineReloadTenantBlocking(uint32_t tenant_id, const char *yaml, int reload_cnt);
int DetectEngineTentantRegisterLivedev(uint32_t tenant_id, int device_id);
int DetectEngineTentantRegisterVlanId(uint32_t tenant_id, uint16_t vlan_id);
int DetectEngineTentantUnregisterVlanId(uint32_t tenant_id, uint16_t vlan_id);
int DetectEngineTentantRegisterPcapFile(uint32_t tenant_id);

@ -1325,6 +1325,7 @@ enum DetectEngineTenantSelectors
TENANT_SELECTOR_UNKNOWN = 0, /**< not set */
TENANT_SELECTOR_DIRECT, /**< method provides direct tenant id */
TENANT_SELECTOR_VLAN, /**< map vlan to tenant id */
TENANT_SELECTOR_LIVEDEV, /**< map livedev to tenant id */
};
typedef struct DetectEngineTenantMapping_ {

@ -133,6 +133,7 @@ int LiveRegisterDevice(const char *dev)
SC_ATOMIC_INIT(pd->drop);
SC_ATOMIC_INIT(pd->invalid_checksums);
pd->ignore_checksum = 0;
pd->id = LiveGetDeviceCount();
TAILQ_INSERT_TAIL(&live_devices, pd, next);
SCLogDebug("Device \"%s\" registered and created.", dev);

@ -40,13 +40,18 @@ int LiveGetOffload(void);
typedef struct LiveDevice_ {
char *dev; /**< the device (e.g. "eth0") */
char dev_short[MAX_DEVNAME + 1];
bool tenant_id_set;
int ignore_checksum;
int id;
SC_ATOMIC_DECLARE(uint64_t, pkts);
SC_ATOMIC_DECLARE(uint64_t, drop);
SC_ATOMIC_DECLARE(uint64_t, bypassed);
SC_ATOMIC_DECLARE(uint64_t, invalid_checksums);
TAILQ_ENTRY(LiveDevice_) next;
uint32_t tenant_id; /**< tenant id in multi-tenancy */
uint32_t offload_orig; /**< original offload settings to restore @exit */
} LiveDevice;

Loading…
Cancel
Save