multi-detect: (un)register-tenant unix socket commands

Make available to live mode and unix socket mode.

register-tenant:
    Loads a new YAML, does basic validation.
    Loads a new detection engine
    Loads rules
    Add new de_ctx to master store and stores tenant id in the de_ctx so
        we can look it up by tenant id later.

unregister-tenant:
    Gets the de_ctx, moves it to the freelist
    Removes config

Introduce DetectEngineGetByTenantId, which gets a reference to the
detect engine by tenant id.
pull/1608/head
Victor Julien 11 years ago
parent 3aa58f25ad
commit 147a6d2bfd

@ -80,7 +80,7 @@ class SuricataCompleter:
class SuricataSC: class SuricataSC:
def __init__(self, sck_path, verbose=False): def __init__(self, sck_path, verbose=False):
self.cmd_list=['shutdown','quit','pcap-file','pcap-file-number','pcap-file-list','iface-list','iface-stat'] self.cmd_list=['shutdown','quit','pcap-file','pcap-file-number','pcap-file-list','iface-list','iface-stat','register-tenant','unregister-tenant']
self.sck_path = sck_path self.sck_path = sck_path
self.verbose = verbose self.verbose = verbose
@ -206,6 +206,27 @@ class SuricataSC:
else: else:
arguments = {} arguments = {}
arguments["variable"] = variable arguments["variable"] = variable
elif "unregister-tenant" in command:
try:
[cmd, tenantid] = command.split(' ', 1)
except:
raise SuricataCommandException("Unable to split command '%s'" % (command))
if cmd != "unregister-tenant":
raise SuricataCommandException("Invalid command '%s'" % (command))
else:
arguments = {}
arguments["id"] = int(tenantid)
elif "register-tenant" in command:
try:
[cmd, tenantid, filename] = command.split(' ', 2)
except:
raise SuricataCommandException("Arguments to command '%s' is missing" % (command))
if cmd != "register-tenant":
raise SuricataCommandException("Invalid command '%s'" % (command))
else:
arguments = {}
arguments["id"] = int(tenantid)
arguments["filename"] = filename
else: else:
cmd = command cmd = command
else: else:

