Go to the documentation of this file.
75 #if defined (OS_WIN32)
79 static SCMutex sc_log_stream_lock;
90 static char *SCLogGetLogFilename(
const char *);
115 static inline int SCLogMapLogLevelToSyslogLevel(
int log_level)
117 int syslog_log_level = 0;
151 return syslog_log_level;
160 static inline void SCLogPrintToStream(FILE *fd,
char *
msg)
167 #if defined (OS_WIN32)
171 if (fprintf(fd,
"%s\n",
msg) < 0)
172 printf(
"Error writing to stream using fprintf\n");
176 #if defined (OS_WIN32)
193 static inline void SCLogPrintToSyslog(
int syslog_log_level,
const char *
msg)
205 static int SCLogMessageJSON(
struct timeval *tval,
char *buffer,
size_t buffer_size,
207 unsigned line,
const char *
function,
SCError error_code,
210 json_t *js = json_object();
213 json_t *ejs = json_object();
219 json_object_set_new(js,
"timestamp", json_string(timebuf));
223 json_object_set_new(js,
"log_level", json_string(s));
225 json_object_set_new(js,
"log_level", json_string(
"INVALID"));
228 json_object_set_new(js,
"event_type", json_string(
"engine"));
230 if (error_code > 0) {
231 json_object_set_new(ejs,
"error_code", json_integer(error_code));
232 json_object_set_new(ejs,
"error", json_string(
SCErrorToString(error_code)));
236 json_object_set_new(ejs,
"message", json_string(message));
240 json_object_set_new(ejs,
"function", json_string(
function));
243 json_object_set_new(ejs,
"file", json_string(file));
246 json_object_set_new(ejs,
"line", json_integer(line));
249 json_object_set_new(js,
"engine", ejs);
251 char *js_s = json_dumps(js,
252 JSON_PRESERVE_ORDER|JSON_COMPACT|JSON_ENSURE_ASCII|
254 snprintf(buffer, buffer_size,
"%s", js_s);
257 json_object_del(js,
"engine");
258 json_object_clear(js);
277 static SCError SCLogMessageGetBuffer(
279 char *buffer,
size_t buffer_size,
280 const char *log_format,
283 const unsigned int line,
const char *
function,
284 const SCError error_code,
const char *message)
287 return SCLogMessageJSON(tval, buffer, buffer_size, log_level, file, line,
function, error_code, message);
290 const char *s = NULL;
291 struct tm *tms = NULL;
293 const char *redb =
"";
294 const char *red =
"";
295 const char *yellowb =
"";
296 const char *yellow =
"";
297 const char *green =
"";
298 const char *blue =
"";
299 const char *reset =
"";
303 yellowb =
"\x1b[1;33m";
315 char local_format[strlen(log_format) + 1];
316 strlcpy(local_format, log_format,
sizeof(local_format));
317 char *temp_fmt = local_format;
318 char *substr = temp_fmt;
324 switch(temp_fmt[1]) {
332 "%s%s%d/%d/%04d -- %02d:%02d:%02d%s",
333 substr, green, tms->tm_mday, tms->tm_mon + 1,
334 tms->tm_year + 1900, tms->tm_hour, tms->tm_min,
347 "%s%s%u%s", substr, yellow, getpid(), reset);
377 "%s%s", substr, ((
tv != NULL)?
tv->
name:
"UNKNOWN TM"));
380 "%s%s", substr,
"N/A");
395 "%s%s%s%s", substr, redb, s, reset);
398 "%s%s%s%s", substr, red, s, reset);
401 "%s%s%s%s", substr, yellowb, s, reset);
404 "%s%s%s%s", substr, yellow, s, reset);
407 "%s%s", substr,
"INVALID");
420 "%s%s%s%s", substr, blue, file, reset);
432 "%s%s%u%s", substr, green, line, reset);
444 "%s%s%s%s", substr, green,
function, reset);
468 if (error_code !=
SC_OK) {
470 "[%sERRCODE%s: %s%s%s(%s%d%s)] - ", yellow, reset, red,
SCErrorToString(error_code), reset, yellow, error_code, reset);
481 if (error_code >
SC_OK)
495 #define MAX_SUBSTRINGS 30
504 #undef MAX_SUBSTRINGS
516 if (op_iface_ctx->
file == NULL) {
520 if (op_iface_ctx->
file_d != NULL) {
521 fclose(op_iface_ctx->
file_d);
523 op_iface_ctx->
file_d = fopen(op_iface_ctx->
file,
"a");
524 if (op_iface_ctx->
file_d == NULL) {
542 const unsigned int line,
const char *
function,
543 const SCError error_code,
const char *message)
549 printf(
"Logging module not initialized. Call SCLogInitLogModule() "
550 "first before using the debug API\n");
556 gettimeofday(&tval, NULL);
559 while (op_iface_ctx != NULL) {
561 op_iface_ctx = op_iface_ctx->
next;
565 switch (op_iface_ctx->
iface) {
567 if (SCLogMessageGetBuffer(&tval, op_iface_ctx->
use_color, op_iface_ctx->
type,
568 buffer,
sizeof(buffer),
571 log_level, file, line,
function,
572 error_code, message) == 0)
574 SCLogPrintToStream((log_level ==
SC_LOG_ERROR)? stderr: stdout, buffer);
578 if (SCLogMessageGetBuffer(&tval, 0, op_iface_ctx->
type, buffer,
sizeof(buffer),
581 log_level, file, line,
function,
582 error_code, message) == 0)
587 r = SCLogReopen(op_iface_ctx);
590 SCLogPrintToStream(op_iface_ctx->
file_d, buffer);
596 op_iface_ctx->
file, strerror(errno));
601 if (SCLogMessageGetBuffer(&tval, 0, op_iface_ctx->
type, buffer,
sizeof(buffer),
604 log_level, file, line,
function,
605 error_code, message) == 0)
607 SCLogPrintToSyslog(SCLogMapLogLevelToSyslogLevel(log_level), buffer);
613 op_iface_ctx = op_iface_ctx->
next;
618 void SCLog(
int x,
const char *file,
const char *func,
const int line,
619 const char *fmt, ...)
631 vsnprintf(
msg,
sizeof(
msg), fmt, ap);
637 void SCLogErr(
int x,
const char *file,
const char *func,
const int line,
638 const int err,
const char *fmt, ...)
650 vsnprintf(
msg,
sizeof(
msg), fmt, ap);
690 "Fatal error encountered in SCLogAllocLogOPBuffer. Exiting...");
696 i++, op_iface_ctx = op_iface_ctx->
next) {
697 buffer[i].
log_format = op_iface_ctx->log_format;
698 buffer[i].
temp = buffer[i].
msg;
718 "Fatal error encountered in SCLogallocLogOPIfaceCtx. Exiting...");
737 const char *log_format,
743 if (iface_ctx == NULL) {
745 "Fatal error encountered in SCLogInitFileOPIface. Exiting...");
755 if ( (iface_ctx->
file_d = fopen(file,
"a")) == NULL) {
756 printf(
"Error opening file %s\n", file);
776 if (iface_ctx->
file != NULL) {
778 iface_ctx->
file = NULL;
784 if (iface_ctx->
file_d != NULL) {
785 fclose(iface_ctx->
file_d);
803 static inline SCLogOPIfaceCtx *SCLogInitConsoleOPIface(
const char *log_format,
808 if (iface_ctx == NULL) {
810 "Fatal error encountered in SCLogInitConsoleOPIface. Exiting...");
817 const char *tmp_log_format = log_format;
821 printf(
"Overriding setting for \"console.format\" because of env "
822 "var SC_LOG_FORMAT=\"%s\".\n", s);
827 if (tmp_log_format != NULL &&
829 printf(
"Error allocating memory\n");
840 printf(
"Overriding setting for \"console.level\" because of env "
841 "var SC_LOG_LEVEL=\"%s\".\n", s);
849 if (isatty(fileno(stdout)) && isatty(fileno(stderr))) {
868 const char *log_format,
874 if ( iface_ctx == NULL) {
876 "Fatal error encountered in SCLogInitSyslogOPIface. Exiting...");
886 if (log_format != NULL &&
888 printf(
"Error allocating memory\n");
908 while (iface_ctx != NULL) {
911 if (iface_ctx->
file_d != NULL) {
912 fclose(iface_ctx->
file_d);
916 if (iface_ctx->
file != NULL)
926 iface_ctx = iface_ctx->
next;
944 const char *s = NULL;
950 }
else if (sc_lid != NULL) {
960 if (sc_lid != NULL) {
961 printf(
"Warning: Invalid/No global_log_level assigned by user. Falling "
962 "back on the default_log_level \"%s\"\n",
979 static inline const char *SCLogGetDefaultLogFormat(
void)
982 if (strstr(prog_ver,
"RELEASE") != NULL) {
997 const char *format = NULL;
1001 if (format == NULL) {
1002 if (sc_lid != NULL) {
1009 format = SCLogGetDefaultLogFormat();
1011 if (sc_lid != NULL) {
1012 printf(
"Warning: Invalid/No global_log_format supplied by user or format "
1013 "length exceeded limit of \"%d\" characters. Falling back on "
1021 printf(
"Error allocating memory\n");
1039 const char *s = NULL;
1041 if (sc_lid != NULL && sc_lid->
op_ifaces != NULL) {
1053 printf(
"Warning: Invalid output interface supplied by user. "
1054 "Falling back on default_output_interface \"%s\"\n",
1062 if (sc_lid != NULL) {
1063 printf(
"Warning: Output_interface not supplied by user. Falling "
1064 "back on default_output_interface \"%s\"\n",
1109 const char *filter = NULL;
1117 if (filter == NULL) {
1118 if (sc_lid != NULL) {
1123 if (filter != NULL && strcmp(filter,
"") != 0) {
1126 printf(
"pcre filter alloc failed\n");
1132 printf(
"pcre compile of \"%s\" failed at offset %d : %s\n", filter,
1140 printf(
"pcre study failed: %s\n", ep);
1178 if (sc_lid != NULL) {
1179 SCLogFreeLogOPIfaceCtx(sc_lid->
op_ifaces);
1191 static inline void SCLogFreeLogConfig(
SCLogConfig *sc_lc)
1193 if (sc_lc != NULL) {
1206 SCLogFreeLogOPIfaceCtx(sc_lc->
op_ifaces);
1224 if (iface_ctx == NULL) {
1226 printf(
"Argument(s) to SCLogAppendOPIfaceCtx() NULL\n");
1232 while (temp != NULL) {
1240 prev->
next = iface_ctx;
1265 const char *log_format,
1266 int log_level,
const char *arg)
1270 if (log_level < SC_LOG_NONE || log_level >
SC_LOG_DEBUG) {
1272 printf(
"Warning: Supplied log_level_override for op_interface \"%s\" "
1273 "is invalid. Defaulting to not specifying an override\n",
1289 printf(
"Output Interface \"%s\" not supported by the logging module",
1310 #if defined (OS_WIN32)
1311 if (
SCMutexInit(&sc_log_stream_lock, NULL) != 0) {
1319 "Fatal error encountered in SCLogInitLogModule. Exiting...");
1323 SCLogSetLogLevel(sc_lid, sc_log_config);
1324 SCLogSetLogFormat(sc_lid, sc_log_config);
1325 SCLogSetOPIface(sc_lid, sc_log_config);
1326 SCLogSetOPFilter(sc_lid, sc_log_config);
1341 int have_logging = 0;
1352 if (outputs == NULL) {
1353 SCLogDebug(
"No logging.output configuration section found.");
1358 if (sc_lid == NULL) {
1359 SCLogDebug(
"Could not allocate memory for log init data");
1364 const char *default_log_level_s = NULL;
1365 if (
ConfGet(
"logging.default-log-level", &default_log_level_s) == 1) {
1368 if (default_log_level == -1) {
1370 default_log_level_s);
1389 const char *level_s;
1402 if (type_s != NULL) {
1403 if (strcmp(type_s,
"regular") == 0)
1405 else if (strcmp(type_s,
"json") == 0) {
1417 if (level_s != NULL) {
1424 max_level =
MAX(max_level, level);
1428 level =
MAX(min_level, level);
1430 if (strcmp(output->
name,
"console") == 0) {
1431 op_iface_ctx = SCLogInitConsoleOPIface(format, level,
type);
1433 else if (strcmp(output->
name,
"file") == 0) {
1435 if (filename == NULL) {
1437 "Logging to file requires a filename");
1441 path = SCLogGetLogFilename(filename);
1448 op_iface_ctx = SCLogInitFileOPIface(path, format, level,
type);
1451 else if (strcmp(output->
name,
"syslog") == 0) {
1455 if (facility_s != NULL) {
1457 if (facility == -1) {
1459 "facility: \"%s\", now using \"%s\" as syslog "
1464 SCLogDebug(
"Initializing syslog logging with format \"%s\"", format);
1466 op_iface_ctx = SCLogInitSyslogOPIface(facility, format, level,
type);
1470 "ignoring", output->
name);
1472 if (op_iface_ctx != NULL) {
1477 if (daemon && (have_logging == 0)) {
1479 "NO logging compatible with daemon mode selected,"
1480 " suricata won't be able to log. Please update "
1481 " 'logging.outputs' in the YAML.");
1505 static char *SCLogGetLogFilename(
const char *filearg)
1508 char *log_filename =
SCMalloc(PATH_MAX);
1509 if (
unlikely(log_filename == NULL))
1511 snprintf(log_filename, PATH_MAX,
"%s/%s", log_dir, filearg);
1512 return log_filename;
1520 SCLogFreeLogConfig(sc_log_config);
1526 sc_log_config = NULL;
1533 #if defined (OS_WIN32)
1551 static int SCLogTestInit01(
void)
1567 strcmp(SCLogGetDefaultLogFormat(), sc_log_config->
log_format) == 0);
1581 !strcmp(
"%n- %l", sc_log_config->
log_format));
1592 static int SCLogTestInit02(
void)
1597 char *logfile = SCLogGetLogFilename(
"boo.txt");
1621 strcmp(SCLogGetDefaultLogFormat(), sc_log_config->
log_format) == 0);
1629 SCLogFreeLogInitData(sc_lid);
1649 strcmp(
"kaboo", sc_log_config->
log_format) == 0);
1655 SCLogFreeLogInitData(sc_lid);
1662 static int SCLogTestInit03(
void)
1682 static int SCLogTestInit04(
void)
1710 static int SCLogTestInit05(
void)
1713 memset(
str,
'A',
sizeof(
str));
pcre_extra * op_filter_regex_study
#define SC_LOG_DEF_LOG_FORMAT_REL
#define SC_LOG_DEF_SYSLOG_FACILITY
SCLogOPIfaceCtx * op_ifaces
int SCLogMatchFGFilterBL(const char *file, const char *function, int line)
Checks if there is a match for the incoming log_message with any of the FG filters....
#define SC_LOG_DEF_SYSLOG_FACILITY_STR
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
@ SC_ERR_MISSING_CONFIG_PARAM
void SCLogInitLogModule(SCLogInitData *sc_lid)
Initializes the logging module.
#define syslog(__pri, __fmt, __param)
void SCLogLoadConfig(int daemon, int verbose)
void CreateIsoTimeString(const struct timeval *ts, char *str, size_t size)
SCEnumCharMap sc_log_level_map[]
int sc_log_fg_filters_present
void unsetenv(const char *name)
SCLogOPBuffer * SCLogAllocLogOPBuffer(void)
Allocates an output buffer for an output interface. Used when we want the op_interface log_format to ...
#define SC_LOG_FMT_PREFIX
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
ThreadVars * TmThreadsGetCallingThread(void)
Returns the TV for the calling thread.
#define SC_LOG_FMT_FILE_NAME
@ SC_ERR_LOG_FG_FILTER_MATCH
const char * global_log_format
struct HtpBodyChunk_ * next
Structure to be used when log_level override support would be provided by the logging module.
#define SC_LOG_ENV_LOG_OP_IFACE
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
#define SC_LOG_ENV_LOG_FACILITY
void SCLogDeInitLogModule(void)
De-Initializes the logging module.
#define TAILQ_FOREACH(var, head, field)
int sc_log_module_initialized
Used to indicate whether the logging module has been init or not.
#define SC_LOG_DEF_LOG_OP_IFACE
Structure containing init data, that would be passed to SCInitDebugModule()
#define JSON_ESCAPE_SLASH
#define SC_LOG_FMT_LOG_LEVEL
const char * SCErrorToString(SCError err)
Maps the error code, to its string equivalent.
int SCLogMatchFDFilter(const char *function)
Checks if there is a match for the incoming log_message with any of the FD filters.
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
void SCLog(int x, const char *file, const char *func, const int line, const char *fmt,...)
size_t strlcpy(char *dst, const char *src, size_t siz)
void SCLogReleaseFGFilters(void)
The output interface context for the logging module.
void OutputRegisterFileRotationFlag(int *flag)
Register a flag for file rotation notification.
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
#define SC_LOG_ENV_LOG_LEVEL
ENV vars that can be used to set the properties for the logging module.
void SCLogReleaseFDFilters(void)
Releases all the FD filters added to the logging module.
#define PASS
Pass the test.
int SCLogPrintFGFilters()
Prints the FG filters(both WL and BL). Used for debugging purposes.
SCEnumCharMap * SCSyslogGetFacilityMap(void)
returns the syslog facility enum map
#define SCMutexUnlock(mut)
SCLogOPIfaceCtx * SCLogInitOPIfaceCtx(const char *iface_name, const char *log_format, int log_level, const char *arg)
Creates a new output interface based on the arguments sent. The kind of output interface to be create...
void SCLogRegisterTests()
Per thread variable structure.
@ SC_ERR_INVALID_ARGUMENT
const char * GetProgramVersion(void)
get string with program version
#define SC_LOG_ENV_LOG_FILE
struct tm * SCLocalTime(time_t timep, struct tm *result)
int SCLogMatchFGFilterWL(const char *file, const char *function, int line)
Checks if there is a match for the incoming log_message with any of the FG filters....
int sc_log_module_cleaned
Used to indicate whether the logging module has been cleaned or not.
char msg[SC_LOG_MAX_LOG_MSG_LEN]
SCLogLevel global_log_level
#define SC_LOG_DEF_LOG_FILE
void setenv(const char *name, const char *value, int overwrite)
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
SCError SCLogMessage(const SCLogLevel log_level, const char *file, const unsigned int line, const char *function, const SCError error_code, const char *message)
Adds the global log_format to the outgoing buffer.
SCLogLevel
The various log levels NOTE: when adding new level, don't forget to update SCLogMapLogLevelToSyslogLe...
#define SCMutexInit(mut, mutattrs)
#define SC_LOG_MAX_LOG_FORMAT_LEN
#define SCGetThreadIdLong(...)
SCEnumCharMap sc_log_op_iface_map[]
ConfNode * ConfNodeLookupChild(const ConfNode *node, const char *name)
Lookup a child configuration node by name.
const char * SCMapEnumValueToName(int enum_value, SCEnumCharMap *table)
Maps an enum value to a string name, from the supplied table.
int SCLogPrintFDFilters(void)
Prints the FG filters(both WL and BL). Used for debugging purposes.
int SCMapEnumNameToValue(const char *enum_name, SCEnumCharMap *table)
Maps a string name to an enum value from the supplied table. Please specify the last element of any m...
#define SC_LOG_DEF_LOG_LEVEL
#define SC_LOG_ENV_LOG_OP_FILTER
struct SCLogOPIfaceCtx_ * next
#define SC_LOG_ENV_LOG_FORMAT
int PathIsAbsolute(const char *path)
Check if a path is absolute.
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Holds the config state used by the logging api.
#define SC_LOG_DEF_LOG_FORMAT_DEV
int sc_log_fd_filters_present
#define FatalError(x,...)
void SCLogErr(int x, const char *file, const char *func, const int line, const int err, const char *fmt,...)
SCLogInitData * SCLogAllocLogInitData(void)
Returns a pointer to a new SCLogInitData. This is a public interface intended to be used after the lo...
const char * ConfigGetLogDirectory()
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
#define SC_LOG_MAX_LOG_MSG_LEN
#define SC_LOG_FMT_FUNCTION
int ConfValIsFalse(const char *val)
Check if a value is false.
int SCLogRemoveFDFilter(const char *function)
Removes a Function-Dependent(FD) filter.
SCLogLevel sc_log_global_log_level
Holds the global log level. Is the same as sc_log_config->log_level.
int SCLogAddFGFilterBL(const char *file, const char *function, int line)
Adds a Blacklist(BL) fine-grained(FG) filter. A FG filter BL filter allows messages that don't match ...
void SCLogAppendOPIfaceCtx(SCLogOPIfaceCtx *iface_ctx, SCLogInitData *sc_lid)
Appends an output_interface to the output_interface list sent in head.
const char * startup_message
int SCLogAddFDFilter(const char *function)
Adds a Function-Dependent(FD) filter.
#define openlog(__ident, __option, __facility)
SCLogOPIfaceCtx * op_ifaces
SCLogLevel SCLogGetLogLevel(void)
@ SC_LOG_OP_IFACE_CONSOLE
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
const char * ConfNodeLookupChildValue(const ConfNode *node, const char *name)
Lookup the value of a child configuration node by name.