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");
672 while (op_iface_ctx != NULL) {
674 op_iface_ctx = op_iface_ctx->
next;
678 switch (op_iface_ctx->
iface) {
680 if (SCLogMessageGetBuffer(
ts, op_iface_ctx->
use_color, op_iface_ctx->
type, buffer,
684 log_level, file, line,
function, module, message) == 0) {
685 SCLogPrintToStream((log_level ==
SC_LOG_ERROR)? stderr: stdout, buffer);
689 if (SCLogMessageGetBuffer(
ts, 0, op_iface_ctx->
type, buffer,
sizeof(buffer),
692 log_level, file, line,
function, module, message) == 0) {
696 r = SCLogReopen(op_iface_ctx);
699 SCLogPrintToStream(op_iface_ctx->
file_d, buffer);
704 SCLogError(
"re-opening file \"%s\" failed: %s", op_iface_ctx->
file,
710 if (SCLogMessageGetBuffer(
ts, 0, op_iface_ctx->
type, buffer,
sizeof(buffer),
713 log_level, file, line,
function, module, message) == 0) {
714 SCLogPrintToSyslog(SCLogMapLogLevelToSyslogLevel(log_level), buffer);
720 op_iface_ctx = op_iface_ctx->
next;
725 void SCLog(
int x,
const char *file,
const char *func,
const int line,
const char *module,
726 const char *fmt, ...)
738 vsnprintf(
msg,
sizeof(
msg), fmt, ap);
744 void SCLogErr(
int x,
const char *file,
const char *func,
const int line,
const char *module,
745 const char *fmt, ...)
757 vsnprintf(
msg,
sizeof(
msg), fmt, ap);
794 FatalError(
"Fatal error encountered in SCLogAllocLogOPBuffer. Exiting...");
798 for (
int i = 0; i < sc_log_config->
op_ifaces_cnt; i++, op_iface_ctx = op_iface_ctx->
next) {
799 buffer[i].
log_format = op_iface_ctx->log_format;
800 buffer[i].
temp = buffer[i].
msg;
819 FatalError(
"Fatal error encountered in SCLogallocLogOPIfaceCtx. Exiting...");
836 static inline SCLogOPIfaceCtx *SCLogInitFileOPIface(
const char *file, uint32_t userid,
837 uint32_t groupid,
const char *log_format,
int log_level,
SCLogOPType type)
840 if (iface_ctx == NULL) {
841 FatalError(
"Fatal error encountered in SCLogInitFileOPIface. Exiting...");
851 if ( (iface_ctx->
file_d = fopen(file,
"a")) == NULL) {
852 SCLogWarning(
"error opening file %s: %s", file, strerror(errno));
857 if (userid != 0 || groupid != 0) {
858 if (fchown(fileno(iface_ctx->
file_d), userid, groupid) == -1) {
859 SCLogWarning(
"Failed to change ownership of file %s: %s", file, strerror(errno));
880 if (iface_ctx->
file != NULL) {
882 iface_ctx->
file = NULL;
888 if (iface_ctx->
file_d != NULL) {
889 fclose(iface_ctx->
file_d);
907 static inline SCLogOPIfaceCtx *SCLogInitConsoleOPIface(
const char *log_format,
912 if (iface_ctx == NULL) {
913 FatalError(
"Fatal error encountered in SCLogInitConsoleOPIface. Exiting...");
920 const char *tmp_log_format = log_format;
924 printf(
"Overriding setting for \"console.format\" because of env "
925 "var SC_LOG_FORMAT=\"%s\".\n", s);
930 if (tmp_log_format != NULL &&
932 printf(
"Error allocating memory\n");
943 printf(
"Overriding setting for \"console.level\" because of env "
944 "var SC_LOG_LEVEL=\"%s\".\n", s);
952 if (isatty(fileno(stdout)) && isatty(fileno(stderr))) {
971 const char *log_format,
977 if ( iface_ctx == NULL) {
978 FatalError(
"Fatal error encountered in SCLogInitSyslogOPIface. Exiting...");
988 if (log_format != NULL &&
990 printf(
"Error allocating memory\n");
1010 while (iface_ctx != NULL) {
1013 if (iface_ctx->
file_d != NULL) {
1014 fclose(iface_ctx->
file_d);
1018 if (iface_ctx->
file != NULL)
1028 iface_ctx = iface_ctx->
next;
1046 const char *s = NULL;
1052 }
else if (sc_lid != NULL) {
1062 if (sc_lid != NULL) {
1063 printf(
"Warning: Invalid/No global_log_level assigned by user. Falling "
1064 "back on the default_log_level \"%s\"\n",
1081 static inline const char *SCLogGetDefaultLogFormat(
const SCLogLevel lvl)
1084 if (strstr(prog_ver,
"RELEASE") != NULL) {
1104 const char *format = NULL;
1108 if (format == NULL) {
1109 if (sc_lid != NULL) {
1116 format = SCLogGetDefaultLogFormat(sc_lc->
log_level);
1118 if (sc_lid != NULL) {
1119 printf(
"Warning: Invalid/No global_log_format supplied by user or format "
1120 "length exceeded limit of \"%d\" characters. Falling back on "
1128 printf(
"Error allocating memory\n");
1146 const char *s = NULL;
1148 if (sc_lid != NULL && sc_lid->
op_ifaces != NULL) {
1160 printf(
"Warning: Invalid output interface supplied by user. "
1161 "Falling back on default_output_interface \"%s\"\n",
1169 if (sc_lid != NULL) {
1170 printf(
"Warning: Output_interface not supplied by user. Falling "
1171 "back on default_output_interface \"%s\"\n",
1216 const char *filter = NULL;
1224 if (filter == NULL) {
1225 if (sc_lid != NULL) {
1230 if (filter != NULL && strcmp(filter,
"") != 0) {
1233 printf(
"pcre filter alloc failed\n");
1237 pcre2_compile((PCRE2_SPTR8)filter, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
1240 PCRE2_UCHAR errbuffer[256];
1241 pcre2_get_error_message(en, errbuffer,
sizeof(errbuffer));
1242 printf(
"pcre2 compile of \"%s\" failed at offset %d : %s\n", filter, (
int)eo,
1280 if (sc_lid != NULL) {
1281 SCLogFreeLogOPIfaceCtx(sc_lid->
op_ifaces);
1293 static inline void SCLogFreeLogConfig(
SCLogConfig *sc_lc)
1295 if (sc_lc != NULL) {
1308 SCLogFreeLogOPIfaceCtx(sc_lc->
op_ifaces);
1326 if (iface_ctx == NULL) {
1328 printf(
"Argument(s) to SCLogAppendOPIfaceCtx() NULL\n");
1334 while (temp != NULL) {
1342 prev->
next = iface_ctx;
1369 const char *iface_name,
const char *log_format,
int log_level,
const char *arg)
1373 if (log_level < SC_LOG_NONE || log_level >
SC_LOG_DEBUG) {
1374 printf(
"Warning: Supplied log_level_override for op_interface \"%s\" "
1375 "is invalid. Defaulting to not specifying an override\n",
1390 printf(
"Output Interface \"%s\" not supported by the logging module",
1413 #if defined (OS_WIN32)
1414 if (
SCMutexInit(&sc_log_stream_lock, NULL) != 0) {
1415 FatalError(
"Failed to initialize log mutex.");
1421 FatalError(
"Fatal error encountered in SCLogInitLogModule. Exiting...");
1424 SCLogSetLogLevel(sc_lid, sc_log_config);
1425 SCLogSetLogFormat(sc_lid, sc_log_config);
1426 SCLogSetOPIface(sc_lid, sc_log_config);
1427 SCLogSetOPFilter(sc_lid, sc_log_config);
1442 int have_logging = 0;
1453 if (outputs == NULL) {
1454 SCLogDebug(
"No logging.output configuration section found.");
1459 if (sc_lid == NULL) {
1460 SCLogDebug(
"Could not allocate memory for log init data");
1465 const char *default_log_level_s = NULL;
1466 if (
ConfGet(
"logging.default-log-level", &default_log_level_s) == 1) {
1469 if (default_log_level == -1) {
1470 SCLogError(
"Invalid default log level: %s", default_log_level_s);
1489 const char *level_s;
1502 if (type_s != NULL) {
1503 if (strcmp(type_s,
"regular") == 0)
1505 else if (strcmp(type_s,
"json") == 0) {
1513 if (level_s != NULL) {
1516 SCLogError(
"Invalid log level: %s", level_s);
1519 max_level =
MAX(max_level, level);
1523 level =
MAX(min_level, level);
1525 if (strcmp(output->
name,
"console") == 0) {
1526 op_iface_ctx = SCLogInitConsoleOPIface(format, level,
type);
1528 else if (strcmp(output->
name,
"file") == 0) {
1529 if (format == NULL) {
1534 if (filename == NULL) {
1535 FatalError(
"Logging to file requires a filename");
1539 path = SCLogGetLogFilename(filename);
1544 FatalError(
"failed to setup output to file");
1546 op_iface_ctx = SCLogInitFileOPIface(path, userid, groupid, format, level,
type);
1549 else if (strcmp(output->
name,
"syslog") == 0) {
1553 if (facility_s != NULL) {
1555 if (facility == -1) {
1557 "facility: \"%s\", now using \"%s\" as syslog "
1563 SCLogDebug(
"Initializing syslog logging with format \"%s\"", format);
1565 op_iface_ctx = SCLogInitSyslogOPIface(facility, format, level,
type);
1570 if (op_iface_ctx != NULL) {
1575 if (daemon && (have_logging == 0)) {
1576 SCLogWarning(
"no logging compatible with daemon mode selected,"
1577 " suricata won't be able to log. Please update "
1578 " 'logging.outputs' in the YAML.");
1602 static char *SCLogGetLogFilename(
const char *filearg)
1605 char *log_filename =
SCMalloc(PATH_MAX);
1606 if (
unlikely(log_filename == NULL))
1608 snprintf(log_filename, PATH_MAX,
"%s/%s", log_dir, filearg);
1609 return log_filename;
1617 SCLogFreeLogConfig(sc_log_config);
1623 sc_log_config = NULL;
1630 #if defined (OS_WIN32)
1648 static int SCLogTestInit01(
void)
1664 strcmp(SCLogGetDefaultLogFormat(sc_log_config->
log_level),
1679 !strcmp(
"%n- %l", sc_log_config->
log_format));
1690 static int SCLogTestInit02(
void)
1695 char *logfile = SCLogGetLogFilename(
"boo.txt");
1701 sc_iface_ctx = SCLogInitOPIfaceCtx(
"file",
"%m - %d",
SC_LOG_WARNING, logfile);
1703 sc_iface_ctx = SCLogInitOPIfaceCtx(
"console", NULL,
SC_LOG_ERROR,
1718 strcmp(SCLogGetDefaultLogFormat(sc_log_config->
log_level),
1727 SCLogFreeLogInitData(sc_lid);
1747 strcmp(
"kaboo", sc_log_config->
log_format) == 0);
1753 SCLogFreeLogInitData(sc_lid);
1760 static int SCLogTestInit03(
void)
1780 static int SCLogTestInit04(
void)
1808 static int SCLogTestInit05(
void)
1811 memset(
str,
'A',
sizeof(
str));