80static SCMutex sc_log_stream_lock;
86static const char *SCTransformModule(
const char *module_name,
int *dn_len);
96static char *SCLogGetLogFilename(
const char *);
121static inline int SCLogMapLogLevelToSyslogLevel(
int log_level)
123 int syslog_log_level = 0;
148 return syslog_log_level;
157static inline void SCLogPrintToStream(FILE *fd,
char *msg)
164#if defined (OS_WIN32)
168 if (fprintf(fd,
"%s\n", msg) < 0)
169 printf(
"Error writing to stream using fprintf\n");
173#if defined (OS_WIN32)
188static inline void SCLogPrintToSyslog(
int syslog_log_level,
const char *msg)
193 syslog(syslog_log_level,
"%s", msg);
198static int SCLogMessageJSON(
SCTime_t tval,
char *buffer,
size_t buffer_size,
SCLogLevel log_level,
199 const char *file,
unsigned line,
const char *function,
const char *module,
202 SCJsonBuilder *js = SCJbNewObject();
208 SCJbSetString(js,
"timestamp", timebuf);
212 SCJbSetString(js,
"log_level", s);
218 SCJbOpenObject(js,
"engine");
221 SCJbSetString(js,
"message", message);
231 dn_name = SCTransformModule(module, &dn_len);
232 SCJbSetString(js,
"module", dn_name);
237 SCJbSetString(js,
"function", function);
240 SCJbSetString(js,
"file", file);
243 SCJbSetUint(js,
"line", line);
248 memcpy(buffer, SCJbPtr(js),
MIN(buffer_size, SCJbLen(js)));
258static const int transform_max_segs = 2;
277static const char *SCTransformModule(
const char *module_name,
int *dn_len)
288 if (strncmp(
"tm-", module_name, 3) == 0) {
289 *dn_len = (int)strlen(module_name) - 3;
290 return module_name + 3;
291 }
else if (strncmp(
"util-", module_name, 5) == 0) {
292 *dn_len = (int)strlen(module_name) - 5;
293 return module_name + 5;
294 }
else if (strncmp(
"source-pcap-file", module_name, 16) == 0) {
295 *dn_len = (int)strlen(
"pcap");
297 }
else if (strncmp(
"source-", module_name, 7) == 0) {
298 *dn_len = (int)strlen(module_name) - 7;
299 return module_name + 7;
300 }
else if (strncmp(
"runmode-", module_name, 8) == 0) {
301 *dn_len = (int)strlen(module_name) - 8;
302 return module_name + 8;
303 }
else if (strncmp(
"app-layer-", module_name, 10) == 0) {
304 *dn_len = (int)strlen(module_name);
306 }
else if (strncmp(
"detect-engine", module_name, 13) == 0) {
307 *dn_len = (int)strlen(
"detect");
314 char *w = (
char *)module_name;
315 while (w && (w = strchr(w,
'-')) != NULL && seg_cnt < transform_max_segs) {
321 if (seg_cnt < transform_max_segs)
322 *dn_len = (int)strlen(module_name);
324 *dn_len = (int)(last - module_name);
341 size_t buffer_size,
const char *log_format,
const SCLogLevel log_level,
const char *file,
342 const unsigned int line,
const char *function,
const char *module,
const char *message)
345 return SCLogMessageJSON(
346 tval, buffer, buffer_size, log_level, file, line, function, module, message);
349 const char *s = NULL;
350 struct tm *tms = NULL;
352 const char *redb =
"";
353 const char *red =
"";
354 const char *yellowb =
"";
355 const char *yellow =
"";
356 const char *green =
"";
357 const char *blue =
"";
358 const char *reset =
"";
362 yellowb =
"\x1b[1;33m";
374 const int add_M = strstr(log_format,
"%M") == NULL;
375 char local_format[strlen(log_format) + add_M * 2 + 1];
376 strlcpy(local_format, log_format,
sizeof(local_format));
378 strlcat(local_format,
"%M",
sizeof(local_format));
379 char *temp_fmt = local_format;
380 char *substr = temp_fmt;
387 switch(temp_fmt[1]) {
394 "%s%s%04d-%02d-%02d %02d:%02d:%02d%s", substr, green, tms->tm_year + 1900,
395 tms->tm_mon + 1, tms->tm_mday, tms->tm_hour, tms->tm_min, tms->tm_sec,
411 "%s%s%d/%d/%04d -- %02d:%02d:%02d%s",
412 substr, green, tms->tm_mday, tms->tm_mon + 1,
413 tms->tm_year + 1900, tms->tm_hour, tms->tm_min,
426 "%s%s%u%s", substr, yellow, getpid(), reset);
466 "%s%s%s%s", substr, redb, s, reset);
469 "%s%s%s%s", substr, red, s, reset);
472 "%s%s%s%s", substr, yellowb, s, reset);
475 substr, yellow, s, reset);
494 substr, redb, s, reset);
497 substr, red, s, reset);
500 substr, yellowb, s, reset);
503 "%s%s%s%s", substr, yellow, s, reset);
506 "%s%s", substr,
"INVALID");
519 "%s%s%s%s", substr, blue, file, reset);
531 "%s%s%u%s", substr, green, line, reset);
545 const char *dn_name =
"unknown";
547 dn_name = SCTransformModule(module, &dn_len);
551 green, dn_name, reset);
563 "%s%s%s%s", substr, green, function, reset);
612 if (pcre2_match(sc_log_config->
op_filter_regex, (PCRE2_SPTR8)buffer, strlen(buffer), 0, 0,
627 if (op_iface_ctx->
file == NULL) {
631 if (op_iface_ctx->
file_d != NULL) {
632 fclose(op_iface_ctx->
file_d);
634 op_iface_ctx->
file_d = fopen(op_iface_ctx->
file,
"a");
635 if (op_iface_ctx->
file_d == NULL) {
653 const char *function,
const char *module,
const char *message)
659 printf(
"Logging module not initialized. Call SCLogInitLogModule() "
660 "first before using the debug API\n");
666 gettimeofday(&tval, NULL);
670 while (op_iface_ctx != NULL) {
672 op_iface_ctx = op_iface_ctx->
next;
676 switch (op_iface_ctx->
iface) {
678 if (SCLogMessageGetBuffer(
ts, op_iface_ctx->
use_color, op_iface_ctx->
type, buffer,
682 log_level, file, line, function, module, message) == 0) {
683 SCLogPrintToStream((log_level ==
SC_LOG_ERROR)? stderr: stdout, buffer);
687 if (SCLogMessageGetBuffer(
ts, 0, op_iface_ctx->
type, buffer,
sizeof(buffer),
690 log_level, file, line, function, module, message) == 0) {
694 r = SCLogReopen(op_iface_ctx);
697 SCLogPrintToStream(op_iface_ctx->
file_d, buffer);
702 SCLogError(
"re-opening file \"%s\" failed: %s", op_iface_ctx->
file,
708 if (SCLogMessageGetBuffer(
ts, 0, op_iface_ctx->
type, buffer,
sizeof(buffer),
711 log_level, file, line, function, module, message) == 0) {
712 SCLogPrintToSyslog(SCLogMapLogLevelToSyslogLevel(log_level), buffer);
718 op_iface_ctx = op_iface_ctx->
next;
723void SCLog(
int x,
const char *file,
const char *func,
const int line,
const char *module,
724 const char *fmt, ...)
736 vsnprintf(msg,
sizeof(msg), fmt, ap);
742void SCLogErr(
int x,
const char *file,
const char *func,
const int line,
const char *module,
743 const char *fmt, ...)
755 vsnprintf(msg,
sizeof(msg), fmt, ap);
792 FatalError(
"Fatal error encountered in SCLogAllocLogOPBuffer. Exiting...");
796 for (
int i = 0; i < sc_log_config->
op_ifaces_cnt; i++, op_iface_ctx = op_iface_ctx->
next) {
798 buffer[i].
temp = buffer[i].
msg;
817 FatalError(
"Fatal error encountered in SCLogallocLogOPIfaceCtx. Exiting...");
834static inline SCLogOPIfaceCtx *SCLogInitFileOPIface(
const char *file, uint32_t userid,
835 uint32_t groupid,
const char *log_format,
int log_level,
SCLogOPType type)
838 if (iface_ctx == NULL) {
839 FatalError(
"Fatal error encountered in SCLogInitFileOPIface. Exiting...");
849 if ( (iface_ctx->
file_d = fopen(file,
"a")) == NULL) {
850 SCLogWarning(
"error opening file %s: %s", file, strerror(errno));
855 if (userid != 0 || groupid != 0) {
856 if (fchown(fileno(iface_ctx->
file_d), userid, groupid) == -1) {
857 SCLogWarning(
"Failed to change ownership of file %s: %s", file, strerror(errno));
878 if (iface_ctx->
file != NULL) {
880 iface_ctx->
file = NULL;
886 if (iface_ctx->
file_d != NULL) {
887 fclose(iface_ctx->
file_d);
905static inline SCLogOPIfaceCtx *SCLogInitConsoleOPIface(
const char *log_format,
910 if (iface_ctx == NULL) {
911 FatalError(
"Fatal error encountered in SCLogInitConsoleOPIface. Exiting...");
918 const char *tmp_log_format = log_format;
922 printf(
"Overriding setting for \"console.format\" because of env "
923 "var SC_LOG_FORMAT=\"%s\".\n", s);
928 if (tmp_log_format != NULL &&
930 printf(
"Error allocating memory\n");
941 printf(
"Overriding setting for \"console.level\" because of env "
942 "var SC_LOG_LEVEL=\"%s\".\n", s);
950 if (isatty(fileno(stdout)) && isatty(fileno(stderr))) {
969 const char *log_format,
975 if ( iface_ctx == NULL) {
976 FatalError(
"Fatal error encountered in SCLogInitSyslogOPIface. Exiting...");
986 if (log_format != NULL &&
988 printf(
"Error allocating memory\n");
1008 while (iface_ctx != NULL) {
1011 if (iface_ctx->
file_d != NULL) {
1012 fclose(iface_ctx->
file_d);
1016 if (iface_ctx->
file != NULL)
1026 iface_ctx = iface_ctx->
next;
1042 const char *s = NULL;
1048 }
else if (sc_lid != NULL) {
1058 if (sc_lid != NULL) {
1059 printf(
"Warning: Invalid/No global_log_level assigned by user. Falling "
1060 "back on the default_log_level \"%s\"\n",
1075static inline const char *SCLogGetDefaultLogFormat(
const SCLogLevel lvl)
1078 if (strstr(prog_ver,
"RELEASE") != NULL) {
1098 const char *format = NULL;
1102 if (format == NULL) {
1103 if (sc_lid != NULL) {
1110 format = SCLogGetDefaultLogFormat(sc_lc->
log_level);
1112 if (sc_lid != NULL) {
1113 printf(
"Warning: Invalid/No global_log_format supplied by user or format "
1114 "length exceeded limit of \"%d\" characters. Falling back on "
1122 printf(
"Error allocating memory\n");
1138 const char *s = NULL;
1140 if (sc_lid != NULL && sc_lid->
op_ifaces != NULL) {
1152 printf(
"Warning: Invalid output interface supplied by user. "
1153 "Falling back on default_output_interface \"%s\"\n",
1161 if (sc_lid != NULL) {
1162 printf(
"Warning: Output_interface not supplied by user. Falling "
1163 "back on default_output_interface \"%s\"\n",
1207 const char *filter = NULL;
1215 if (filter == NULL) {
1216 if (sc_lid != NULL) {
1221 if (filter != NULL && strcmp(filter,
"") != 0) {
1224 printf(
"pcre filter alloc failed\n");
1228 pcre2_compile((PCRE2_SPTR8)filter, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
1231 PCRE2_UCHAR errbuffer[256];
1232 pcre2_get_error_message(en, errbuffer,
sizeof(errbuffer));
1233 printf(
"pcre2 compile of \"%s\" failed at offset %d : %s\n", filter, (
int)eo,
1269 if (sc_lid != NULL) {
1270 SCLogFreeLogOPIfaceCtx(sc_lid->
op_ifaces);
1280static inline void SCLogFreeLogConfig(
SCLogConfig *sc_lc)
1282 if (sc_lc != NULL) {
1295 SCLogFreeLogOPIfaceCtx(sc_lc->
op_ifaces);
1311 if (iface_ctx == NULL) {
1313 printf(
"Argument(s) to SCLogAppendOPIfaceCtx() NULL\n");
1319 while (temp != NULL) {
1327 prev->
next = iface_ctx;
1352 const char *iface_name,
const char *log_format,
int log_level,
const char *arg)
1356 if (log_level < SC_LOG_NONE || log_level >
SC_LOG_DEBUG) {
1357 printf(
"Warning: Supplied log_level_override for op_interface \"%s\" "
1358 "is invalid. Defaulting to not specifying an override\n",
1373 printf(
"Output Interface \"%s\" not supported by the logging module",
1396#if defined (OS_WIN32)
1397 if (
SCMutexInit(&sc_log_stream_lock, NULL) != 0) {
1398 FatalError(
"Failed to initialize log mutex.");
1404 FatalError(
"Fatal error encountered in SCLogInitLogModule. Exiting...");
1407 SCLogSetLogLevel(sc_lid, sc_log_config);
1408 SCLogSetLogFormat(sc_lid, sc_log_config);
1409 SCLogSetOPIface(sc_lid, sc_log_config);
1410 SCLogSetOPFilter(sc_lid, sc_log_config);
1424 int have_logging = 0;
1435 if (outputs == NULL) {
1436 SCLogDebug(
"No logging.output configuration section found.");
1441 if (sc_lid == NULL) {
1442 SCLogDebug(
"Could not allocate memory for log init data");
1447 const char *default_log_level_s = NULL;
1448 if (
SCConfGet(
"logging.default-log-level", &default_log_level_s) == 1) {
1451 if (default_log_level == -1) {
1452 SCLogError(
"Invalid default log level: %s", default_log_level_s);
1470 const char *level_s;
1483 if (type_s != NULL) {
1484 if (strcmp(type_s,
"regular") == 0)
1486 else if (strcmp(type_s,
"json") == 0) {
1494 if (level_s != NULL) {
1497 SCLogError(
"Invalid log level: %s", level_s);
1500 max_level =
MAX(max_level, level);
1504 level =
MAX(min_level, level);
1506 if (strcmp(output->
name,
"console") == 0) {
1507 op_iface_ctx = SCLogInitConsoleOPIface(format, level,
type);
1509 else if (strcmp(output->
name,
"file") == 0) {
1510 if (format == NULL) {
1515 if (filename == NULL) {
1516 FatalError(
"Logging to file requires a filename");
1520 path = SCLogGetLogFilename(filename);
1525 FatalError(
"failed to setup output to file");
1527 op_iface_ctx = SCLogInitFileOPIface(path, userid, groupid, format, level,
type);
1530 else if (strcmp(output->
name,
"syslog") == 0) {
1533 if (facility_s != NULL) {
1535 if (facility == -1) {
1537 "facility: \"%s\", now using \"%s\" as syslog "
1543 SCLogDebug(
"Initializing syslog logging with format \"%s\"", format);
1545 op_iface_ctx = SCLogInitSyslogOPIface(facility, format, level,
type);
1550 if (op_iface_ctx != NULL) {
1555 if (daemon && (have_logging == 0)) {
1556 SCLogWarning(
"no logging compatible with daemon mode selected,"
1557 " suricata won't be able to log. Please update "
1558 " 'logging.outputs' in the YAML.");
1581static char *SCLogGetLogFilename(
const char *filearg)
1584 char *log_filename =
SCMalloc(PATH_MAX);
1585 if (
unlikely(log_filename == NULL))
1587 snprintf(log_filename, PATH_MAX,
"%s/%s", log_dir, filearg);
1588 return log_filename;
1596 SCLogFreeLogConfig(sc_log_config);
1602 sc_log_config = NULL;
1609#if defined (OS_WIN32)
1630static int SCLogTestInit01(
void)
1646 strcmp(SCLogGetDefaultLogFormat(sc_log_config->
log_level),
1661 !strcmp(
"%n- %l", sc_log_config->
log_format));
1672static int SCLogTestInit02(
void)
1677 char *logfile = SCLogGetLogFilename(
"boo.txt");
1683 sc_iface_ctx = SCLogInitOPIfaceCtx(
"file",
"%m - %d",
SC_LOG_WARNING, logfile);
1685 sc_iface_ctx = SCLogInitOPIfaceCtx(
"console", NULL,
SC_LOG_ERROR,
1700 strcmp(SCLogGetDefaultLogFormat(sc_log_config->
log_level),
1709 SCLogFreeLogInitData(sc_lid);
1729 strcmp(
"kaboo", sc_log_config->
log_format) == 0);
1735 SCLogFreeLogInitData(sc_lid);
1742static int SCLogTestInit03(
void)
1762static int SCLogTestInit04(
void)
1790static int SCLogTestInit05(
void)
1793 memset(
str,
'A',
sizeof(
str));
struct HtpBodyChunk_ * next
SCConfNode * SCConfNodeLookupChild(const SCConfNode *node, const char *name)
Lookup a child configuration node by name.
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
int SCConfValIsFalse(const char *val)
Check if a value is false.
int SCConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
void OutputRegisterFileRotationFlag(int *flag)
Register a flag for file rotation notification.
#define TAILQ_FOREACH(var, head, field)
#define JB_SET_STRING(jb, key, val)
Holds the config state used by the logging api.
pcre2_match_data * op_filter_regex_match
SCLogOPIfaceCtx * op_ifaces
pcre2_code * op_filter_regex
Structure containing init data, that would be passed to SCInitDebugModule()
SCLogOPIfaceCtx * op_ifaces
SCLogLevel global_log_level
const char * startup_message
const char * global_log_format
Structure to be used when log_level override support would be provided by the logging module.
char msg[SC_LOG_MAX_LOG_MSG_LEN]
The output interface context for the logging module.
struct SCLogOPIfaceCtx_ * next
size_t strlcat(char *, const char *src, size_t siz)
size_t strlcpy(char *dst, const char *src, size_t siz)
const char * GetProgramVersion(void)
get string with program version
#define SCMutexUnlock(mut)
#define SCMutexInit(mut, mutattrs)
thread_local char t_thread_name[THREAD_NAME_LEN+1]
#define SCGetThreadIdLong(...)
const char * SCConfigGetLogDirectory(void)
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_fd_filters_present
int SCLogMatchFDFilter(const char *function)
Checks if there is a match for the incoming log_message with any of the FD filters.
void SCLogReleaseFDFilters(void)
Releases all the FD filters added to the logging module.
int SCLogPrintFGFilters(void)
Prints the FG filters(both WL and BL). Used for debugging purposes.
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....
int sc_log_fg_filters_present
void SCLogReleaseFGFilters(void)
int SCLogAddFDFilter(const char *function)
Adds a Function-Dependent(FD) filter.
int SCLogRemoveFDFilter(const char *function)
Removes a Function-Dependent(FD) filter.
int SCLogPrintFDFilters(void)
Prints the FG filters(both WL and BL). Used for debugging purposes.
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 ...
SCEnumCharMap sc_log_op_iface_map[]
int sc_log_module_cleaned
Used to indicate whether the logging module has been cleaned or not.
SCLogOPBuffer * SCLogAllocLogOPBuffer(void)
Allocates an output buffer for an output interface. Used when we want the op_interface log_format to ...
void SCLogDeInitLogModule(void)
De-Initializes the logging module.
SCLogLevel sc_log_global_log_level
Holds the global log level. Is the same as sc_log_config->log_level.
void SCLogLoadConfig(int daemon, int verbose, uint32_t userid, uint32_t groupid)
int sc_log_module_initialized
Used to indicate whether the logging module has been init or not.
SCEnumCharMap sc_log_slevel_map[]
SCLogInitData * SCLogAllocLogInitData(void)
Returns a pointer to a new SCLogInitData. This is a public interface intended to be used after the lo...
void SCLogErr(int x, const char *file, const char *func, const int line, const char *module, const char *fmt,...)
SCLogLevel SCLogGetLogLevel(void)
void SCFatalErrorOnInitStatic(const char *arg)
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
void SCLogRegisterTests(void)
SCError SCLogMessage(const SCLogLevel log_level, const char *file, const unsigned int line, const char *function, const char *module, const char *message)
Adds the global log_format to the outgoing buffer.
void SCLog(int x, const char *file, const char *func, const int line, const char *module, const char *fmt,...)
void SCLogInitLogModule(SCLogInitData *sc_lid)
Initializes the logging module.
SCEnumCharMap sc_log_level_map[]
void SCLogAppendOPIfaceCtx(SCLogOPIfaceCtx *iface_ctx, SCLogInitData *sc_lid)
Appends an output_interface to the output_interface list sent in head.
#define FatalErrorOnInit(...)
Fatal error IF we're starting up, and configured to consider errors to be fatal errors.
#define SC_LOG_DEF_LOG_FORMAT_REL_CONFIG
#define SC_LOG_FMT_THREAD_NAME
#define SC_LOG_DEF_LOG_FORMAT_DEBUG
SCLogLevel
The various log levels NOTE: when adding new level, don't forget to update SCLogMapLogLevelToSyslogLe...
#define SC_LOG_MAX_LOG_MSG_LEN
#define SC_LOG_DEF_LOG_FORMAT_REL_INFO
#define SC_LOG_DEF_LOG_FORMAT_REL_NOTICE
#define SC_LOG_DEF_FILE_FORMAT
#define SC_LOG_ENV_LOG_FACILITY
#define SC_LOG_FMT_SUBSYSTEM
#define SC_LOG_FMT_PREFIX
#define SC_LOG_DEF_LOG_FILE
#define SC_LOG_ENV_LOG_OP_IFACE
#define SC_LOG_FMT_MESSAGE
#define SC_LOG_ENV_LOG_LEVEL
ENV vars that can be used to set the properties for the logging module.
#define SCLogWarning(...)
Macro used to log WARNING messages.
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
#define SC_LOG_FMT_FUNCTION
#define SC_LOG_FMT_LOG_LEVEL
#define SC_LOG_DEF_LOG_OP_IFACE
@ SC_LOG_OP_IFACE_CONSOLE
#define SC_LOG_ENV_LOG_FILE
#define SC_LOG_ENV_LOG_FORMAT
#define SC_LOG_FMT_LOG_SLEVEL
#define SCLogError(...)
Macro used to log ERROR messages.
#define SC_LOG_DEF_SYSLOG_FACILITY_STR
#define SC_LOG_ENV_LOG_OP_FILTER
#define SC_LOG_DEF_LOG_LEVEL
#define SC_LOG_FMT_TIME_LEGACY
#define SC_LOG_FMT_FILE_NAME
#define SC_LOG_MAX_LOG_FORMAT_LEN
#define SC_LOG_DEF_SYSLOG_FACILITY
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...
const char * SCMapEnumValueToName(int enum_value, SCEnumCharMap *table)
Maps an enum value to a string name, from the supplied table.
int PathIsAbsolute(const char *path)
Check if a path is absolute.
SCEnumCharMap * SCSyslogGetFacilityMap(void)
returns the syslog facility enum map
struct tm * SCLocalTime(time_t timep, struct tm *result)
void CreateIsoTimeString(const SCTime_t ts, char *str, size_t size)
#define SCTIME_FROM_TIMEVAL(tv)
#define DEBUG_VALIDATE_BUG_ON(exp)
void setenv(const char *name, const char *value, int overwrite)
void unsetenv(const char *name)
#define syslog(__pri, __fmt, __param)
#define openlog(__ident, __option, __facility)