Go to the documentation of this file.
36 #if defined(HAVE_SYS_UN_H) && defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SYS_TYPES_H)
37 #define BUILD_WITH_UNIXSOCKET
38 #include <sys/types.h>
39 #include <sys/socket.h>
43 #ifdef HAVE_LIBHIREDIS
47 #define LOGFILE_NAME_MAX 255
49 static bool LogFileNewThreadedCtx(
LogFileCtx *parent_ctx,
const char *log_path,
const char *append,
55 #ifdef BUILD_WITH_UNIXSOCKET
63 SCLogOpenUnixSocketFp(
const char *path,
int sock_type,
int log_err)
65 struct sockaddr_un saun;
69 memset(&saun, 0x00,
sizeof(saun));
71 s = socket(PF_UNIX, sock_type, 0);
74 saun.sun_family = AF_UNIX;
75 strlcpy(saun.sun_path, path,
sizeof(saun.sun_path));
77 if (connect(s, (
const struct sockaddr *)&saun,
sizeof(saun)) < 0)
89 "Error connecting to socket \"%s\": %s (will keep trying)", path, strerror(errno));
101 static int SCLogUnixSocketReconnect(
LogFileCtx *log_ctx)
103 int disconnected = 0;
115 gettimeofday(&
tv, NULL);
116 now = (uint64_t)
tv.tv_sec * 1000;
117 now +=
tv.tv_usec / 1000;
129 }
else if (disconnected) {
130 SCLogWarning(
"Reconnect failed: %s (will keep trying)", strerror(errno));
133 return log_ctx->
fp ? 1 : 0;
136 static int SCLogFileWriteSocket(
const char *buffer,
int buffer_len,
142 if (
ctx->fp == NULL &&
ctx->is_sock) {
143 SCLogUnixSocketReconnect(
ctx);
149 if (
ctx->fp != NULL) {
150 int fd = fileno(
ctx->fp);
151 ssize_t size = send(fd, buffer, buffer_len,
ctx->send_flags);
155 if (errno == EAGAIN || errno == EWOULDBLOCK) {
156 SCLogDebug(
"Socket would block, dropping event.");
157 }
else if (errno == EINTR) {
159 SCLogDebug(
"Interrupted system call, trying again.");
162 SCLogDebug(
"Too many interrupted system calls, "
166 SCLogDebug(
"Send failed: %s", strerror(errno));
172 if (reopen && tries++ == 0) {
173 if (SCLogUnixSocketReconnect(
ctx)) {
185 static inline void OutputWriteLock(pthread_mutex_t *
m)
196 static int SCLogFileWriteNoLock(
const char *buffer,
int buffer_len,
LogFileCtx *log_ctx)
209 time_t now = time(NULL);
239 static int SCLogFileWrite(
const char *buffer,
int buffer_len,
LogFileCtx *log_ctx)
241 OutputWriteLock(&log_ctx->
fp_mutex);
244 #ifdef BUILD_WITH_UNIXSOCKET
246 ret = SCLogFileWriteSocket(buffer, buffer_len, log_ctx);
258 time_t now = time(NULL);
266 clearerr(log_ctx->
fp);
267 if (1 != fwrite(buffer, buffer_len, 1, log_ctx->
fp)) {
271 ferror(log_ctx->
fp) ? strerror(errno) :
"unknown error",
291 static char *SCLogFilenameFromPattern(
const char *pattern)
293 char *filename =
SCMalloc(PATH_MAX);
294 if (filename == NULL) {
307 static void SCLogFileCloseNoLock(
LogFileCtx *log_ctx)
319 static void SCLogFileClose(
LogFileCtx *log_ctx)
322 SCLogFileCloseNoLock(log_ctx);
326 static char ThreadLogFileHashCompareFunc(
327 void *data1, uint16_t datalen1,
void *data2, uint16_t datalen2)
332 if (p1 == NULL || p2 == NULL)
337 static uint32_t ThreadLogFileHashFunc(
HashTable *ht,
void *data, uint16_t datalen)
344 static void ThreadLogFileHashFreeFunc(
void *data)
363 SCLogError(
"Unable to allocate threads container");
368 ThreadLogFileHashCompareFunc, ThreadLogFileHashFreeFunc);
370 FatalError(
"Unable to initialize thread/entry hash table");
375 SCLogError(
"Unable to allocate threads append setting");
403 SCLogOpenFileFp(
const char *path,
const char *append_setting, uint32_t mode)
407 char *filename = SCLogFilenameFromPattern(path);
408 if (filename == NULL) {
419 ret = fopen(filename,
"a");
421 ret = fopen(filename,
"w");
425 SCLogError(
"Error opening file: \"%s\": %s", filename, strerror(errno));
429 int r = _chmod(filename, (mode_t)mode);
431 int r = fchmod(fileno(ret), (mode_t)mode);
434 SCLogWarning(
"Could not chmod %s to %o: %s", filename, mode, strerror(errno));
454 const char *default_filename,
457 char log_path[PATH_MAX];
459 const char *filename, *filetype;
462 if (conf == NULL || log_ctx == NULL || default_filename == NULL) {
463 SCLogError(
"SCConfLogOpenGeneric(conf %p, ctx %p, default %p) "
464 "missing an argument",
465 conf, log_ctx, default_filename);
468 if (log_ctx->
fp != NULL) {
469 SCLogError(
"SCConfLogOpenGeneric: previously initialized Log CTX "
476 if (filename == NULL)
477 filename = default_filename;
482 snprintf(log_path, PATH_MAX,
"%s", filename);
484 snprintf(log_path, PATH_MAX,
"%s/%s", log_dir, filename);
489 if (rotate_int != NULL) {
490 time_t now = time(NULL);
494 if (strcmp(rotate_int,
"minute") == 0) {
497 }
else if (strcmp(rotate_int,
"hour") == 0) {
500 }
else if (strcmp(rotate_int,
"day") == 0) {
516 if (filetype == NULL)
521 if (filemode != NULL &&
StringParseUint32(&mode, 8, (uint16_t)strlen(filemode), filemode) > 0) {
530 log_ctx->
json_flags = JSON_PRESERVE_ORDER|JSON_COMPACT|
535 if (json_flags != 0) {
539 log_ctx->
json_flags &= ~(JSON_PRESERVE_ORDER);
556 #ifdef BUILD_WITH_UNIXSOCKET
558 if (strcasecmp(filetype,
"unix_stream") == 0 || strcasecmp(filetype,
"unix_dgram") == 0) {
559 FatalError(
"Socket file types do not support threaded output");
564 if (strcasecmp(filetype,
"unix_stream") == 0) {
565 #ifdef BUILD_WITH_UNIXSOCKET
569 log_ctx->
fp = SCLogOpenUnixSocketFp(log_path, SOCK_STREAM, 1);
573 }
else if (strcasecmp(filetype,
"unix_dgram") == 0) {
574 #ifdef BUILD_WITH_UNIXSOCKET
578 log_ctx->
fp = SCLogOpenUnixSocketFp(log_path, SOCK_DGRAM, 1);
583 strcasecmp(filetype,
"file") == 0) {
586 log_ctx->
fp = SCLogOpenFileFp(log_path, append, log_ctx->
filemode);
587 if (log_ctx->
fp == NULL)
599 "%s.filetype. Expected \"regular\" (default), \"unix_stream\", "
605 SCLogError(
"Failed to allocate memory for filename");
609 #ifdef BUILD_WITH_UNIXSOCKET
612 SCLogInfo(
"Setting logging socket of non-blocking in live mode.");
616 SCLogInfo(
"%s output device (%s) initialized: %s", conf->
name, filetype,
637 SCLogWarning(
"Can't re-open LogFileCtx without a filename.");
641 if (log_ctx->
fp != NULL) {
649 if (log_ctx->
fp == NULL) {
667 lf_ctx->
Write = SCLogFileWrite;
668 lf_ctx->
Close = SCLogFileClose;
692 FatalError(
"Unable to allocate thread/hash-entry entry");
699 FatalError(
"Unable to add thread/hash-entry mapping");
718 SCLogDebug(
"%s: Adding reference for thread %" PRIi64
719 " (local thread id %d) to file %s [ctx %p]",
726 thread_id, parent_ctx->
filename, parent_ctx);
727 if (LogFileNewThreadedCtx(
740 SCLogDebug(
"Existing file for thread/entry %p reference to file %s [ctx %p]", entry,
751 static bool LogFileThreadedName(
752 const char *original_name,
char *threaded_name,
size_t len, uint32_t unique_id)
756 if (strcmp(
"/dev/null", original_name) == 0) {
763 FatalError(
"Invalid filename for threaded mode \"%s\"; "
764 "no basename found.",
769 char *dot = strrchr(base,
'.');
771 char *tname =
SCStrdup(original_name);
780 dot = strrchr(original_name,
'.');
781 int dotpos = dot - original_name;
782 tname[dotpos] =
'\0';
783 char *ext = tname + dotpos + 1;
784 if (strlen(tname) && strlen(ext)) {
785 snprintf(threaded_name,
len,
"%s.%u.%s", tname, unique_id, ext);
787 FatalError(
"Invalid filename for threaded mode \"%s\"; "
788 "filenames must include an extension, e.g: \"name.ext\"",
793 snprintf(threaded_name,
len,
"%s.%u", original_name, unique_id);
804 static bool LogFileNewThreadedCtx(
LogFileCtx *parent_ctx,
const char *log_path,
const char *append,
809 SCLogError(
"Unable to allocate thread file context entry %p", entry);
813 *thread = *parent_ctx;
817 if (!LogFileThreadedName(log_path, fname,
sizeof(fname), entry->
slot_number)) {
818 SCLogError(
"Unable to create threaded filename for log");
821 SCLogDebug(
"%s: thread open -- using name %s [replaces %s] - thread %d [slot %d]",
823 thread->
fp = SCLogOpenFileFp(fname, append, thread->
filemode);
824 if (thread->
fp == NULL) {
829 SCLogError(
"Unable to duplicate filename for context entry %p", entry);
833 thread->
Write = SCLogFileWriteNoLock;
834 thread->
Close = SCLogFileCloseNoLock;
844 thread->
parent = parent_ctx;
845 thread->
entry = entry;
854 thread->
Close(thread);
870 if (lf_ctx == NULL) {
890 if (lf_ctx->
fp != NULL) {
891 lf_ctx->
Close(lf_ctx);
897 if (lf_ctx->
prefix != NULL) {
919 #ifdef HAVE_LIBHIREDIS
921 if (lf_ctx->redis_setup.stream_format != NULL) {
922 SCFree(lf_ctx->redis_setup.stream_format);
927 memset(lf_ctx, 0,
sizeof(*lf_ctx));
946 #ifdef HAVE_LIBHIREDIS
uint64_t SCParseTimeSizeString(const char *str)
Parse string containing time size (1m, 1h, etc).
int SCRunmodeGet(void)
Get the current run mode.
#define SC_ATOMIC_DECL_AND_INIT_WITH_VAL(type, name, val)
wrapper for declaring an atomic variable and initializing it to a specific value
LogFileCtx * LogFileNewCtx(void)
LogFileNewCtx() Get a new LogFileCtx.
uint64_t SCGetSecondsUntil(const char *str, time_t epoch)
Get seconds until a time unit changes.
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
int(* Write)(const char *buffer, const int buffer_len, const void *init_data, void *thread_data)
Called for each EVE log record.
#define LOGFILE_RECONN_MIN_TIME
#define DEFAULT_LOG_MODE_APPEND
int(* Write)(const char *buffer, int buffer_len, struct LogFileCtx_ *fp)
#define JSON_ESCAPE_SLASH
int SCConfLogReopen(LogFileCtx *log_ctx)
Reopen a regular log file with the side-affect of truncating it.
bool IsRunModeOffline(enum RunModes run_mode_to_check)
#define SCClearErrUnlocked
int ConfValIsTrue(const char *val)
Check if a value is true.
void HashTableFree(HashTable *ht)
thread_local char t_thread_name[THREAD_NAME_LEN+1]
int SCConfLogOpenGeneric(ConfNode *conf, LogFileCtx *log_ctx, const char *default_filename, int rotate)
open a generic output "log file", which may be a regular file or a socket
size_t strlcpy(char *dst, const char *src, size_t siz)
void(* ThreadDeinit)(const void *init_data, void *thread_data)
Called to deinitialize each thread.
void OutputRegisterFileRotationFlag(int *flag)
Register a flag for file rotation notification.
int SCTimeToStringPattern(time_t epoch, const char *pattern, char *str, size_t size)
Convert epoch time to string pattern.
int LogFileWrite(LogFileCtx *file_ctx, MemBuffer *buffer)
#define DEFAULT_LOG_FILETYPE
#define SCMutexUnlock(mut)
void * HashTableLookup(HashTable *ht, void *data, uint16_t datalen)
int HashTableRemove(HashTable *ht, void *data, uint16_t datalen)
ThreadId internal_thread_id
int StringParseUint32(uint32_t *res, int base, size_t len, const char *str)
#define SCLogWarning(...)
Macro used to log WARNING messages.
int HashTableAdd(HashTable *ht, void *data, uint16_t datalen)
LogThreadedFileCtx * threads
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
const char * SCBasename(const char *path)
@ LOGFILE_TYPE_UNIX_DGRAM
bool SCLogOpenThreadedFile(const char *log_path, const char *append, LogFileCtx *parent_ctx)
@ LOGFILE_TYPE_UNIX_STREAM
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
#define SCMutexInit(mut, mutattrs)
#define SCGetThreadIdLong(...)
ConfNode * ConfNodeLookupChild(const ConfNode *node, const char *name)
Lookup a child configuration node by name.
struct LogFileCtx_ * parent
LogFileCtx * LogFileEnsureExists(ThreadId thread_id, LogFileCtx *parent_ctx)
LogFileEnsureExists() Ensure a log file context for the thread exists.
int PathIsAbsolute(const char *path)
Check if a path is absolute.
ThreadLogFileHashEntry * entry
int LogFileFreeCtx(LogFileCtx *lf_ctx)
LogFileFreeCtx() Destroy a LogFileCtx (Close the file and free memory)
void(* Deinit)(void *init_data)
Final call to deinitialize this filetype.
const char * ConfigGetLogDirectory(void)
#define SCLogError(...)
Macro used to log ERROR messages.
#define LOGFILE_ROTATE_INTERVAL
int ConfValIsFalse(const char *val)
Check if a value is false.
thread_local SCError sc_errno
HashTable * HashTableInit(uint32_t size, uint32_t(*Hash)(struct HashTable_ *, void *, uint16_t), char(*Compare)(void *, uint16_t, void *, uint16_t), void(*Free)(void *))
SCLogLevel sc_log_global_log_level
Holds the global log level. Is the same as sc_log_config->log_level.
void MemBufferWriteString(MemBuffer *dst, const char *fmt,...)
void(* Close)(struct LogFileCtx_ *fp)
#define MEMBUFFER_BUFFER(mem_buffer)
Get the MemBuffers underlying buffer.
int(* ThreadInit)(const void *init_data, const ThreadId thread_id, void **thread_data)
Initialize thread specific data.
#define SCLogNotice(...)
Macro used to log NOTICE messages.
void OutputUnregisterFileRotationFlag(int *flag)
Unregister a file rotation flag.
#define MEMBUFFER_OFFSET(mem_buffer)
Get the MemBuffers current offset.
int SCCreateDirectoryTree(const char *path, const bool final)
Recursively create a directory.
const char * ConfNodeLookupChildValue(const ConfNode *node, const char *name)
Lookup the value of a child configuration node by name.