This patch adds redis support to JSON output.
LDFLAGS="${LDFLAGS} -pie"
fi
+# libhiredis
+ AC_ARG_ENABLE(hiredis,
+ AS_HELP_STRING([--enable-hiredis],[Enable Redis support]),
+ [ enable_hiredis="yes"],
+ [ enable_hiredis="no"])
+ AC_ARG_WITH(libhiredis_includes,
+ [ --with-libhiredis-includes=DIR libhiredis include directory],
+ [with_libhiredis_includes="$withval"],[with_libhiredis_includes="no"])
+ AC_ARG_WITH(libhiredis_libraries,
+ [ --with-libhiredis-libraries=DIR libhiredis library directory],
+ [with_libhiredis_libraries="$withval"],[with_libhiredis_libraries="no"])
+
+ if test "$enable_hiredis" = "yes"; then
+ if test "$with_libhiredis_includes" != "no"; then
+ CPPFLAGS="${CPPFLAGS} -I${with_libhiredis_includes}"
+ fi
+
+ AC_CHECK_HEADER("hiredis/hiredis.h",HIREDIS="yes",HIREDIS="no")
+ if test "$HIREDIS" = "yes"; then
+ if test "$with_libhiredis_libraries" != "no"; then
+ LDFLAGS="${LDFLAGS} -L${with_libhiredis_libraries}"
+ fi
+ AC_CHECK_LIB(hiredis, redisConnect,, HIREDIS="no")
+ fi
+ if test "$HIREDIS" = "no"; then
+ echo
+ echo " ERROR! libhiredis library not found, go get it"
+ echo " from https://github.com/redis/hiredis or your distribution:"
+ echo
+ echo " Ubuntu: apt-get install libhiredis-dev"
+ echo " Fedora: yum install libhiredis-devel"
+ echo
+ exit 1
+ fi
+ if test "$HIREDIS" = "yes"; then
+ AC_DEFINE([HAVE_LIBHIREDIS],[1],[libhiredis available])
+ enable_hiredis="yes"
+ fi
+ fi
+
# get cache line size
AC_PATH_PROG(HAVE_GETCONF_CMD, getconf, "no")
if test "$HAVE_GETCONF_CMD" != "no"; then
libnss support: ${enable_nss}
libnspr support: ${enable_nspr}
libjansson support: ${enable_jansson}
+ hiredis support: ${enable_hiredis}
Prelude support: ${enable_prelude}
PCRE jit: ${pcre_jit_available}
LUA support: ${enable_lua}
#else /* implied we do have JSON support */
#include <jansson.h>
+#if HAVE_LIBHIREDIS
+#include <hiredis/hiredis.h>
+#endif
#define DEFAULT_LOG_FILENAME "eve.json"
#define DEFAULT_ALERT_SYSLOG_FACILITY_STR "local0"
file_ctx->Write((const char *)MEMBUFFER_BUFFER(buffer),
MEMBUFFER_OFFSET(buffer), file_ctx);
}
+#if HAVE_LIBHIREDIS
+ else if (file_ctx->type == LOGFILE_TYPE_REDIS) {
+ /* FIXME go async here */
+ redisReply *reply = redisCommand(file_ctx->redis, "%s %s %s",
+ file_ctx->redis_setup.command,
+ file_ctx->redis_setup.key,
+ js_s);
+ switch (reply->type) {
+ case REDIS_REPLY_ERROR:
+ SCLogWarning(SC_WARN_NO_UNITTESTS, "Redis error: %s", reply->str);
+ break;
+ case REDIS_REPLY_INTEGER:
+ SCLogDebug("Redis integer %lld", reply->integer);
+ break;
+ default:
+ SCLogError(SC_ERR_INVALID_VALUE,
+ "Redis default triggered with %d", reply->type);
+ break;
+ }
+ freeReplyObject(reply);
+ }
+#endif
SCMutexUnlock(&file_ctx->fp_mutex);
free(js_s);
return 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) {
+#if HAVE_LIBHIREDIS
+ json_ctx->json_out = LOGFILE_TYPE_REDIS;
+#else
+ SCLogError(SC_ERR_INVALID_ARGUMENT,
+ "redis JSON output option is not compiled");
+ exit(EXIT_FAILURE);
+#endif
} else {
SCLogError(SC_ERR_INVALID_ARGUMENT,
"Invalid JSON output option: %s", output_s);
openlog(ident, LOG_PID|LOG_NDELAY, facility);
}
+#if HAVE_LIBHIREDIS
+ else if (json_ctx->json_out == LOGFILE_TYPE_REDIS) {
+ ConfNode *redis_node = ConfNodeLookupChild(conf, "redis");
+ const char *redis_server = NULL;
+ const char *redis_port = NULL;
+ const char *redis_mode = NULL;
+ const char *redis_key = NULL;
+
+ if (redis_node) {
+ redis_server = ConfNodeLookupChildValue(redis_node, "server");
+ redis_port = ConfNodeLookupChildValue(redis_node, "port");
+ redis_mode = ConfNodeLookupChildValue(redis_node, "mode");
+ redis_key = ConfNodeLookupChildValue(redis_node, "key");
+ }
+ if (!redis_server) {
+ redis_server = "127.0.0.1";
+ SCLogInfo("Using default redis server (127.0.0.1)");
+ }
+ if (!redis_port)
+ redis_port = "6379";
+ if (!redis_mode)
+ redis_mode = "list";
+ if (!redis_key)
+ redis_key = "suricata";
+ json_ctx->file_ctx->redis_setup.key = SCStrdup(redis_key);
+
+ if (!json_ctx->file_ctx->redis_setup.key) {
+ SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate redis key name");
+ exit(EXIT_FAILURE);
+ }
+
+ if (!strcmp(redis_mode, "list")) {
+ json_ctx->file_ctx->redis_setup.command = SCStrdup("LPUSH");
+ if (!json_ctx->file_ctx->redis_setup.command) {
+ SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate redis key command");
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ json_ctx->file_ctx->redis_setup.command = SCStrdup("PUBLISH");
+ if (!json_ctx->file_ctx->redis_setup.command) {
+ SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate redis key command");
+ exit(EXIT_FAILURE);
+ }
+ }
+ redisContext *c = redisConnect(redis_server, atoi(redis_port));
+ if (c != NULL && c->err) {
+ SCLogError(SC_ERR_SOCKET, "Error connecting to redis server: %s\n", c->errstr);
+ exit(EXIT_FAILURE);
+ }
+ json_ctx->file_ctx->redis = c;
+ }
+#endif
const char *sensor_id_s = ConfNodeLookupChildValue(conf, "sensor-id");
if (sensor_id_s != NULL) {
int OutputJSONBuffer(json_t *js, LogFileCtx *file_ctx, MemBuffer *buffer);
OutputCtx *OutputJsonInitCtx(ConfNode *);
-
enum JsonFormat { COMPACT, INDENT };
/*
SCMutexUnlock(&lf_ctx->fp_mutex);
}
+#ifdef HAVE_LIBHIREDIS
+ if (lf_ctx->type == LOGFILE_TYPE_REDIS && lf_ctx->redis) {
+ redisFree(lf_ctx->redis);
+ }
+#endif
+
SCMutexDestroy(&lf_ctx->fp_mutex);
if (lf_ctx->prefix != NULL)
#include "conf.h" /* ConfNode */
#include "tm-modules.h" /* LogFileCtx */
+#include "hiredis/hiredis.h"
+
typedef struct {
uint16_t fileno;
} PcieFile;
enum LogFileType { LOGFILE_TYPE_FILE,
LOGFILE_TYPE_SYSLOG,
LOGFILE_TYPE_UNIX_DGRAM,
- LOGFILE_TYPE_UNIX_STREAM };
+ LOGFILE_TYPE_UNIX_STREAM,
+ LOGFILE_TYPE_REDIS };
+
+enum RedisMode { REDIS_LIST, REDIS_CHANNEL };
+
+typedef struct RedisSetup_ {
+ enum RedisMode mode;
+ char *command;
+ char *key;
+} RedisSetup;
/** Global structure for Output Context */
typedef struct LogFileCtx_ {
union {
FILE *fp;
PcieFile *pcie_fp;
+#ifdef HAVE_LIBHIREDIS
+ redisContext *redis;
+#endif
};
+#ifdef HAVE_LIBHIREDIS
+ RedisSetup redis_setup;
+#endif
+
int (*Write)(const char *buffer, int buffer_len, struct LogFileCtx_ *fp);
void (*Close)(struct LogFileCtx_ *fp);
# Extensible Event Format (nicknamed EVE) event log in JSON format
- eve-log:
enabled: yes
- filetype: regular #regular|syslog|unix_dgram|unix_stream
+ filetype: regular #regular|syslog|unix_dgram|unix_stream|redis
filename: eve.json
#prefix: "@cee: " # prefix to prepend to each log entry
# the following are valid when type: syslog above
#facility: local5
#level: Info ## possible levels: Emergency, Alert, Critical,
## Error, Warning, Notice, Info, Debug
+ #redis:
+ # server: 127.0.0.1
+ # port: 6379
+ # mode: list ## possible values: list (default), channel
+ # key: suricata ## key or channel to use (default to suricata)
types:
- alert:
# payload: yes # enable dumping payload in Base64