76 #if defined (OS_WIN32)
80 static SCMutex sc_log_stream_lock;
86 static const char *SCTransformModule(
const char *module_name,
int *dn_len);
96 static char *SCLogGetLogFilename(
const char *);
121 static inline int SCLogMapLogLevelToSyslogLevel(
int log_level)
123 int syslog_log_level = 0;
148 return syslog_log_level;
157 static 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)
190 static inline void SCLogPrintToSyslog(
int syslog_log_level,
const char *
msg)
202 static int SCLogMessageJSON(
SCTime_t tval,
char *buffer,
size_t buffer_size,
SCLogLevel log_level,
203 const char *file,
unsigned line,
const char *
function,
const char *module,
206 JsonBuilder *js = jb_new_object();
212 jb_set_string(js,
"timestamp", timebuf);
216 jb_set_string(js,
"log_level", s);
222 jb_open_object(js,
"engine");
225 jb_set_string(js,
"message", message);
235 dn_name = SCTransformModule(module, &dn_len);
236 jb_set_string(js,
"module", dn_name);
241 jb_set_string(js,
"function",
function);
244 jb_set_string(js,
"file", file);
247 jb_set_uint(js,
"line", line);
252 memcpy(buffer, jb_ptr(js),
MIN(buffer_size, jb_len(js)));
262 static const int transform_max_segs = 2;
281 static const char *SCTransformModule(
const char *module_name,
int *dn_len)
292 if (strncmp(
"tm-", module_name, 3) == 0) {
293 *dn_len = strlen(module_name) - 3;
294 return module_name + 3;
295 }
else if (strncmp(
"util-", module_name, 5) == 0) {
296 *dn_len = strlen(module_name) - 5;
297 return module_name + 5;
298 }
else if (strncmp(
"source-pcap-file", module_name, 16) == 0) {
299 *dn_len = strlen(
"pcap");
301 }
else if (strncmp(
"source-", module_name, 7) == 0) {
302 *dn_len = strlen(module_name) - 7;
303 return module_name + 7;
304 }
else if (strncmp(
"runmode-", module_name, 8) == 0) {
305 *dn_len = strlen(module_name) - 8;
306 return module_name + 8;
307 }
else if (strncmp(
"app-layer-", module_name, 10) == 0) {
308 *dn_len = strlen(module_name);
310 }
else if (strncmp(
"detect-engine", module_name, 13) == 0) {
311 *dn_len = strlen(
"detect");
318 char *w = (
char *)module_name;
319 while (w && (w = strchr(w,
'-')) != NULL && seg_cnt < transform_max_segs) {
325 if (seg_cnt < transform_max_segs)
326 *dn_len = strlen(module_name);
328 *dn_len = last - module_name;
345 size_t buffer_size,
const char *log_format,
const SCLogLevel log_level,
const char *file,
346 const unsigned int line,
const char *
function,
const char *module,
const char *message)
349 return SCLogMessageJSON(
350 tval, buffer, buffer_size, log_level, file, line,
function, module, message);
353 const char *s = NULL;
354 struct tm *tms = NULL;
356 const char *redb =
"";
357 const char *red =
"";
358 const char *yellowb =
"";
359 const char *yellow =
"";
360 const char *green =
"";
361 const char *blue =
"";
362 const char *reset =
"";
366 yellowb =
"\x1b[1;33m";
378 const int add_M = strstr(log_format,
"%M") == NULL;
379 char local_format[strlen(log_format) + add_M * 2 + 1];
380 strlcpy(local_format, log_format,
sizeof(local_format));
382 strlcat(local_format,
"%M",
sizeof(local_format));
383 char *temp_fmt = local_format;
384 char *substr = temp_fmt;
391 switch(temp_fmt[1]) {
398 "%s%s%04d-%02d-%02d %02d:%02d:%02d%s", substr, green, tms->tm_year + 1900,
399 tms->tm_mon + 1, tms->tm_mday, tms->tm_hour, tms->tm_min, tms->tm_sec,
415 "%s%s%d/%d/%04d -- %02d:%02d:%02d%s",
416 substr, green, tms->tm_mday, tms->tm_mon + 1,
417 tms->tm_year + 1900, tms->tm_hour, tms->tm_min,
430 "%s%s%u%s", substr, yellow, getpid(), reset);
470 "%s%s%s%s", substr, redb, s, reset);
473 "%s%s%s%s", substr, red, s, reset);
476 "%s%s%s%s", substr, yellowb, s, reset);
479 substr, yellow, s, reset);
498 substr, redb, s, reset);
501 substr, red, s, reset);
504 substr, yellowb, s, reset);
507 "%s%s%s%s", substr, yellow, s, reset);
510 "%s%s", substr,
"INVALID");
523 "%s%s%s%s", substr, blue, file, reset);
535 "%s%s%u%s", substr, green, line, reset);
549 const char *dn_name =
"unknown";
551 dn_name = SCTransformModule(module, &dn_len);
555 green, dn_name, reset);
567 "%s%s%s%s", substr, green,
function, reset);
616 if (pcre2_match(sc_log_config->
op_filter_regex, (PCRE2_SPTR8)buffer, strlen(buffer), 0, 0,
631 if (op_iface_ctx->
file == NULL) {
635 if (op_iface_ctx->
file_d != NULL) {
636 fclose(op_iface_ctx->
file_d);
638 op_iface_ctx->
file_d = fopen(op_iface_ctx->
file,
"a");
639 if (op_iface_ctx->
file_d == NULL) {
657 const char *
function,
const char *module,
const char *message)
663 printf(
"Logging module not initialized. Call SCLogInitLogModule() "
664 "first before using the debug API\n");
670 gettimeofday(&tval, NULL);
674 while (op_iface_ctx != NULL) {
676 op_iface_ctx = op_iface_ctx->
next;
680 switch (op_iface_ctx->
iface) {
682 if (SCLogMessageGetBuffer(
ts, op_iface_ctx->
use_color, op_iface_ctx->
type, buffer,
686 log_level, file, line,
function, module, message) == 0) {
687 SCLogPrintToStream((log_level ==
SC_LOG_ERROR)? stderr: stdout, buffer);
691 if (SCLogMessageGetBuffer(
ts, 0, op_iface_ctx->
type, buffer,
sizeof(buffer),
694 log_level, file, line,
function, module, message) == 0) {
698 r = SCLogReopen(op_iface_ctx);
701 SCLogPrintToStream(op_iface_ctx->
file_d, buffer);
706 SCLogError(
"re-opening file \"%s\" failed: %s", op_iface_ctx->
file,
712 if (SCLogMessageGetBuffer(
ts, 0, op_iface_ctx->
type, buffer,
sizeof(buffer),
715 log_level, file, line,
function, module, message) == 0) {
716 SCLogPrintToSyslog(SCLogMapLogLevelToSyslogLevel(log_level), buffer);
722 op_iface_ctx = op_iface_ctx->
next;
727 void SCLog(
int x,
const char *file,
const char *func,
const int line,
const char *module,
728 const char *fmt, ...)
740 vsnprintf(
msg,
sizeof(
msg), fmt, ap);
746 void SCLogErr(
int x,
const char *file,
const char *func,
const int line,
const char *module,
747 const char *fmt, ...)
759 vsnprintf(
msg,
sizeof(
msg), fmt, ap);
796 FatalError(
"Fatal error encountered in SCLogAllocLogOPBuffer. Exiting...");
800 for (
int i = 0; i < sc_log_config->
op_ifaces_cnt; i++, op_iface_ctx = op_iface_ctx->
next) {
801 buffer[i].
log_format = op_iface_ctx->log_format;
802 buffer[i].
temp = buffer[i].
msg;
821 FatalError(
"Fatal error encountered in SCLogallocLogOPIfaceCtx. Exiting...");
838 static inline SCLogOPIfaceCtx *SCLogInitFileOPIface(
const char *file, uint32_t userid,
839 uint32_t groupid,
const char *log_format,
int log_level,
SCLogOPType type)
842 if (iface_ctx == NULL) {
843 FatalError(
"Fatal error encountered in SCLogInitFileOPIface. Exiting...");
853 if ( (iface_ctx->
file_d = fopen(file,
"a")) == NULL) {
854 SCLogWarning(
"error opening file %s: %s", file, strerror(errno));
859 if (userid != 0 || groupid != 0) {
860 if (fchown(fileno(iface_ctx->
file_d), userid, groupid) == -1) {
861 SCLogWarning(
"Failed to change ownership of file %s: %s", file, strerror(errno));
882 if (iface_ctx->
file != NULL) {
884 iface_ctx->
file = NULL;
890 if (iface_ctx->
file_d != NULL) {
891 fclose(iface_ctx->
file_d);
909 static inline SCLogOPIfaceCtx *SCLogInitConsoleOPIface(
const char *log_format,
914 if (iface_ctx == NULL) {
915 FatalError(
"Fatal error encountered in SCLogInitConsoleOPIface. Exiting...");
922 const char *tmp_log_format = log_format;
926 printf(
"Overriding setting for \"console.format\" because of env "
927 "var SC_LOG_FORMAT=\"%s\".\n", s);
932 if (tmp_log_format != NULL &&
934 printf(
"Error allocating memory\n");
945 printf(
"Overriding setting for \"console.level\" because of env "
946 "var SC_LOG_LEVEL=\"%s\".\n", s);
954 if (isatty(fileno(stdout)) && isatty(fileno(stderr))) {
973 const char *log_format,
979 if ( iface_ctx == NULL) {
980 FatalError(
"Fatal error encountered in SCLogInitSyslogOPIface. Exiting...");
990 if (log_format != NULL &&
992 printf(
"Error allocating memory\n");
1012 while (iface_ctx != NULL) {
1015 if (iface_ctx->
file_d != NULL) {
1016 fclose(iface_ctx->
file_d);
1020 if (iface_ctx->
file != NULL)
1030 iface_ctx = iface_ctx->
next;
1048 const char *s = NULL;
1054 }
else if (sc_lid != NULL) {
1064 if (sc_lid != NULL) {
1065 printf(
"Warning: Invalid/No global_log_level assigned by user. Falling "
1066 "back on the default_log_level \"%s\"\n",
1083 static inline const char *SCLogGetDefaultLogFormat(
const SCLogLevel lvl)
1086 if (strstr(prog_ver,
"RELEASE") != NULL) {
1106 const char *format = NULL;
1110 if (format == NULL) {
1111 if (sc_lid != NULL) {
1118 format = SCLogGetDefaultLogFormat(sc_lc->
log_level);
1120 if (sc_lid != NULL) {
1121 printf(
"Warning: Invalid/No global_log_format supplied by user or format "
1122 "length exceeded limit of \"%d\" characters. Falling back on "
1130 printf(
"Error allocating memory\n");
1148 const char *s = NULL;
1150 if (sc_lid != NULL && sc_lid->
op_ifaces != NULL) {
1162 printf(
"Warning: Invalid output interface supplied by user. "
1163 "Falling back on default_output_interface \"%s\"\n",
1171 if (sc_lid != NULL) {
1172 printf(
"Warning: Output_interface not supplied by user. Falling "
1173 "back on default_output_interface \"%s\"\n",
1218 const char *filter = NULL;
1226 if (filter == NULL) {
1227 if (sc_lid != NULL) {
1232 if (filter != NULL && strcmp(filter,
"") != 0) {
1235 printf(
"pcre filter alloc failed\n");
1239 pcre2_compile((PCRE2_SPTR8)filter, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
1242 PCRE2_UCHAR errbuffer[256];
1243 pcre2_get_error_message(en, errbuffer,
sizeof(errbuffer));
1244 printf(
"pcre2 compile of \"%s\" failed at offset %d : %s\n", filter, (
int)eo,
1282 if (sc_lid != NULL) {
1283 SCLogFreeLogOPIfaceCtx(sc_lid->
op_ifaces);
1295 static inline void SCLogFreeLogConfig(
SCLogConfig *sc_lc)
1297 if (sc_lc != NULL) {
1310 SCLogFreeLogOPIfaceCtx(sc_lc->
op_ifaces);
1328 if (iface_ctx == NULL) {
1330 printf(
"Argument(s) to SCLogAppendOPIfaceCtx() NULL\n");
1336 while (temp != NULL) {
1344 prev->
next = iface_ctx;
1371 const char *iface_name,
const char *log_format,
int log_level,
const char *arg)
1375 if (log_level < SC_LOG_NONE || log_level >
SC_LOG_DEBUG) {
1376 printf(
"Warning: Supplied log_level_override for op_interface \"%s\" "
1377 "is invalid. Defaulting to not specifying an override\n",
1392 printf(
"Output Interface \"%s\" not supported by the logging module",
1415 #if defined (OS_WIN32)
1416 if (
SCMutexInit(&sc_log_stream_lock, NULL) != 0) {
1417 FatalError(
"Failed to initialize log mutex.");
1423 FatalError(
"Fatal error encountered in SCLogInitLogModule. Exiting...");
1426 SCLogSetLogLevel(sc_lid, sc_log_config);
1427 SCLogSetLogFormat(sc_lid, sc_log_config);
1428 SCLogSetOPIface(sc_lid, sc_log_config);
1429 SCLogSetOPFilter(sc_lid, sc_log_config);
1444 int have_logging = 0;
1455 if (outputs == NULL) {
1456 SCLogDebug(
"No logging.output configuration section found.");
1461 if (sc_lid == NULL) {
1462 SCLogDebug(
"Could not allocate memory for log init data");
1467 const char *default_log_level_s = NULL;
1468 if (
ConfGet(
"logging.default-log-level", &default_log_level_s) == 1) {
1471 if (default_log_level == -1) {
1472 SCLogError(
"Invalid default log level: %s", default_log_level_s);
1491 const char *level_s;
1504 if (type_s != NULL) {
1505 if (strcmp(type_s,
"regular") == 0)
1507 else if (strcmp(type_s,
"json") == 0) {
1515 if (level_s != NULL) {
1518 SCLogError(
"Invalid log level: %s", level_s);
1521 max_level =
MAX(max_level, level);
1525 level =
MAX(min_level, level);
1527 if (strcmp(output->
name,
"console") == 0) {
1528 op_iface_ctx = SCLogInitConsoleOPIface(format, level,
type);
1530 else if (strcmp(output->
name,
"file") == 0) {
1531 if (format == NULL) {
1536 if (filename == NULL) {
1537 FatalError(
"Logging to file requires a filename");
1541 path = SCLogGetLogFilename(filename);
1546 FatalError(
"failed to setup output to file");
1548 op_iface_ctx = SCLogInitFileOPIface(path, userid, groupid, format, level,
type);
1551 else if (strcmp(output->
name,
"syslog") == 0) {
1555 if (facility_s != NULL) {
1557 if (facility == -1) {
1559 "facility: \"%s\", now using \"%s\" as syslog "
1565 SCLogDebug(
"Initializing syslog logging with format \"%s\"", format);
1567 op_iface_ctx = SCLogInitSyslogOPIface(facility, format, level,
type);
1572 if (op_iface_ctx != NULL) {
1577 if (daemon && (have_logging == 0)) {
1578 SCLogWarning(
"no logging compatible with daemon mode selected,"
1579 " suricata won't be able to log. Please update "
1580 " 'logging.outputs' in the YAML.");
1604 static char *SCLogGetLogFilename(
const char *filearg)
1607 char *log_filename =
SCMalloc(PATH_MAX);
1608 if (
unlikely(log_filename == NULL))
1610 snprintf(log_filename, PATH_MAX,
"%s/%s", log_dir, filearg);
1611 return log_filename;
1619 SCLogFreeLogConfig(sc_log_config);
1625 sc_log_config = NULL;
1632 #if defined (OS_WIN32)
1650 static int SCLogTestInit01(
void)
1666 strcmp(SCLogGetDefaultLogFormat(sc_log_config->
log_level),
1681 !strcmp(
"%n- %l", sc_log_config->
log_format));
1692 static int SCLogTestInit02(
void)
1697 char *logfile = SCLogGetLogFilename(
"boo.txt");
1703 sc_iface_ctx = SCLogInitOPIfaceCtx(
"file",
"%m - %d",
SC_LOG_WARNING, logfile);
1705 sc_iface_ctx = SCLogInitOPIfaceCtx(
"console", NULL,
SC_LOG_ERROR,
1720 strcmp(SCLogGetDefaultLogFormat(sc_log_config->
log_level),
1729 SCLogFreeLogInitData(sc_lid);
1749 strcmp(
"kaboo", sc_log_config->
log_format) == 0);
1755 SCLogFreeLogInitData(sc_lid);
1762 static int SCLogTestInit03(
void)
1782 static int SCLogTestInit04(
void)
1810 static int SCLogTestInit05(
void)
1813 memset(
str,
'A',
sizeof(
str));