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)
188 static inline void SCLogPrintToSyslog(
int syslog_log_level,
const char *msg)
193 syslog(syslog_log_level,
"%s", msg);
198 static 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)));
258 static const int transform_max_segs = 2;
277 static 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;
376 char local_format[strlen(log_format) + add_M * 2 + 1];
377 strlcpy(local_format, log_format,
sizeof(local_format));
379 strlcat(local_format,
"%M",
sizeof(local_format));
380 char *temp_fmt = local_format;
381 char *substr = temp_fmt;
388 switch(temp_fmt[1]) {
395 "%s%s%04d-%02d-%02d %02d:%02d:%02d%s", substr, green, tms->tm_year + 1900,
396 tms->tm_mon + 1, tms->tm_mday, tms->tm_hour, tms->tm_min, tms->tm_sec,
412 "%s%s%d/%d/%04d -- %02d:%02d:%02d%s",
413 substr, green, tms->tm_mday, tms->tm_mon + 1,
414 tms->tm_year + 1900, tms->tm_hour, tms->tm_min,
427 "%s%s%u%s", substr, yellow, getpid(), reset);
467 "%s%s%s%s", substr, redb, s, reset);
470 "%s%s%s%s", substr, red, s, reset);
473 "%s%s%s%s", substr, yellowb, s, reset);
476 substr, yellow, s, reset);
495 substr, redb, s, reset);
498 substr, red, s, reset);
501 substr, yellowb, s, reset);
504 "%s%s%s%s", substr, yellow, s, reset);
507 "%s%s", substr,
"INVALID");
520 "%s%s%s%s", substr, blue, file, reset);
532 "%s%s%u%s", substr, green, line, reset);
546 const char *dn_name =
"unknown";
548 dn_name = SCTransformModule(module, &dn_len);
552 green, dn_name, reset);
564 "%s%s%s%s", substr, green,
function, reset);
613 if (pcre2_match(sc_log_config->
op_filter_regex, (PCRE2_SPTR8)buffer, strlen(buffer), 0, 0,
628 if (op_iface_ctx->
file == NULL) {
632 if (op_iface_ctx->
file_d != NULL) {
633 fclose(op_iface_ctx->
file_d);
635 op_iface_ctx->
file_d = fopen(op_iface_ctx->
file,
"a");
636 if (op_iface_ctx->
file_d == NULL) {
654 const char *
function,
const char *module,
const char *message)
660 printf(
"Logging module not initialized. Call SCLogInitLogModule() "
661 "first before using the debug API\n");
667 gettimeofday(&tval, NULL);
671 while (op_iface_ctx != NULL) {
673 op_iface_ctx = op_iface_ctx->
next;
677 switch (op_iface_ctx->
iface) {
679 if (SCLogMessageGetBuffer(
ts, op_iface_ctx->
use_color, op_iface_ctx->
type, buffer,
683 log_level, file, line,
function, module, message) == 0) {
684 SCLogPrintToStream((log_level ==
SC_LOG_ERROR)? stderr: stdout, buffer);
688 if (SCLogMessageGetBuffer(
ts, 0, op_iface_ctx->
type, buffer,
sizeof(buffer),
691 log_level, file, line,
function, module, message) == 0) {
695 r = SCLogReopen(op_iface_ctx);
698 SCLogPrintToStream(op_iface_ctx->
file_d, buffer);
703 SCLogError(
"re-opening file \"%s\" failed: %s", op_iface_ctx->
file,
709 if (SCLogMessageGetBuffer(
ts, 0, op_iface_ctx->
type, buffer,
sizeof(buffer),
712 log_level, file, line,
function, module, message) == 0) {
713 SCLogPrintToSyslog(SCLogMapLogLevelToSyslogLevel(log_level), buffer);
719 op_iface_ctx = op_iface_ctx->
next;
724 void SCLog(
int x,
const char *file,
const char *func,
const int line,
const char *module,
725 const char *fmt, ...)
737 vsnprintf(msg,
sizeof(msg), fmt, ap);
743 void SCLogErr(
int x,
const char *file,
const char *func,
const int line,
const char *module,
744 const char *fmt, ...)
756 vsnprintf(msg,
sizeof(msg), fmt, ap);
793 FatalError(
"Fatal error encountered in SCLogAllocLogOPBuffer. Exiting...");
797 for (
int i = 0; i < sc_log_config->
op_ifaces_cnt; i++, op_iface_ctx = op_iface_ctx->
next) {
798 buffer[i].
log_format = op_iface_ctx->log_format;
799 buffer[i].
temp = buffer[i].
msg;
818 FatalError(
"Fatal error encountered in SCLogallocLogOPIfaceCtx. Exiting...");
835 static inline SCLogOPIfaceCtx *SCLogInitFileOPIface(
const char *file, uint32_t userid,
836 uint32_t groupid,
const char *log_format,
int log_level,
SCLogOPType type)
839 if (iface_ctx == NULL) {
840 FatalError(
"Fatal error encountered in SCLogInitFileOPIface. Exiting...");
850 if ( (iface_ctx->
file_d = fopen(file,
"a")) == NULL) {
851 SCLogWarning(
"error opening file %s: %s", file, strerror(errno));
856 if (userid != 0 || groupid != 0) {
857 if (fchown(fileno(iface_ctx->
file_d), userid, groupid) == -1) {
858 SCLogWarning(
"Failed to change ownership of file %s: %s", file, strerror(errno));
879 if (iface_ctx->
file != NULL) {
881 iface_ctx->
file = NULL;
887 if (iface_ctx->
file_d != NULL) {
888 fclose(iface_ctx->
file_d);
906 static inline SCLogOPIfaceCtx *SCLogInitConsoleOPIface(
const char *log_format,
911 if (iface_ctx == NULL) {
912 FatalError(
"Fatal error encountered in SCLogInitConsoleOPIface. Exiting...");
919 const char *tmp_log_format = log_format;
923 printf(
"Overriding setting for \"console.format\" because of env "
924 "var SC_LOG_FORMAT=\"%s\".\n", s);
929 if (tmp_log_format != NULL &&
931 printf(
"Error allocating memory\n");
942 printf(
"Overriding setting for \"console.level\" because of env "
943 "var SC_LOG_LEVEL=\"%s\".\n", s);
951 if (isatty(fileno(stdout)) && isatty(fileno(stderr))) {
970 const char *log_format,
976 if ( iface_ctx == NULL) {
977 FatalError(
"Fatal error encountered in SCLogInitSyslogOPIface. Exiting...");
987 if (log_format != NULL &&
989 printf(
"Error allocating memory\n");
1009 while (iface_ctx != NULL) {
1012 if (iface_ctx->
file_d != NULL) {
1013 fclose(iface_ctx->
file_d);
1017 if (iface_ctx->
file != NULL)
1027 iface_ctx = iface_ctx->
next;
1043 const char *s = NULL;
1049 }
else if (sc_lid != NULL) {
1059 if (sc_lid != NULL) {
1060 printf(
"Warning: Invalid/No global_log_level assigned by user. Falling "
1061 "back on the default_log_level \"%s\"\n",
1076 static inline const char *SCLogGetDefaultLogFormat(
const SCLogLevel lvl)
1079 if (strstr(prog_ver,
"RELEASE") != NULL) {
1099 const char *format = NULL;
1103 if (format == NULL) {
1104 if (sc_lid != NULL) {
1111 format = SCLogGetDefaultLogFormat(sc_lc->
log_level);
1113 if (sc_lid != NULL) {
1114 printf(
"Warning: Invalid/No global_log_format supplied by user or format "
1115 "length exceeded limit of \"%d\" characters. Falling back on "
1123 printf(
"Error allocating memory\n");
1139 const char *s = NULL;
1141 if (sc_lid != NULL && sc_lid->
op_ifaces != NULL) {
1153 printf(
"Warning: Invalid output interface supplied by user. "
1154 "Falling back on default_output_interface \"%s\"\n",
1162 if (sc_lid != NULL) {
1163 printf(
"Warning: Output_interface not supplied by user. Falling "
1164 "back on default_output_interface \"%s\"\n",
1208 const char *filter = NULL;
1216 if (filter == NULL) {
1217 if (sc_lid != NULL) {
1222 if (filter != NULL && strcmp(filter,
"") != 0) {
1225 printf(
"pcre filter alloc failed\n");
1229 pcre2_compile((PCRE2_SPTR8)filter, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
1232 PCRE2_UCHAR errbuffer[256];
1233 pcre2_get_error_message(en, errbuffer,
sizeof(errbuffer));
1234 printf(
"pcre2 compile of \"%s\" failed at offset %d : %s\n", filter, (
int)eo,
1270 if (sc_lid != NULL) {
1271 SCLogFreeLogOPIfaceCtx(sc_lid->
op_ifaces);
1281 static inline void SCLogFreeLogConfig(
SCLogConfig *sc_lc)
1283 if (sc_lc != NULL) {
1296 SCLogFreeLogOPIfaceCtx(sc_lc->
op_ifaces);
1312 if (iface_ctx == NULL) {
1314 printf(
"Argument(s) to SCLogAppendOPIfaceCtx() NULL\n");
1320 while (temp != NULL) {
1328 prev->
next = iface_ctx;
1353 const char *iface_name,
const char *log_format,
int log_level,
const char *arg)
1357 if (log_level < SC_LOG_NONE || log_level >
SC_LOG_DEBUG) {
1358 printf(
"Warning: Supplied log_level_override for op_interface \"%s\" "
1359 "is invalid. Defaulting to not specifying an override\n",
1374 printf(
"Output Interface \"%s\" not supported by the logging module",
1397 #if defined (OS_WIN32)
1398 if (
SCMutexInit(&sc_log_stream_lock, NULL) != 0) {
1399 FatalError(
"Failed to initialize log mutex.");
1405 FatalError(
"Fatal error encountered in SCLogInitLogModule. Exiting...");
1408 SCLogSetLogLevel(sc_lid, sc_log_config);
1409 SCLogSetLogFormat(sc_lid, sc_log_config);
1410 SCLogSetOPIface(sc_lid, sc_log_config);
1411 SCLogSetOPFilter(sc_lid, sc_log_config);
1425 int have_logging = 0;
1436 if (outputs == NULL) {
1437 SCLogDebug(
"No logging.output configuration section found.");
1442 if (sc_lid == NULL) {
1443 SCLogDebug(
"Could not allocate memory for log init data");
1448 const char *default_log_level_s = NULL;
1449 if (
SCConfGet(
"logging.default-log-level", &default_log_level_s) == 1) {
1452 if (default_log_level == -1) {
1453 SCLogError(
"Invalid default log level: %s", default_log_level_s);
1471 const char *level_s;
1484 if (type_s != NULL) {
1485 if (strcmp(type_s,
"regular") == 0)
1487 else if (strcmp(type_s,
"json") == 0) {
1495 if (level_s != NULL) {
1498 SCLogError(
"Invalid log level: %s", level_s);
1501 max_level =
MAX(max_level, level);
1505 level =
MAX(min_level, level);
1507 if (strcmp(output->
name,
"console") == 0) {
1508 op_iface_ctx = SCLogInitConsoleOPIface(format, level,
type);
1510 else if (strcmp(output->
name,
"file") == 0) {
1511 if (format == NULL) {
1516 if (filename == NULL) {
1517 FatalError(
"Logging to file requires a filename");
1521 path = SCLogGetLogFilename(filename);
1526 FatalError(
"failed to setup output to file");
1528 op_iface_ctx = SCLogInitFileOPIface(path, userid, groupid, format, level,
type);
1531 else if (strcmp(output->
name,
"syslog") == 0) {
1534 if (facility_s != NULL) {
1536 if (facility == -1) {
1538 "facility: \"%s\", now using \"%s\" as syslog "
1544 SCLogDebug(
"Initializing syslog logging with format \"%s\"", format);
1546 op_iface_ctx = SCLogInitSyslogOPIface(facility, format, level,
type);
1551 if (op_iface_ctx != NULL) {
1556 if (daemon && (have_logging == 0)) {
1557 SCLogWarning(
"no logging compatible with daemon mode selected,"
1558 " suricata won't be able to log. Please update "
1559 " 'logging.outputs' in the YAML.");
1582 static char *SCLogGetLogFilename(
const char *filearg)
1585 char *log_filename =
SCMalloc(PATH_MAX);
1586 if (
unlikely(log_filename == NULL))
1588 snprintf(log_filename, PATH_MAX,
"%s/%s", log_dir, filearg);
1589 return log_filename;
1597 SCLogFreeLogConfig(sc_log_config);
1603 sc_log_config = NULL;
1610 #if defined (OS_WIN32)
1631 static int SCLogTestInit01(
void)
1647 strcmp(SCLogGetDefaultLogFormat(sc_log_config->
log_level),
1662 !strcmp(
"%n- %l", sc_log_config->
log_format));
1673 static int SCLogTestInit02(
void)
1678 char *logfile = SCLogGetLogFilename(
"boo.txt");
1684 sc_iface_ctx = SCLogInitOPIfaceCtx(
"file",
"%m - %d",
SC_LOG_WARNING, logfile);
1686 sc_iface_ctx = SCLogInitOPIfaceCtx(
"console", NULL,
SC_LOG_ERROR,
1701 strcmp(SCLogGetDefaultLogFormat(sc_log_config->
log_level),
1710 SCLogFreeLogInitData(sc_lid);
1730 strcmp(
"kaboo", sc_log_config->
log_format) == 0);
1736 SCLogFreeLogInitData(sc_lid);
1743 static int SCLogTestInit03(
void)
1763 static int SCLogTestInit04(
void)
1791 static int SCLogTestInit05(
void)
1794 memset(
str,
'A',
sizeof(
str));
1795 str[
sizeof(
str) - 1] =
'\0';