output/json: Refactor internal routines

pull/6395/head
Jeff Lucovsky 4 years ago committed by Victor Julien
parent 5ba08dfef5
commit 0e3773ddef

@ -1002,6 +1002,78 @@ int OutputJsonBuilderBuffer(JsonBuilder *js, OutputJsonThreadCtx *ctx)
return 0;
}
static inline enum LogFileType FileTypeFromConf(const char *typestr)
{
enum LogFileType log_filetype = LOGFILE_TYPE_NOTSET;
if (typestr == NULL) {
log_filetype = LOGFILE_TYPE_FILE;
} else if (strcmp(typestr, "file") == 0 || strcmp(typestr, "regular") == 0) {
log_filetype = LOGFILE_TYPE_FILE;
} else if (strcmp(typestr, "unix_dgram") == 0) {
log_filetype = LOGFILE_TYPE_UNIX_DGRAM;
} else if (strcmp(typestr, "unix_stream") == 0) {
log_filetype = LOGFILE_TYPE_UNIX_STREAM;
} else if (strcmp(typestr, "redis") == 0) {
#ifdef HAVE_LIBHIREDIS
log_filetype = LOGFILE_TYPE_REDIS;
#else
FatalError(SC_ERR_FATAL, "redis JSON output option is not compiled");
#endif
}
SCLogDebug("type %s, file type value %d", typestr, log_filetype);
return log_filetype;
}
static int LogFileTypePrepare(
OutputJsonCtx *json_ctx, enum LogFileType log_filetype, ConfNode *conf)
{
if (log_filetype == LOGFILE_TYPE_FILE || log_filetype == LOGFILE_TYPE_UNIX_DGRAM ||
log_filetype == LOGFILE_TYPE_UNIX_STREAM) {
if (SCConfLogOpenGeneric(conf, json_ctx->file_ctx, DEFAULT_LOG_FILENAME, 1) < 0) {
return -1;
}
OutputRegisterFileRotationFlag(&json_ctx->file_ctx->rotation_flag);
}
#ifdef HAVE_LIBHIREDIS
else if (log_filetype == LOGFILE_TYPE_REDIS) {
SCLogRedisInit();
ConfNode *redis_node = ConfNodeLookupChild(conf, "redis");
if (!json_ctx->file_ctx->sensor_name) {
char hostname[1024];
gethostname(hostname, 1023);
json_ctx->file_ctx->sensor_name = SCStrdup(hostname);
}
if (json_ctx->file_ctx->sensor_name == NULL) {
return -1;
}
if (SCConfLogOpenRedis(redis_node, json_ctx->file_ctx) < 0) {
return -1;
}
}
#endif
else if (log_filetype == LOGFILE_TYPE_PLUGIN) {
if (json_ctx->file_ctx->threaded) {
/* Prepare for threaded log output. */
if (!SCLogOpenThreadedFile(NULL, NULL, json_ctx->file_ctx, 1)) {
return -1;
}
}
ConfNode *plugin_conf = ConfNodeLookupChild(conf, json_ctx->plugin->name);
void *init_data = NULL;
if (json_ctx->plugin->Init(json_ctx->plugin->internal ? conf : plugin_conf,
json_ctx->file_ctx->threaded, &init_data) < 0) {
return -1;
}
json_ctx->file_ctx->plugin.plugin = json_ctx->plugin;
json_ctx->file_ctx->plugin.init_data = init_data;
}
return 0;
}
/**
* \brief Create a new LogFileCtx for "fast" output style.
* \param conf The configuration node for this output.
@ -1010,6 +1082,7 @@ int OutputJsonBuilderBuffer(JsonBuilder *js, OutputJsonThreadCtx *ctx)
OutputInitResult OutputJsonInitCtx(ConfNode *conf)
{
OutputInitResult result = { NULL, false };
OutputCtx *output_ctx = NULL;
OutputJsonCtx *json_ctx = SCCalloc(1, sizeof(OutputJsonCtx));
if (unlikely(json_ctx == NULL)) {
@ -1038,20 +1111,16 @@ OutputInitResult OutputJsonInitCtx(ConfNode *conf)
if (sensor_name) {
json_ctx->file_ctx->sensor_name = SCStrdup(sensor_name);
if (json_ctx->file_ctx->sensor_name == NULL) {
LogFileFreeCtx(json_ctx->file_ctx);
SCFree(json_ctx);
return result;
if (json_ctx->file_ctx->sensor_name == NULL) {
goto error_exit;
}
} else {
json_ctx->file_ctx->sensor_name = NULL;
}
OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
output_ctx = SCCalloc(1, sizeof(OutputCtx));
if (unlikely(output_ctx == NULL)) {
LogFileFreeCtx(json_ctx->file_ctx);
SCFree(json_ctx);
return result;
goto error_exit;
}
output_ctx->data = json_ctx;
@ -1059,45 +1128,21 @@ OutputInitResult OutputJsonInitCtx(ConfNode *conf)
if (conf) {
const char *output_s = ConfNodeLookupChildValue(conf, "filetype");
// Backwards compatibility
if (output_s == NULL) {
output_s = ConfNodeLookupChildValue(conf, "type");
}
if (output_s != NULL) {
if (strcmp(output_s, "file") == 0 ||
strcmp(output_s, "regular") == 0) {
json_ctx->json_out = LOGFILE_TYPE_FILE;
} else if (strcmp(output_s, "syslog") == 0) {
json_ctx->json_out = LOGFILE_TYPE_SYSLOG;
} else if (strcmp(output_s, "unix_dgram") == 0) {
json_ctx->json_out = LOGFILE_TYPE_UNIX_DGRAM;
} else if (strcmp(output_s, "unix_stream") == 0) {
json_ctx->json_out = LOGFILE_TYPE_UNIX_STREAM;
} else if (strcmp(output_s, "redis") == 0) {
#ifdef HAVE_LIBHIREDIS
SCLogRedisInit();
json_ctx->json_out = LOGFILE_TYPE_REDIS;
#else
FatalError(SC_ERR_FATAL,
"redis JSON output option is not compiled");
#endif
} else {
enum LogFileType log_filetype = FileTypeFromConf(output_s);
if (log_filetype == LOGFILE_TYPE_NOTSET) {
#ifdef HAVE_PLUGINS
SCPluginFileType *plugin = SCPluginFindFileType(output_s);
if (plugin == NULL) {
FatalError(SC_ERR_INVALID_ARGUMENT,
"Invalid JSON output option: %s", output_s);
} else {
json_ctx->json_out = LOGFILE_TYPE_PLUGIN;
json_ctx->plugin = plugin;
}
#else
FatalError(SC_ERR_INVALID_ARGUMENT,
"Invalid JSON output option: %s", output_s);
SCPluginFileType *plugin = SCPluginFindFileType(output_s);
if (plugin != NULL) {
log_filetype = LOGFILE_TYPE_PLUGIN;
json_ctx->plugin = plugin;
} else
#endif
}
FatalError(SC_ERR_INVALID_ARGUMENT, "Invalid JSON output option: %s", output_s);
}
const char *prefix = ConfNodeLookupChildValue(conf, "prefix");
@ -1121,115 +1166,17 @@ OutputInitResult OutputJsonInitCtx(ConfNode *conf)
} else {
json_ctx->file_ctx->threaded = false;
}
if (json_ctx->json_out == LOGFILE_TYPE_FILE ||
json_ctx->json_out == LOGFILE_TYPE_UNIX_DGRAM ||
json_ctx->json_out == LOGFILE_TYPE_UNIX_STREAM)
{
if (SCConfLogOpenGeneric(conf, json_ctx->file_ctx, DEFAULT_LOG_FILENAME, 1) < 0) {
LogFileFreeCtx(json_ctx->file_ctx);
SCFree(json_ctx);
SCFree(output_ctx);
return result;
}
OutputRegisterFileRotationFlag(&json_ctx->file_ctx->rotation_flag);
}
#ifndef OS_WIN32
else if (json_ctx->json_out == LOGFILE_TYPE_SYSLOG) {
const char *facility_s = ConfNodeLookupChildValue(conf, "facility");
if (facility_s == NULL) {
facility_s = DEFAULT_ALERT_SYSLOG_FACILITY_STR;
}
int facility = SCMapEnumNameToValue(facility_s, SCSyslogGetFacilityMap());
if (facility == -1) {
SCLogWarning(SC_ERR_INVALID_ARGUMENT, "Invalid syslog facility: \"%s\","
" now using \"%s\" as syslog facility", facility_s,
DEFAULT_ALERT_SYSLOG_FACILITY_STR);
facility = DEFAULT_ALERT_SYSLOG_FACILITY;
}
const char *level_s = ConfNodeLookupChildValue(conf, "level");
if (level_s != NULL) {
int level = SCMapEnumNameToValue(level_s, SCSyslogGetLogLevelMap());
if (level != -1) {
json_ctx->file_ctx->syslog_setup.alert_syslog_level = level;
}
}
const char *ident = ConfNodeLookupChildValue(conf, "identity");
/* if null we just pass that to openlog, which will then
* figure it out by itself. */
openlog(ident, LOG_PID|LOG_NDELAY, facility);
if (LogFileTypePrepare(json_ctx, log_filetype, conf) < 0) {
goto error_exit;
}
#endif
#ifdef HAVE_LIBHIREDIS
else if (json_ctx->json_out == LOGFILE_TYPE_REDIS) {
ConfNode *redis_node = ConfNodeLookupChild(conf, "redis");
if (!json_ctx->file_ctx->sensor_name) {
char hostname[1024];
gethostname(hostname, 1023);
json_ctx->file_ctx->sensor_name = SCStrdup(hostname);
}
if (json_ctx->file_ctx->sensor_name == NULL) {
LogFileFreeCtx(json_ctx->file_ctx);
SCFree(json_ctx);
SCFree(output_ctx);
return result;
}
if (SCConfLogOpenRedis(redis_node, json_ctx->file_ctx) < 0) {
LogFileFreeCtx(json_ctx->file_ctx);
SCFree(json_ctx);
SCFree(output_ctx);
return result;
}
}
#endif
#ifdef HAVE_PLUGINS
else if (json_ctx->json_out == LOGFILE_TYPE_PLUGIN) {
if (json_ctx->file_ctx->threaded) {
/* Prepare for storing per-thread data */
if (!SCLogOpenThreadedFile(NULL, NULL, json_ctx->file_ctx, 1)) {
SCFree(json_ctx);
SCFree(output_ctx);
return result;
}
}
void *init_data = NULL;
if (json_ctx->plugin->Init(conf, json_ctx->file_ctx->threaded, &init_data) < 0) {
LogFileFreeCtx(json_ctx->file_ctx);
SCFree(json_ctx);
SCFree(output_ctx);
return result;
}
/* Now that initialization completed successfully, if threaded, make sure
* that ThreadInit and ThreadDeInit exist
*/
if (json_ctx->file_ctx->threaded) {
if (!json_ctx->plugin->ThreadInit || !json_ctx->plugin->ThreadDeinit) {
FatalError(SC_ERR_LOG_OUTPUT, "Output logger must supply ThreadInit and "
"ThreadDeinit functions for threaded mode");
}
}
json_ctx->file_ctx->plugin.plugin = json_ctx->plugin;
json_ctx->file_ctx->plugin.init_data = init_data;
}
#endif
const char *sensor_id_s = ConfNodeLookupChildValue(conf, "sensor-id");
if (sensor_id_s != NULL) {
if (StringParseUint64((uint64_t *)&sensor_id, 10, 0, sensor_id_s) < 0) {
SCLogError(SC_ERR_INVALID_ARGUMENT,
"Failed to initialize JSON output, "
"invalid sensor-id: %s", sensor_id_s);
exit(EXIT_FAILURE);
FatalError(SC_ERR_INVALID_ARGUMENT,
"Failed to initialize JSON output, "
"invalid sensor-id: %s",
sensor_id_s);
}
}
@ -1264,10 +1211,10 @@ OutputInitResult OutputJsonInitCtx(ConfNode *conf)
if (StringParseUint16(&json_ctx->cfg.community_id_seed,
10, 0, cid_seed) < 0)
{
SCLogError(SC_ERR_INVALID_ARGUMENT,
"Failed to initialize JSON output, "
"invalid community-id-seed: %s", cid_seed);
exit(EXIT_FAILURE);
FatalError(SC_ERR_INVALID_ARGUMENT,
"Failed to initialize JSON output, "
"invalid community-id-seed: %s",
cid_seed);
}
}
@ -1286,8 +1233,7 @@ OutputInitResult OutputJsonInitCtx(ConfNode *conf)
(RunmodeGetCurrent() == RUNMODE_PCAP_FILE ||
RunmodeGetCurrent() == RUNMODE_UNIX_SOCKET);
}
json_ctx->file_ctx->type = json_ctx->json_out;
json_ctx->file_ctx->type = log_filetype;
}
SCLogDebug("returning output_ctx %p", output_ctx);
@ -1295,6 +1241,18 @@ OutputInitResult OutputJsonInitCtx(ConfNode *conf)
result.ctx = output_ctx;
result.ok = true;
return result;
error_exit:
if (json_ctx->file_ctx) {
LogFileFreeCtx(json_ctx->file_ctx);
}
if (json_ctx) {
SCFree(json_ctx);
}
if (output_ctx) {
SCFree(output_ctx);
}
return result;
}
static void OutputJsonDeInitCtx(OutputCtx *output_ctx)

@ -36,6 +36,7 @@ typedef struct SCPlugin_ {
const char *name;
const char *license;
const char *author;
const bool internal;
void (*Init)(void);
} SCPlugin;
@ -48,7 +49,8 @@ typedef struct SCPlugin_ {
* plugins: section
*/
typedef struct SCPluginFileType_ {
char *name;
const char *name;
bool internal;
/* Init Called on first access */
int (*Init)(ConfNode *conf, bool threaded, void **init_data);
/* Write - Called on each write to the object */

Loading…
Cancel
Save