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)
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 JsonBuilder *js = jb_new_object();
208 jb_set_string(js,
"timestamp", timebuf);
212 jb_set_string(js,
"log_level", s);
218 jb_open_object(js,
"engine");
221 jb_set_string(js,
"message", message);
231 dn_name = SCTransformModule(module, &dn_len);
232 jb_set_string(js,
"module", dn_name);
237 jb_set_string(js,
"function",
function);
240 jb_set_string(js,
"file", file);
243 jb_set_uint(js,
"line", line);
248 memcpy(buffer, jb_ptr(js),
MIN(buffer_size, jb_len(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 = strlen(module_name) - 3;
290 return module_name + 3;
291 }
else if (strncmp(
"util-", module_name, 5) == 0) {
292 *dn_len = strlen(module_name) - 5;
293 return module_name + 5;
294 }
else if (strncmp(
"source-pcap-file", module_name, 16) == 0) {
295 *dn_len = strlen(
"pcap");
297 }
else if (strncmp(
"source-", module_name, 7) == 0) {
298 *dn_len = strlen(module_name) - 7;
299 return module_name + 7;
300 }
else if (strncmp(
"runmode-", module_name, 8) == 0) {
301 *dn_len = strlen(module_name) - 8;
302 return module_name + 8;
303 }
else if (strncmp(
"app-layer-", module_name, 10) == 0) {
304 *dn_len = strlen(module_name);
306 }
else if (strncmp(
"detect-engine", module_name, 13) == 0) {
307 *dn_len = 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 = strlen(module_name);
324 *dn_len = 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;
723 void 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);
742 void 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) {
797 buffer[i].
log_format = op_iface_ctx->log_format;
798 buffer[i].
temp = buffer[i].
msg;
817 FatalError(
"Fatal error encountered in SCLogallocLogOPIfaceCtx. Exiting...");
834 static 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);
905 static 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",
1075 static 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);
1280 static 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 (
ConfGet(
"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);
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) {
1535 if (facility_s != NULL) {
1537 if (facility == -1) {
1539 "facility: \"%s\", now using \"%s\" as syslog "
1545 SCLogDebug(
"Initializing syslog logging with format \"%s\"", format);
1547 op_iface_ctx = SCLogInitSyslogOPIface(facility, format, level,
type);
1552 if (op_iface_ctx != NULL) {
1557 if (daemon && (have_logging == 0)) {
1558 SCLogWarning(
"no logging compatible with daemon mode selected,"
1559 " suricata won't be able to log. Please update "
1560 " 'logging.outputs' in the YAML.");
1584 static char *SCLogGetLogFilename(
const char *filearg)
1587 char *log_filename =
SCMalloc(PATH_MAX);
1588 if (
unlikely(log_filename == NULL))
1590 snprintf(log_filename, PATH_MAX,
"%s/%s", log_dir, filearg);
1591 return log_filename;
1599 SCLogFreeLogConfig(sc_log_config);
1605 sc_log_config = NULL;
1612 #if defined (OS_WIN32)
1628 static int SCLogTestInit01(
void)
1644 strcmp(SCLogGetDefaultLogFormat(sc_log_config->
log_level),
1659 !strcmp(
"%n- %l", sc_log_config->
log_format));
1670 static int SCLogTestInit02(
void)
1675 char *logfile = SCLogGetLogFilename(
"boo.txt");
1681 sc_iface_ctx = SCLogInitOPIfaceCtx(
"file",
"%m - %d",
SC_LOG_WARNING, logfile);
1683 sc_iface_ctx = SCLogInitOPIfaceCtx(
"console", NULL,
SC_LOG_ERROR,
1698 strcmp(SCLogGetDefaultLogFormat(sc_log_config->
log_level),
1707 SCLogFreeLogInitData(sc_lid);
1727 strcmp(
"kaboo", sc_log_config->
log_format) == 0);
1733 SCLogFreeLogInitData(sc_lid);
1740 static int SCLogTestInit03(
void)
1760 static int SCLogTestInit04(
void)
1788 static int SCLogTestInit05(
void)
1791 memset(
str,
'A',
sizeof(
str));