79 #if defined (OS_WIN32)
83 static SCMutex sc_log_stream_lock;
89 static const char *SCTransformModule(
const char *module_name,
int *dn_len);
99 static char *SCLogGetLogFilename(
const char *);
124 static inline int SCLogMapLogLevelToSyslogLevel(
int log_level)
126 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)
191 static inline void SCLogPrintToSyslog(
int syslog_log_level,
const char *msg)
196 syslog(syslog_log_level,
"%s", msg);
201 static int SCLogMessageJSON(
SCTime_t tval,
char *buffer,
size_t buffer_size,
SCLogLevel log_level,
202 const char *file,
unsigned line,
const char *
function,
const char *module,
211 SCJbSetString(js,
"timestamp", timebuf);
215 SCJbSetString(js,
"log_level", s);
221 SCJbOpenObject(js,
"engine");
224 SCJbSetString(js,
"message", message);
234 dn_name = SCTransformModule(module, &dn_len);
235 SCJbSetString(js,
"module", dn_name);
240 SCJbSetString(js,
"function",
function);
243 SCJbSetString(js,
"file", file);
246 SCJbSetUint(js,
"line", line);
253 const size_t len =
MIN(buffer_size - 1, (
size_t)SCJbLen(js));
254 memcpy(buffer, SCJbPtr(js),
len);
265 static const int transform_max_segs = 2;
284 static const char *SCTransformModule(
const char *module_name,
int *dn_len)
295 if (strncmp(
"tm-", module_name, 3) == 0) {
296 *dn_len = (int)strlen(module_name) - 3;
297 return module_name + 3;
298 }
else if (strncmp(
"util-", module_name, 5) == 0) {
299 *dn_len = (int)strlen(module_name) - 5;
300 return module_name + 5;
301 }
else if (strncmp(
"source-pcap-file", module_name, 16) == 0) {
302 *dn_len = (int)strlen(
"pcap");
304 }
else if (strncmp(
"source-", module_name, 7) == 0) {
305 *dn_len = (int)strlen(module_name) - 7;
306 return module_name + 7;
307 }
else if (strncmp(
"runmode-", module_name, 8) == 0) {
308 *dn_len = (int)strlen(module_name) - 8;
309 return module_name + 8;
310 }
else if (strncmp(
"app-layer-", module_name, 10) == 0) {
311 *dn_len = (int)strlen(module_name);
313 }
else if (strncmp(
"detect-engine", module_name, 13) == 0) {
314 *dn_len = (int)strlen(
"detect");
321 char *w = (
char *)module_name;
322 while (w && (w = strchr(w,
'-')) != NULL && seg_cnt < transform_max_segs) {
328 if (seg_cnt < transform_max_segs)
329 *dn_len = (int)strlen(module_name);
331 *dn_len = (int)(last - module_name);
348 size_t buffer_size,
const char *log_format,
const SCLogLevel log_level,
const char *file,
349 const unsigned int line,
const char *
function,
const char *module,
const char *message)
352 return SCLogMessageJSON(
353 tval, buffer, buffer_size, log_level, file, line,
function, module, message);
356 const char *s = NULL;
357 struct tm *tms = NULL;
359 const char *redb =
"";
360 const char *red =
"";
361 const char *yellowb =
"";
362 const char *yellow =
"";
363 const char *green =
"";
364 const char *blue =
"";
365 const char *reset =
"";
369 yellowb =
"\x1b[1;33m";
381 const int add_M = strstr(log_format,
"%M") == NULL;
383 char local_format[strlen(log_format) + add_M * 2 + 1];
384 strlcpy(local_format, log_format,
sizeof(local_format));
386 strlcat(local_format,
"%M",
sizeof(local_format));
387 char *temp_fmt = local_format;
388 char *substr = temp_fmt;
395 switch(temp_fmt[1]) {
402 "%s%s%04d-%02d-%02d %02d:%02d:%02d%s", substr, green, tms->tm_year + 1900,
403 tms->tm_mon + 1, tms->tm_mday, tms->tm_hour, tms->tm_min, tms->tm_sec,
419 "%s%s%d/%d/%04d -- %02d:%02d:%02d%s",
420 substr, green, tms->tm_mday, tms->tm_mon + 1,
421 tms->tm_year + 1900, tms->tm_hour, tms->tm_min,
434 "%s%s%u%s", substr, yellow, getpid(), reset);
474 "%s%s%s%s", substr, redb, s, reset);
477 "%s%s%s%s", substr, red, s, reset);
480 "%s%s%s%s", substr, yellowb, s, reset);
483 substr, yellow, s, reset);
502 substr, redb, s, reset);
505 substr, red, s, reset);
508 substr, yellowb, s, reset);
511 "%s%s%s%s", substr, yellow, s, reset);
514 "%s%s", substr,
"INVALID");
527 "%s%s%s%s", substr, blue, file, reset);
539 "%s%s%u%s", substr, green, line, reset);
553 const char *dn_name =
"unknown";
555 dn_name = SCTransformModule(module, &dn_len);
559 green, dn_name, reset);
571 "%s%s%s%s", substr, green,
function, reset);
620 if (pcre2_match(sc_log_config->
op_filter_regex, (PCRE2_SPTR8)buffer, strlen(buffer), 0, 0,
635 if (op_iface_ctx->
file == NULL) {
639 if (op_iface_ctx->
file_d != NULL) {
640 fclose(op_iface_ctx->
file_d);
643 if (op_iface_ctx->
file_d == NULL) {
661 const char *
function,
const char *module,
const char *message)
667 printf(
"Logging module not initialized. Call SCLogInitLogModule() "
668 "first before using the debug API\n");
674 gettimeofday(&tval, NULL);
678 while (op_iface_ctx != NULL) {
680 op_iface_ctx = op_iface_ctx->
next;
684 switch (op_iface_ctx->
iface) {
686 if (SCLogMessageGetBuffer(
ts, op_iface_ctx->
use_color, op_iface_ctx->
type, buffer,
690 log_level, file, line,
function, module, message) == 0) {
691 SCLogPrintToStream((log_level ==
SC_LOG_ERROR)? stderr: stdout, buffer);
695 if (SCLogMessageGetBuffer(
ts, 0, op_iface_ctx->
type, buffer,
sizeof(buffer),
698 log_level, file, line,
function, module, message) == 0) {
702 r = SCLogReopen(op_iface_ctx);
705 SCLogPrintToStream(op_iface_ctx->
file_d, buffer);
710 SCLogError(
"re-opening file \"%s\" failed: %s", op_iface_ctx->
file,
716 if (SCLogMessageGetBuffer(
ts, 0, op_iface_ctx->
type, buffer,
sizeof(buffer),
719 log_level, file, line,
function, module, message) == 0) {
720 SCLogPrintToSyslog(SCLogMapLogLevelToSyslogLevel(log_level), buffer);
726 op_iface_ctx = op_iface_ctx->
next;
731 void SCLog(
int x,
const char *file,
const char *func,
const int line,
const char *module,
732 const char *fmt, ...)
744 vsnprintf(msg,
sizeof(msg), fmt, ap);
750 void SCLogErr(
int x,
const char *file,
const char *func,
const int line,
const char *module,
751 const char *fmt, ...)
763 vsnprintf(msg,
sizeof(msg), fmt, ap);
800 FatalError(
"Fatal error encountered in SCLogAllocLogOPBuffer. Exiting...");
804 for (
int i = 0; i < sc_log_config->
op_ifaces_cnt; i++, op_iface_ctx = op_iface_ctx->
next) {
805 buffer[i].
log_format = op_iface_ctx->log_format;
806 buffer[i].
temp = buffer[i].
msg;
825 FatalError(
"Fatal error encountered in SCLogallocLogOPIfaceCtx. Exiting...");
842 static inline SCLogOPIfaceCtx *SCLogInitFileOPIface(
const char *file, uint32_t userid,
843 uint32_t groupid,
const char *log_format,
int log_level,
SCLogOPType type)
846 if (iface_ctx == NULL) {
847 FatalError(
"Fatal error encountered in SCLogInitFileOPIface. Exiting...");
858 if (iface_ctx->
file_d == NULL) {
859 SCLogWarning(
"error opening file %s: %s", file, strerror(errno));
864 if (userid != 0 || groupid != 0) {
865 if (fchown(fileno(iface_ctx->
file_d), userid, groupid) == -1) {
866 SCLogWarning(
"Failed to change ownership of file %s: %s", file, strerror(errno));
887 if (iface_ctx->
file != NULL) {
889 iface_ctx->
file = NULL;
895 if (iface_ctx->
file_d != NULL) {
896 fclose(iface_ctx->
file_d);
914 static inline SCLogOPIfaceCtx *SCLogInitConsoleOPIface(
const char *log_format,
919 if (iface_ctx == NULL) {
920 FatalError(
"Fatal error encountered in SCLogInitConsoleOPIface. Exiting...");
927 const char *tmp_log_format = log_format;
931 printf(
"Overriding setting for \"console.format\" because of env "
932 "var SC_LOG_FORMAT=\"%s\".\n", s);
937 if (tmp_log_format != NULL &&
939 printf(
"Error allocating memory\n");
950 printf(
"Overriding setting for \"console.level\" because of env "
951 "var SC_LOG_LEVEL=\"%s\".\n", s);
959 if (isatty(fileno(stdout)) && isatty(fileno(stderr))) {
978 const char *log_format,
984 if ( iface_ctx == NULL) {
985 FatalError(
"Fatal error encountered in SCLogInitSyslogOPIface. Exiting...");
995 if (log_format != NULL &&
997 printf(
"Error allocating memory\n");
1017 while (iface_ctx != NULL) {
1020 if (iface_ctx->
file_d != NULL) {
1021 fclose(iface_ctx->
file_d);
1025 if (iface_ctx->
file != NULL)
1035 iface_ctx = iface_ctx->
next;
1051 const char *s = NULL;
1057 }
else if (sc_lid != NULL) {
1067 if (sc_lid != NULL) {
1068 printf(
"Warning: Invalid/No global_log_level assigned by user. Falling "
1069 "back on the default_log_level \"%s\"\n",
1089 static inline const char *SCLogGetDefaultLogFormat(
const SCLogLevel lvl)
1092 if (strstr(prog_ver,
"RELEASE") != NULL) {
1112 const char *format = NULL;
1116 if (format == NULL) {
1117 if (sc_lid != NULL) {
1124 format = SCLogGetDefaultLogFormat(sc_lc->
log_level);
1126 if (sc_lid != NULL) {
1127 printf(
"Warning: Invalid/No global_log_format supplied by user or format "
1128 "length exceeded limit of \"%d\" characters. Falling back on "
1136 printf(
"Error allocating memory\n");
1152 const char *s = NULL;
1154 if (sc_lid != NULL && sc_lid->
op_ifaces != NULL) {
1166 printf(
"Warning: Invalid output interface supplied by user. "
1167 "Falling back on default_output_interface \"%s\"\n",
1175 if (sc_lid != NULL) {
1176 printf(
"Warning: Output_interface not supplied by user. Falling "
1177 "back on default_output_interface \"%s\"\n",
1221 const char *filter = NULL;
1229 if (filter == NULL) {
1230 if (sc_lid != NULL) {
1235 if (filter != NULL && strcmp(filter,
"") != 0) {
1238 printf(
"pcre filter alloc failed\n");
1242 pcre2_compile((PCRE2_SPTR8)filter, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
1245 PCRE2_UCHAR errbuffer[256];
1246 pcre2_get_error_message(en, errbuffer,
sizeof(errbuffer));
1247 printf(
"pcre2 compile of \"%s\" failed at offset %d : %s\n", filter, (
int)eo,
1283 if (sc_lid != NULL) {
1284 SCLogFreeLogOPIfaceCtx(sc_lid->
op_ifaces);
1294 static inline void SCLogFreeLogConfig(
SCLogConfig *sc_lc)
1296 if (sc_lc != NULL) {
1309 SCLogFreeLogOPIfaceCtx(sc_lc->
op_ifaces);
1325 if (iface_ctx == NULL) {
1327 printf(
"Argument(s) to SCLogAppendOPIfaceCtx() NULL\n");
1333 while (temp != NULL) {
1341 prev->
next = iface_ctx;
1366 const char *iface_name,
const char *log_format,
int log_level,
const char *arg)
1370 if (log_level < SC_LOG_NONE || log_level >
SC_LOG_DEBUG) {
1371 printf(
"Warning: Supplied log_level_override for op_interface \"%s\" "
1372 "is invalid. Defaulting to not specifying an override\n",
1387 printf(
"Output Interface \"%s\" not supported by the logging module",
1410 #if defined (OS_WIN32)
1411 if (
SCMutexInit(&sc_log_stream_lock, NULL) != 0) {
1412 FatalError(
"Failed to initialize log mutex.");
1418 FatalError(
"Fatal error encountered in SCLogInitLogModule. Exiting...");
1421 SCLogSetLogLevel(sc_lid, sc_log_config);
1422 SCLogSetLogFormat(sc_lid, sc_log_config);
1423 SCLogSetOPIface(sc_lid, sc_log_config);
1424 SCLogSetOPFilter(sc_lid, sc_log_config);
1438 int have_logging = 0;
1449 if (outputs == NULL) {
1450 SCLogDebug(
"No logging.output configuration section found.");
1455 if (sc_lid == NULL) {
1456 SCLogDebug(
"Could not allocate memory for log init data");
1461 const char *default_log_level_s = NULL;
1462 if (
SCConfGetNonNull(
"logging.default-log-level", &default_log_level_s) == 1) {
1465 if (default_log_level == -1) {
1466 SCLogError(
"Invalid default log level: %s", default_log_level_s);
1484 const char *level_s;
1497 if (type_s != NULL) {
1498 if (strcmp(type_s,
"regular") == 0)
1500 else if (strcmp(type_s,
"json") == 0) {
1508 if (level_s != NULL) {
1511 SCLogError(
"Invalid log level: %s", level_s);
1514 max_level =
MAX(max_level, level);
1518 level =
MAX(min_level, level);
1520 if (strcmp(output->
name,
"console") == 0) {
1521 op_iface_ctx = SCLogInitConsoleOPIface(format, level,
type);
1523 else if (strcmp(output->
name,
"file") == 0) {
1524 if (format == NULL) {
1529 if (filename == NULL) {
1530 FatalError(
"Logging to file requires a filename");
1534 path = SCLogGetLogFilename(filename);
1539 FatalError(
"failed to setup output to file");
1541 op_iface_ctx = SCLogInitFileOPIface(path, userid, groupid, format, level,
type);
1544 else if (strcmp(output->
name,
"syslog") == 0) {
1547 if (facility_s != NULL) {
1549 if (facility == -1) {
1551 "facility: \"%s\", now using \"%s\" as syslog "
1557 SCLogDebug(
"Initializing syslog logging with format \"%s\"", format);
1559 op_iface_ctx = SCLogInitSyslogOPIface(facility, format, level,
type);
1564 if (op_iface_ctx != NULL) {
1569 if (daemon && (have_logging == 0)) {
1570 SCLogWarning(
"no logging compatible with daemon mode selected,"
1571 " suricata won't be able to log. Please update "
1572 " 'logging.outputs' in the YAML.");
1595 static char *SCLogGetLogFilename(
const char *filearg)
1598 char *log_filename =
SCMalloc(PATH_MAX);
1599 if (
unlikely(log_filename == NULL))
1601 snprintf(log_filename, PATH_MAX,
"%s/%s", log_dir, filearg);
1602 return log_filename;
1610 SCLogFreeLogConfig(sc_log_config);
1616 sc_log_config = NULL;
1623 #if defined (OS_WIN32)
1644 static int SCLogTestInit01(
void)
1660 strcmp(SCLogGetDefaultLogFormat(sc_log_config->
log_level),
1675 !strcmp(
"%n- %l", sc_log_config->
log_format));
1686 static int SCLogTestInit02(
void)
1691 char *logfile = SCLogGetLogFilename(
"boo.txt");
1697 sc_iface_ctx = SCLogInitOPIfaceCtx(
"file",
"%m - %d",
SC_LOG_WARNING, logfile);
1699 sc_iface_ctx = SCLogInitOPIfaceCtx(
"console", NULL,
SC_LOG_ERROR,
1714 strcmp(SCLogGetDefaultLogFormat(sc_log_config->
log_level),
1723 SCLogFreeLogInitData(sc_lid);
1743 strcmp(
"kaboo", sc_log_config->
log_format) == 0);
1749 SCLogFreeLogInitData(sc_lid);
1756 static int SCLogTestInit03(
void)
1776 static int SCLogTestInit04(
void)
1804 static int SCLogTestInit05(
void)
1807 memset(
str,
'A',
sizeof(
str));
1808 str[
sizeof(
str) - 1] =
'\0';