@ -1640,6 +1640,30 @@ DetectEngineCtx *DetectEngineReference(DetectEngineCtx *de_ctx)
return de_ctx; return de_ctx;
} }
DetectEngineCtx *DetectEngineGetByTenantId(int tenant_id)
{
DetectEngineMasterCtx *master = &g_master_de_ctx;
SCMutexLock(&master->lock);
if (master->list == NULL) {
SCMutexUnlock(&master->lock);
return NULL;
}
DetectEngineCtx *de_ctx = master->list;
while (de_ctx) {
if (de_ctx->tenant_id == tenant_id) {
de_ctx->ref_cnt++;
break;
}
de_ctx = de_ctx->next;
}
SCMutexUnlock(&master->lock);
return de_ctx;
}
void DetectEngineDeReference(DetectEngineCtx **de_ctx) void DetectEngineDeReference(DetectEngineCtx **de_ctx)
{ {
BUG_ON((*de_ctx)->ref_cnt == 0); BUG_ON((*de_ctx)->ref_cnt == 0);

@ -70,6 +70,7 @@ const char *DetectSigmatchListEnumToString(enum DetectSigmatchListEnum type);
int DetectEngineAddToMaster(DetectEngineCtx *de_ctx); int DetectEngineAddToMaster(DetectEngineCtx *de_ctx);
DetectEngineCtx *DetectEngineGetCurrent(void); DetectEngineCtx *DetectEngineGetCurrent(void);
DetectEngineCtx *DetectEngineGetByTenantId(int tenant_id);
void DetectEnginePruneFreeList(void); void DetectEnginePruneFreeList(void);
int DetectEngineMoveToFreeList(DetectEngineCtx *de_ctx); int DetectEngineMoveToFreeList(DetectEngineCtx *de_ctx);
DetectEngineCtx *DetectEngineReference(DetectEngineCtx *); DetectEngineCtx *DetectEngineReference(DetectEngineCtx *);

@ -560,6 +560,8 @@ typedef struct DetectEngineCtx_ {
uint8_t flags; uint8_t flags;
int failure_fatal; int failure_fatal;
int tenant_id;
Signature *sig_list; Signature *sig_list;
uint32_t sig_cnt; uint32_t sig_cnt;

@ -41,6 +41,10 @@
#include "util-profiling.h" #include "util-profiling.h"
#include "conf-yaml-loader.h"
#include "detect-engine.h"
static const char *default_mode = NULL; static const char *default_mode = NULL;
int unix_socket_mode_is_running = 0; int unix_socket_mode_is_running = 0;
@ -397,6 +401,134 @@ void UnixSocketPcapFile(TmEcode tm)
#endif #endif
} }
#ifdef BUILD_UNIX_SOCKET
/**
* \brief Command to add a tenant
*
* \param cmd the content of command Arguments as a json_t object
* \param answer the json_t object that has to be used to answer
* \param data pointer to data defining the context here a PcapCommand::
*/
TmEcode UnixSocketRegisterTenant(json_t *cmd, json_t* answer, void *data)
{
const char *filename;
#ifdef OS_WIN32
struct _stat st;
#else
struct stat st;
#endif /* OS_WIN32 */
/* 1 get tenant id */
json_t *jarg = json_object_get(cmd, "id");
if (!json_is_integer(jarg)) {
json_object_set_new(answer, "message", json_string("id is not an integer"));
return TM_ECODE_FAILED;
}
int tenant_id = json_integer_value(jarg);
/* 2 get tenant yaml */
jarg = json_object_get(cmd, "filename");
if (!json_is_string(jarg)) {
json_object_set_new(answer, "message", json_string("command is not a string"));
return TM_ECODE_FAILED;
}
filename = json_string_value(jarg);
#ifdef OS_WIN32
if(_stat(filename, &st) != 0) {
#else
if(stat(filename, &st) != 0) {
#endif /* OS_WIN32 */
json_object_set_new(answer, "message", json_string("file does not exist"));
return TM_ECODE_FAILED;
}
SCLogDebug("add-tenant: %d %s", tenant_id, filename);
/* 3 register it in the system */
/* 3A yaml parsing */
char prefix[64];
snprintf(prefix, sizeof(prefix), "multi-detect.%d", tenant_id);
if (ConfYamlLoadFileWithPrefix(filename, prefix) != 0) {
json_object_set_new(answer, "message", json_string("YAML loading failed, ConfYamlLoadFileWithPrefix failed"));
return TM_ECODE_FAILED;
}
ConfNode *node = ConfGetNode(prefix);
if (node == NULL) {
json_object_set_new(answer, "message", json_string("YAML loading failed, node == NULL"));
return TM_ECODE_FAILED;
}
#if 0
ConfDump();
#endif
/* 3B setup the de_ctx */
DetectEngineCtx *de_ctx = DetectEngineCtxInitWithPrefix(prefix);
if (de_ctx == NULL) {
json_object_set_new(answer, "message", json_string("detect engine failed to load"));
return TM_ECODE_FAILED;
}
SCLogDebug("de_ctx %p with prefix %s", de_ctx, de_ctx->config_prefix);
de_ctx->tenant_id = tenant_id;
SigLoadSignatures(de_ctx, NULL, 0);
DetectEngineAddToMaster(de_ctx);
/* 3C for each thread, replace det_ctx */
json_object_set_new(answer, "message", json_string("work in progress"));
return TM_ECODE_OK;
}
/**
* \brief Command to remove a tenant
*
* \param cmd the content of command Arguments as a json_t object
* \param answer the json_t object that has to be used to answer
* \param data pointer to data defining the context here a PcapCommand::
*/
TmEcode UnixSocketUnregisterTenant(json_t *cmd, json_t* answer, void *data)
{
/* 1 get tenant id */
json_t *jarg = json_object_get(cmd, "id");
if (!json_is_integer(jarg)) {
SCLogInfo("error: command is not a string");
json_object_set_new(answer, "message", json_string("id is not an integer"));
return TM_ECODE_FAILED;
}
int tenant_id = json_integer_value(jarg);
SCLogInfo("remove-tenant: %d TODO", tenant_id);
/* 2 remove it from the system */
char prefix[64];
snprintf(prefix, sizeof(prefix), "multi-detect.%d", tenant_id);
DetectEngineCtx *de_ctx = DetectEngineGetByTenantId(tenant_id);
if (de_ctx == NULL) {
json_object_set_new(answer, "message", json_string("tenant detect engine not found"));
return TM_ECODE_FAILED;
}
/* move to free list */
DetectEngineMoveToFreeList(de_ctx);
DetectEngineDeReference(&de_ctx);
/* update the threads */
/** TODO */
/* walk free list, freeing the removed de_ctx */
DetectEnginePruneFreeList();
json_object_set_new(answer, "message", json_string("work in progress"));
return TM_ECODE_OK;
}
#endif /* BUILD_UNIX_SOCKET */
/** /**
* \brief Single thread version of the Pcap file processing. * \brief Single thread version of the Pcap file processing.
*/ */

@ -31,4 +31,9 @@ int RunModeUnixSocketIsActive(void);
void UnixSocketPcapFile(TmEcode tm); void UnixSocketPcapFile(TmEcode tm);
#ifdef BUILD_UNIX_SOCKET
TmEcode UnixSocketRegisterTenant(json_t *cmd, json_t* answer, void *data);
TmEcode UnixSocketUnregisterTenant(json_t *cmd, json_t* answer, void *data);
#endif
#endif /* __RUNMODE_UNIX_SOCKET_H__ */ #endif /* __RUNMODE_UNIX_SOCKET_H__ */

@ -899,6 +899,9 @@ static TmEcode UnixManager(ThreadVars *th_v, void *thread_data)
UnixManagerRegisterCommand("conf-get", UnixManagerConfGetCommand, &command, UNIX_CMD_TAKE_ARGS); UnixManagerRegisterCommand("conf-get", UnixManagerConfGetCommand, &command, UNIX_CMD_TAKE_ARGS);
UnixManagerRegisterCommand("dump-counters", StatsOutputCounterSocket, NULL, 0); UnixManagerRegisterCommand("dump-counters", StatsOutputCounterSocket, NULL, 0);
UnixManagerRegisterCommand("reload-rules", UnixManagerReloadRules, NULL, 0); UnixManagerRegisterCommand("reload-rules", UnixManagerReloadRules, NULL, 0);
UnixManagerRegisterCommand("register-tenant", UnixSocketRegisterTenant, &command, UNIX_CMD_TAKE_ARGS);
UnixManagerRegisterCommand("unregister-tenant", UnixSocketUnregisterTenant, &command, UNIX_CMD_TAKE_ARGS);
TmThreadsSetFlag(th_v, THV_INIT_DONE); TmThreadsSetFlag(th_v, THV_INIT_DONE);
while (1) { while (1) {

Loading…
Cancel
Save