suricata
util-debug.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2021 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Anoop Saldanha <anoopsaldanha@gmail.com>
22  *
23  * Debug utility functions
24  */
25 
26 #include "suricata-common.h"
27 #include "util-debug.h"
28 
29 #include "output.h"
30 
31 #include "suricata.h"
32 
33 #include "util-conf.h"
34 #include "util-enum.h"
35 #include "util-path.h"
36 #include "util-syslog.h"
37 
38 // clang-format off
39 /* holds the string-enum mapping for the enums held in the table SCLogLevel */
41  { "Not set", SC_LOG_NOTSET },
42  { "None", SC_LOG_NONE },
43  { "Error", SC_LOG_ERROR },
44  { "Warning", SC_LOG_WARNING },
45  { "Notice", SC_LOG_NOTICE },
46  { "Info", SC_LOG_INFO },
47  { "Perf", SC_LOG_PERF },
48  { "Config", SC_LOG_CONFIG },
49  { "Debug", SC_LOG_DEBUG },
50  { NULL, -1 }
51 };
52 
54  { "Not set", SC_LOG_NOTSET },
55  { "None", SC_LOG_NONE },
56  { "E", SC_LOG_ERROR },
57  { "W", SC_LOG_WARNING },
58  { "i", SC_LOG_NOTICE },
59  { "i", SC_LOG_INFO },
60  { "i", SC_LOG_PERF },
61  { "i", SC_LOG_CONFIG },
62  { "d", SC_LOG_DEBUG },
63  { NULL, -1 }
64 };
65 
66 /* holds the string-enum mapping for the enums held in the table SCLogOPIface */
68  { "Console", SC_LOG_OP_IFACE_CONSOLE },
69  { "File", SC_LOG_OP_IFACE_FILE },
70  { "Syslog", SC_LOG_OP_IFACE_SYSLOG },
71  { NULL, -1 }
72 };
73 // clang-format on
74 
75 #if defined (OS_WIN32)
76 /**
77  * \brief Used for synchronous output on WIN32
78  */
79 static SCMutex sc_log_stream_lock;
80 #endif /* OS_WIN32 */
81 
82 /**
83  * \brief Transform the module name into display module name for logging
84  */
85 static const char *SCTransformModule(const char *module_name, int *dn_len);
86 
87 /**
88  * \brief Holds the config state for the logging module
89  */
90 static SCLogConfig *sc_log_config = NULL;
91 
92 /**
93  * \brief Returns the full path given a file and configured log dir
94  */
95 static char *SCLogGetLogFilename(const char *);
96 
97 /**
98  * \brief Holds the global log level. Is the same as sc_log_config->log_level
99  */
101 
102 /**
103  * \brief Used to indicate whether the logging module has been init or not
104  */
106 
107 /**
108  * \brief Used to indicate whether the logging module has been cleaned or not
109  */
111 
112 /**
113  * \brief Maps the SC logging level to the syslog logging level
114  *
115  * \param The SC logging level that has to be mapped to the syslog_log_level
116  *
117  * \retval syslog_log_level The mapped syslog_api_log_level, for the logging
118  * module api's internal log_level
119  */
120 static inline int SCLogMapLogLevelToSyslogLevel(int log_level)
121 {
122  int syslog_log_level = 0;
123 
124  switch (log_level) {
125  case SC_LOG_ERROR:
126  syslog_log_level = LOG_ERR;
127  break;
128  case SC_LOG_WARNING:
129  syslog_log_level = LOG_WARNING;
130  break;
131  case SC_LOG_NOTICE:
132  syslog_log_level = LOG_NOTICE;
133  break;
134  case SC_LOG_INFO:
135  syslog_log_level = LOG_INFO;
136  break;
137  case SC_LOG_CONFIG:
138  case SC_LOG_DEBUG:
139  case SC_LOG_PERF:
140  syslog_log_level = LOG_DEBUG;
141  break;
142  default:
143  syslog_log_level = LOG_EMERG;
144  break;
145  }
146 
147  return syslog_log_level;
148 }
149 
150 /**
151  * \brief Output function that logs a character string out to a file descriptor
152  *
153  * \param fd Pointer to the file descriptor
154  * \param msg Pointer to the character string that should be logged
155  */
156 static inline void SCLogPrintToStream(FILE *fd, char *msg)
157 {
158  /* Would only happen if the log file failed to re-open during rotation. */
159  if (fd == NULL) {
160  return;
161  }
162 
163 #if defined (OS_WIN32)
164  SCMutexLock(&sc_log_stream_lock);
165 #endif /* OS_WIN32 */
166 
167  if (fprintf(fd, "%s\n", msg) < 0)
168  printf("Error writing to stream using fprintf\n");
169 
170  fflush(fd);
171 
172 #if defined (OS_WIN32)
173  SCMutexUnlock(&sc_log_stream_lock);
174 #endif /* OS_WIN32 */
175 }
176 
177 /**
178  * \brief Output function that logs a character string through the syslog iface
179  *
180  * \param syslog_log_level Holds the syslog_log_level that the message should be
181  * logged as
182  * \param msg Pointer to the char string, that should be logged
183  *
184  * \todo syslog is thread-safe according to POSIX manual and glibc code, but we
185  * we will have to look into non POSIX compliant boxes like freeBSD
186  */
187 static inline void SCLogPrintToSyslog(int syslog_log_level, const char *msg)
188 {
189  //static struct syslog_data data = SYSLOG_DATA_INIT;
190  //syslog_r(syslog_log_level, NULL, "%s", msg);
191 
192  syslog(syslog_log_level, "%s", msg);
193 }
194 
195 /**
196  */
197 static int SCLogMessageJSON(SCTime_t tval, char *buffer, size_t buffer_size, SCLogLevel log_level,
198  const char *file, unsigned line, const char *function, const char *module,
199  const char *message)
200 {
201  SCJsonBuilder *js = SCJbNewObject();
202  if (unlikely(js == NULL))
203  goto error;
204 
205  char timebuf[64];
206  CreateIsoTimeString(tval, timebuf, sizeof(timebuf));
207  SCJbSetString(js, "timestamp", timebuf);
208 
209  const char *s = SCMapEnumValueToName(log_level, sc_log_level_map);
210  if (s != NULL) {
211  SCJbSetString(js, "log_level", s);
212  } else {
213  JB_SET_STRING(js, "log_level", "INVALID");
214  }
215 
216  JB_SET_STRING(js, "event_type", "engine");
217  SCJbOpenObject(js, "engine");
218 
219  if (message)
220  SCJbSetString(js, "message", message);
221 
222  if (t_thread_name[0] != '\0') {
223  SCJbSetString(js, "thread_name", t_thread_name);
224  }
225 
226  if (module) {
227  /* Determine how much of module name to display */
228  int dn_len = 0;
229  const char *dn_name;
230  dn_name = SCTransformModule(module, &dn_len);
231  SCJbSetString(js, "module", dn_name);
232  }
233 
234  if (log_level >= SC_LOG_DEBUG) {
235  if (function)
236  SCJbSetString(js, "function", function);
237 
238  if (file)
239  SCJbSetString(js, "file", file);
240 
241  if (line > 0)
242  SCJbSetUint(js, "line", line);
243  }
244  SCJbClose(js); // engine
245 
246  SCJbClose(js);
247  memcpy(buffer, SCJbPtr(js), MIN(buffer_size, SCJbLen(js)));
248 
249  SCJbFree(js);
250 
251  return 0;
252 
253 error:
254  return -1;
255 }
256 
257 static const int transform_max_segs = 2; /* The maximum segment count to display */
258 /*
259  * \brief Return a display name for the given module name for logging.
260  *
261  * The transformation is dependent upon the source code module names
262  * that use the dash character to separate incremental refinements of
263  * the subsystem.
264  *
265  * The transformation uses the local constant "transform_max_segs" to determine
266  * how many segments to display; the transformed name will never consist
267  * of more than this many segments.
268  *
269  * E.g., "detect-http-content-len" ==> "detect-http" when the max is 2
270  *
271  * \param module_name The source code module name to be transformed.
272  * \param dn_len The number of characters in the display name to print.
273  *
274  * \retval Pointer to the display name
275  */
276 static const char *SCTransformModule(const char *module_name, int *dn_len)
277 {
278  /*
279  * special case for source code module names beginning with:
280  * Prefixes skipped
281  * tm-*
282  * util-*
283  * source-*
284  * No transformation
285  * app-layer-*
286  */
287  if (strncmp("tm-", module_name, 3) == 0) {
288  *dn_len = (int)strlen(module_name) - 3;
289  return module_name + 3;
290  } else if (strncmp("util-", module_name, 5) == 0) {
291  *dn_len = (int)strlen(module_name) - 5;
292  return module_name + 5;
293  } else if (strncmp("source-pcap-file", module_name, 16) == 0) {
294  *dn_len = (int)strlen("pcap");
295  return "pcap";
296  } else if (strncmp("source-", module_name, 7) == 0) {
297  *dn_len = (int)strlen(module_name) - 7;
298  return module_name + 7;
299  } else if (strncmp("runmode-", module_name, 8) == 0) {
300  *dn_len = (int)strlen(module_name) - 8;
301  return module_name + 8;
302  } else if (strncmp("app-layer-", module_name, 10) == 0) {
303  *dn_len = (int)strlen(module_name);
304  return module_name;
305  } else if (strncmp("detect-engine", module_name, 13) == 0) {
306  *dn_len = (int)strlen("detect");
307  return "detect";
308  }
309 
310  int seg_cnt = 0;
311 
312  char *last;
313  char *w = (char *)module_name;
314  while (w && (w = strchr(w, '-')) != NULL && seg_cnt < transform_max_segs) {
315  seg_cnt++;
316  last = w;
317  w++; /* skip past '-' */
318  }
319 
320  if (seg_cnt < transform_max_segs)
321  *dn_len = (int)strlen(module_name);
322  else
323  *dn_len = (int)(last - module_name);
324 
325  return module_name;
326 }
327 
328 /**
329  * \brief Adds the global log_format to the outgoing buffer
330  *
331  * \param log_level log_level of the message that has to be logged
332  * \param msg Buffer containing the outgoing message
333  * \param file File_name from where the message originated
334  * \param function Function_name from where the message originated
335  * \param line Line_no from where the messaged originated
336  *
337  * \retval 0 on success; else a negative value on error
338  */
339 static SCError SCLogMessageGetBuffer(SCTime_t tval, bool color, SCLogOPType type, char *buffer,
340  size_t buffer_size, const char *log_format, const SCLogLevel log_level, const char *file,
341  const unsigned int line, const char *function, const char *module, const char *message)
342 {
343  if (type == SC_LOG_OP_TYPE_JSON)
344  return SCLogMessageJSON(
345  tval, buffer, buffer_size, log_level, file, line, function, module, message);
346 
347  char *temp = buffer;
348  const char *s = NULL;
349  struct tm *tms = NULL;
350 
351  const char *redb = "";
352  const char *red = "";
353  const char *yellowb = "";
354  const char *yellow = "";
355  const char *green = "";
356  const char *blue = "";
357  const char *reset = "";
358  if (color) {
359  redb = "\x1b[1;31m";
360  red = "\x1b[31m";
361  yellowb = "\x1b[1;33m";
362  yellow = "\x1b[33m";
363  green = "\x1b[32m";
364  blue = "\x1b[34m";
365  reset = "\x1b[0m";
366  }
367  /* no of characters_written(cw) by snprintf */
368  int cw = 0;
369 
371 
372  /* make a copy of the format string as it will be modified below */
373  const int add_M = strstr(log_format, "%M") == NULL;
374  DEBUG_VALIDATE_BUG_ON(strlen(log_format) > UINT16_MAX);
375  char local_format[strlen(log_format) + add_M * 2 + 1];
376  strlcpy(local_format, log_format, sizeof(local_format));
377  if (add_M)
378  strlcat(local_format, "%M", sizeof(local_format));
379  char *temp_fmt = local_format;
380  char *substr = temp_fmt;
381  struct tm local_tm;
382 
383  while ((temp_fmt = strchr(temp_fmt, SC_LOG_FMT_PREFIX))) {
384  if ((temp - buffer) > SC_LOG_MAX_LOG_MSG_LEN) {
385  return 0;
386  }
387  switch(temp_fmt[1]) {
388  case SC_LOG_FMT_TIME:
389  temp_fmt[0] = '\0';
390 
391  tms = SCLocalTime(SCTIME_SECS(tval), &local_tm);
392 
393  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
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,
396  reset);
397  if (cw < 0)
398  return -1;
399  temp += cw;
400  temp_fmt++;
401  substr = temp_fmt;
402  substr++;
403  break;
404 
406  temp_fmt[0] = '\0';
407 
408  tms = SCLocalTime(SCTIME_SECS(tval), &local_tm);
409 
410  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
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,
414  tms->tm_sec, reset);
415  if (cw < 0)
416  return -1;
417  temp += cw;
418  temp_fmt++;
419  substr = temp_fmt;
420  substr++;
421  break;
422 
423  case SC_LOG_FMT_PID:
424  temp_fmt[0] = '\0';
425  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
426  "%s%s%u%s", substr, yellow, getpid(), reset);
427  if (cw < 0)
428  return -1;
429  temp += cw;
430  temp_fmt++;
431  substr = temp_fmt;
432  substr++;
433  break;
434 
435  case SC_LOG_FMT_TID:
436  temp_fmt[0] = '\0';
437  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
438  "%s%s%lu%s", substr, yellow, SCGetThreadIdLong(), reset);
439  if (cw < 0)
440  return -1;
441  temp += cw;
442  temp_fmt++;
443  substr = temp_fmt;
444  substr++;
445  break;
446 
448  case SC_LOG_FMT_TM:
449  temp_fmt[0] = '\0';
450  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s%s%s%s", substr,
451  yellow, t_thread_name, reset);
452  if (cw < 0)
453  return -1;
454  temp += cw;
455  temp_fmt++;
456  substr = temp_fmt;
457  substr++;
458  break;
459 
461  temp_fmt[0] = '\0';
462  s = SCMapEnumValueToName(log_level, sc_log_level_map);
463  if (s != NULL) {
464  if (log_level <= SC_LOG_ERROR)
465  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
466  "%s%s%s%s", substr, redb, s, reset);
467  else if (log_level == SC_LOG_WARNING)
468  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
469  "%s%s%s%s", substr, red, s, reset);
470  else if (log_level == SC_LOG_NOTICE)
471  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
472  "%s%s%s%s", substr, yellowb, s, reset);
473  else
474  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s%s%s%s",
475  substr, yellow, s, reset);
476  } else {
477  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s%s", substr,
478  "INVALID");
479  }
480  if (cw < 0)
481  return -1;
482  temp += cw;
483  temp_fmt++;
484  substr = temp_fmt;
485  substr++;
486  break;
487 
489  temp_fmt[0] = '\0';
490  s = SCMapEnumValueToName(log_level, sc_log_slevel_map);
491  if (s != NULL) {
492  if (log_level <= SC_LOG_ERROR)
493  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s%s%s%s",
494  substr, redb, s, reset);
495  else if (log_level == SC_LOG_WARNING)
496  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s%s%s%s",
497  substr, red, s, reset);
498  else if (log_level == SC_LOG_NOTICE)
499  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s%s%s%s",
500  substr, yellowb, s, reset);
501  else
502  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
503  "%s%s%s%s", substr, yellow, s, reset);
504  } else {
505  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
506  "%s%s", substr, "INVALID");
507  }
508  if (cw < 0)
509  return -1;
510  temp += cw;
511  temp_fmt++;
512  substr = temp_fmt;
513  substr++;
514  break;
515 
517  temp_fmt[0] = '\0';
518  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
519  "%s%s%s%s", substr, blue, file, reset);
520  if (cw < 0)
521  return -1;
522  temp += cw;
523  temp_fmt++;
524  substr = temp_fmt;
525  substr++;
526  break;
527 
528  case SC_LOG_FMT_LINE:
529  temp_fmt[0] = '\0';
530  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
531  "%s%s%u%s", substr, green, line, reset);
532  if (cw < 0)
533  return -1;
534  temp += cw;
535  temp_fmt++;
536  substr = temp_fmt;
537  substr++;
538  break;
539 
541  temp_fmt[0] = '\0';
542 
543  /* Determine how much of module name to display */
544  int dn_len = 0;
545  const char *dn_name = "unknown";
546  if (module) {
547  dn_name = SCTransformModule(module, &dn_len);
548  }
549 
550  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s%s%s%s", substr,
551  green, dn_name, reset);
552  if (cw < 0)
553  return -1;
554  temp += cw;
555  temp_fmt++;
556  substr = temp_fmt;
557  substr++;
558  break;
559 
560  case SC_LOG_FMT_FUNCTION:
561  temp_fmt[0] = '\0';
562  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
563  "%s%s%s%s", substr, green, function, reset);
564  if (cw < 0)
565  return -1;
566  temp += cw;
567  temp_fmt++;
568  substr = temp_fmt;
569  substr++;
570  break;
571 
572  case SC_LOG_FMT_MESSAGE: {
573  temp_fmt[0] = '\0';
574  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s", substr);
575  if (cw < 0) {
576  return -1;
577  }
578  temp += cw;
579  if ((temp - buffer) > SC_LOG_MAX_LOG_MSG_LEN) {
580  return 0;
581  }
582  const char *hi = "";
583  if (log_level <= SC_LOG_ERROR)
584  hi = red;
585  else if (log_level <= SC_LOG_NOTICE)
586  hi = yellow;
587  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s%s%s", hi, message,
588  reset);
589  if (cw < 0) {
590  return -1;
591  }
592  temp += cw;
593  if ((temp - buffer) > SC_LOG_MAX_LOG_MSG_LEN) {
594  return 0;
595  }
596  temp_fmt++;
597  substr = temp_fmt;
598  substr++;
599  break;
600  }
601  }
602  temp_fmt++;
603  }
604  if ((temp - buffer) > SC_LOG_MAX_LOG_MSG_LEN) {
605  return 0;
606  }
607  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s", substr);
608  if (cw < 0) {
609  return -1;
610  }
611  if (sc_log_config->op_filter_regex != NULL) {
612  if (pcre2_match(sc_log_config->op_filter_regex, (PCRE2_SPTR8)buffer, strlen(buffer), 0, 0,
613  sc_log_config->op_filter_regex_match, NULL) < 0) {
614  return -1; // bit hacky, but just return !0
615  }
616  }
617 
618  return 0;
619 }
620 
621 /** \internal
622  * \brief try to reopen file
623  * \note no error reporting here, as we're called by SCLogMessage
624  * \retval status 0 ok, -1 error */
625 static int SCLogReopen(SCLogOPIfaceCtx *op_iface_ctx)
626 {
627  if (op_iface_ctx->file == NULL) {
628  return 0;
629  }
630 
631  if (op_iface_ctx->file_d != NULL) {
632  fclose(op_iface_ctx->file_d);
633  }
634  op_iface_ctx->file_d = fopen(op_iface_ctx->file, "a");
635  if (op_iface_ctx->file_d == NULL) {
636  return -1;
637  }
638  return 0;
639 }
640 
641 /**
642  * \brief Adds the global log_format to the outgoing buffer
643  *
644  * \param log_level log_level of the message that has to be logged
645  * \param msg Buffer containing the outgoing message
646  * \param file File_name from where the message originated
647  * \param function Function_name from where the message originated
648  * \param line Line_no from where the messaged originated
649  *
650  * \retval SC_OK on success; else an error code
651  */
652 SCError SCLogMessage(const SCLogLevel log_level, const char *file, const unsigned int line,
653  const char *function, const char *module, const char *message)
654 {
655  char buffer[SC_LOG_MAX_LOG_MSG_LEN] = "";
656  SCLogOPIfaceCtx *op_iface_ctx = NULL;
657 
658  if (sc_log_module_initialized != 1) {
659  printf("Logging module not initialized. Call SCLogInitLogModule() "
660  "first before using the debug API\n");
661  return SC_OK;
662  }
663 
664  /* get ts here so we log the same ts to each output */
665  struct timeval tval;
666  gettimeofday(&tval, NULL);
668 
669  op_iface_ctx = sc_log_config->op_ifaces;
670  while (op_iface_ctx != NULL) {
671  if (log_level != SC_LOG_NOTSET && log_level > op_iface_ctx->log_level) {
672  op_iface_ctx = op_iface_ctx->next;
673  continue;
674  }
675 
676  switch (op_iface_ctx->iface) {
678  if (SCLogMessageGetBuffer(ts, op_iface_ctx->use_color, op_iface_ctx->type, buffer,
679  sizeof(buffer),
680  op_iface_ctx->log_format ? op_iface_ctx->log_format
681  : sc_log_config->log_format,
682  log_level, file, line, function, module, message) == 0) {
683  SCLogPrintToStream((log_level == SC_LOG_ERROR)? stderr: stdout, buffer);
684  }
685  break;
687  if (SCLogMessageGetBuffer(ts, 0, op_iface_ctx->type, buffer, sizeof(buffer),
688  op_iface_ctx->log_format ? op_iface_ctx->log_format
689  : sc_log_config->log_format,
690  log_level, file, line, function, module, message) == 0) {
691  int r = 0;
692  SCMutexLock(&op_iface_ctx->fp_mutex);
693  if (op_iface_ctx->rotation_flag) {
694  r = SCLogReopen(op_iface_ctx);
695  op_iface_ctx->rotation_flag = 0;
696  }
697  SCLogPrintToStream(op_iface_ctx->file_d, buffer);
698  SCMutexUnlock(&op_iface_ctx->fp_mutex);
699 
700  /* report error outside of lock to avoid recursion */
701  if (r == -1) {
702  SCLogError("re-opening file \"%s\" failed: %s", op_iface_ctx->file,
703  strerror(errno));
704  }
705  }
706  break;
708  if (SCLogMessageGetBuffer(ts, 0, op_iface_ctx->type, buffer, sizeof(buffer),
709  op_iface_ctx->log_format ? op_iface_ctx->log_format
710  : sc_log_config->log_format,
711  log_level, file, line, function, module, message) == 0) {
712  SCLogPrintToSyslog(SCLogMapLogLevelToSyslogLevel(log_level), buffer);
713  }
714  break;
715  default:
716  break;
717  }
718  op_iface_ctx = op_iface_ctx->next;
719  }
720  return SC_OK;
721 }
722 
723 void SCLog(int x, const char *file, const char *func, const int line, const char *module,
724  const char *fmt, ...)
725 {
726  if (sc_log_global_log_level >= x &&
728  SCLogMatchFGFilterWL(file, func, line) == 1 ||
729  SCLogMatchFGFilterBL(file, func, line) == 1) &&
731  SCLogMatchFDFilter(func) == 1))
732  {
733  char msg[SC_LOG_MAX_LOG_MSG_LEN];
734  va_list ap;
735  va_start(ap, fmt);
736  vsnprintf(msg, sizeof(msg), fmt, ap);
737  va_end(ap);
738  SCLogMessage(x, file, line, func, module, msg);
739  }
740 }
741 
742 void SCLogErr(int x, const char *file, const char *func, const int line, const char *module,
743  const char *fmt, ...)
744 {
745  if (sc_log_global_log_level >= x &&
747  SCLogMatchFGFilterWL(file, func, line) == 1 ||
748  SCLogMatchFGFilterBL(file, func, line) == 1) &&
750  SCLogMatchFDFilter(func) == 1))
751  {
752  char msg[SC_LOG_MAX_LOG_MSG_LEN];
753  va_list ap;
754  va_start(ap, fmt);
755  vsnprintf(msg, sizeof(msg), fmt, ap);
756  va_end(ap);
757  SCLogMessage(x, file, line, func, module, msg);
758  }
759 }
760 
761 /**
762  * \brief Returns whether debug messages are enabled to be logged or not
763  *
764  * \retval 1 if debug messages are enabled to be logged
765  * \retval 0 if debug messages are not enabled to be logged
766  */
768 {
769 #ifdef DEBUG
771  return 1;
772  else
773  return 0;
774 #else
775  return 0;
776 #endif
777 }
778 
779 /**
780  * \brief Allocates an output buffer for an output interface. Used when we
781  * want the op_interface log_format to override the global_log_format.
782  * Currently not used.
783  *
784  * \retval buffer Pointer to the newly created output_buffer
785  */
787 {
788  SCLogOPBuffer *buffer = NULL;
789 
790  if ( (buffer = SCMalloc(sc_log_config->op_ifaces_cnt *
791  sizeof(SCLogOPBuffer))) == NULL) {
792  FatalError("Fatal error encountered in SCLogAllocLogOPBuffer. Exiting...");
793  }
794 
795  SCLogOPIfaceCtx *op_iface_ctx = sc_log_config->op_ifaces;
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;
799  }
800 
801  return buffer;
802 }
803 
804 /*----------------------The logging module initialization code--------------- */
805 
806 /**
807  * \brief Returns a new output_interface_context
808  *
809  * \retval iface_ctx Pointer to a newly allocated output_interface_context
810  * \initonly
811  */
812 static inline SCLogOPIfaceCtx *SCLogAllocLogOPIfaceCtx(void)
813 {
814  SCLogOPIfaceCtx *iface_ctx = NULL;
815 
816  if ((iface_ctx = SCCalloc(1, sizeof(SCLogOPIfaceCtx))) == NULL) {
817  FatalError("Fatal error encountered in SCLogallocLogOPIfaceCtx. Exiting...");
818  }
819 
820  return iface_ctx;
821 }
822 
823 /**
824  * \brief Initializes the file output interface
825  *
826  * \param file Path to the file used for logging purposes
827  * \param log_format Pointer to the log_format for this op interface, that
828  * overrides the global_log_format
829  * \param log_level Override of the global_log_level by this interface
830  *
831  * \retval iface_ctx Pointer to the file output interface context created
832  * \initonly
833  */
834 static inline SCLogOPIfaceCtx *SCLogInitFileOPIface(const char *file, uint32_t userid,
835  uint32_t groupid, const char *log_format, int log_level, SCLogOPType type)
836 {
837  SCLogOPIfaceCtx *iface_ctx = SCLogAllocLogOPIfaceCtx();
838  if (iface_ctx == NULL) {
839  FatalError("Fatal error encountered in SCLogInitFileOPIface. Exiting...");
840  }
841 
842  if (file == NULL) {
843  goto error;
844  }
845 
846  iface_ctx->iface = SC_LOG_OP_IFACE_FILE;
847  iface_ctx->type = type;
848 
849  if ( (iface_ctx->file_d = fopen(file, "a")) == NULL) {
850  SCLogWarning("error opening file %s: %s", file, strerror(errno));
851  goto error;
852  }
853 
854 #ifndef OS_WIN32
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));
858  }
859  }
860 #endif
861 
862  if ((iface_ctx->file = SCStrdup(file)) == NULL) {
863  goto error;
864  }
865 
866  if (log_format != NULL && (iface_ctx->log_format = SCStrdup(log_format)) == NULL) {
867  goto error;
868  }
869 
870  SCMutexInit(&iface_ctx->fp_mutex, NULL);
872 
873  iface_ctx->log_level = log_level;
874 
875  return iface_ctx;
876 
877 error:
878  if (iface_ctx->file != NULL) {
879  SCFree((char *)iface_ctx->file);
880  iface_ctx->file = NULL;
881  }
882  if (iface_ctx->log_format != NULL) {
883  SCFree((char *)iface_ctx->log_format);
884  iface_ctx->log_format = NULL;
885  }
886  if (iface_ctx->file_d != NULL) {
887  fclose(iface_ctx->file_d);
888  iface_ctx->file_d = NULL;
889  }
890  SCFree(iface_ctx);
891  return NULL;
892 }
893 
894 /**
895  * \brief Initializes the console output interface and deals with possible
896  * env var overrides.
897  *
898  * \param log_format Pointer to the log_format for this op interface, that
899  * overrides the global_log_format
900  * \param log_level Override of the global_log_level by this interface
901  *
902  * \retval iface_ctx Pointer to the console output interface context created
903  * \initonly
904  */
905 static inline SCLogOPIfaceCtx *SCLogInitConsoleOPIface(const char *log_format,
906  SCLogLevel log_level, SCLogOPType type)
907 {
908  SCLogOPIfaceCtx *iface_ctx = SCLogAllocLogOPIfaceCtx();
909 
910  if (iface_ctx == NULL) {
911  FatalError("Fatal error encountered in SCLogInitConsoleOPIface. Exiting...");
912  }
913 
914  iface_ctx->iface = SC_LOG_OP_IFACE_CONSOLE;
915  iface_ctx->type = type;
916 
917  /* console log format is overridden by envvars */
918  const char *tmp_log_format = log_format;
919  const char *s = getenv(SC_LOG_ENV_LOG_FORMAT);
920  if (s != NULL) {
921 #if 0
922  printf("Overriding setting for \"console.format\" because of env "
923  "var SC_LOG_FORMAT=\"%s\".\n", s);
924 #endif
925  tmp_log_format = s;
926  }
927 
928  if (tmp_log_format != NULL &&
929  (iface_ctx->log_format = SCStrdup(tmp_log_format)) == NULL) {
930  printf("Error allocating memory\n");
931  exit(EXIT_FAILURE);
932  }
933 
934  /* console log level is overridden by envvars */
935  SCLogLevel tmp_log_level = log_level;
936  s = getenv(SC_LOG_ENV_LOG_LEVEL);
937  if (s != NULL) {
939  if (l > SC_LOG_NOTSET && l < SC_LOG_LEVEL_MAX) {
940 #if 0
941  printf("Overriding setting for \"console.level\" because of env "
942  "var SC_LOG_LEVEL=\"%s\".\n", s);
943 #endif
944  tmp_log_level = l;
945  }
946  }
947  iface_ctx->log_level = tmp_log_level;
948 
949 #ifndef OS_WIN32
950  if (isatty(fileno(stdout)) && isatty(fileno(stderr))) {
951  iface_ctx->use_color = true;
952  }
953 #endif
954 
955  return iface_ctx;
956 }
957 
958 /**
959  * \brief Initializes the syslog output interface
960  *
961  * \param facility The facility code for syslog
962  * \param log_format Pointer to the log_format for this op interface, that
963  * overrides the global_log_format
964  * \param log_level Override of the global_log_level by this interface
965  *
966  * \retval iface_ctx Pointer to the syslog output interface context created
967  */
968 static inline SCLogOPIfaceCtx *SCLogInitSyslogOPIface(int facility,
969  const char *log_format,
970  SCLogLevel log_level,
972 {
973  SCLogOPIfaceCtx *iface_ctx = SCLogAllocLogOPIfaceCtx();
974 
975  if ( iface_ctx == NULL) {
976  FatalError("Fatal error encountered in SCLogInitSyslogOPIface. Exiting...");
977  }
978 
979  iface_ctx->iface = SC_LOG_OP_IFACE_SYSLOG;
980  iface_ctx->type = type;
981 
982  if (facility == -1)
983  facility = SC_LOG_DEF_SYSLOG_FACILITY;
984  iface_ctx->facility = facility;
985 
986  if (log_format != NULL &&
987  (iface_ctx->log_format = SCStrdup(log_format)) == NULL) {
988  printf("Error allocating memory\n");
989  exit(EXIT_FAILURE);
990  }
991 
992  iface_ctx->log_level = log_level;
993 
994  openlog(NULL, LOG_NDELAY, iface_ctx->facility);
995 
996  return iface_ctx;
997 }
998 
999 /**
1000  * \brief Frees the output_interface context supplied as an argument
1001  *
1002  * \param iface_ctx Pointer to the op_interface_context to be freed
1003  */
1004 static inline void SCLogFreeLogOPIfaceCtx(SCLogOPIfaceCtx *iface_ctx)
1005 {
1006  SCLogOPIfaceCtx *temp = NULL;
1007 
1008  while (iface_ctx != NULL) {
1009  temp = iface_ctx;
1010 
1011  if (iface_ctx->file_d != NULL) {
1012  fclose(iface_ctx->file_d);
1013  SCMutexDestroy(&iface_ctx->fp_mutex);
1014  }
1015 
1016  if (iface_ctx->file != NULL)
1017  SCFree((void *)iface_ctx->file);
1018 
1019  if (iface_ctx->log_format != NULL)
1020  SCFree((void *)iface_ctx->log_format);
1021 
1022  if (iface_ctx->iface == SC_LOG_OP_IFACE_SYSLOG) {
1023  closelog();
1024  }
1025 
1026  iface_ctx = iface_ctx->next;
1027 
1028  SCFree(temp);
1029  }
1030 }
1031 
1032 /**
1033  * \brief Internal function used to set the logging module global_log_level
1034  * during the initialization phase
1035  *
1036  * \param sc_lid The initialization data supplied.
1037  * \param sc_lc The logging module context which has to be updated.
1038  */
1039 static inline void SCLogSetLogLevel(SCLogInitData *sc_lid, SCLogConfig *sc_lc)
1040 {
1041  SCLogLevel log_level = SC_LOG_NOTSET;
1042  const char *s = NULL;
1043 
1044  /* envvar overrides config */
1045  s = getenv(SC_LOG_ENV_LOG_LEVEL);
1046  if (s != NULL) {
1047  log_level = SCMapEnumNameToValue(s, sc_log_level_map);
1048  } else if (sc_lid != NULL) {
1049  log_level = sc_lid->global_log_level;
1050  }
1051 
1052  /* deal with the global_log_level to be used */
1053  if (log_level > SC_LOG_NOTSET && log_level < SC_LOG_LEVEL_MAX)
1054  sc_lc->log_level = log_level;
1055  else {
1057 #ifndef UNITTESTS
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",
1062  }
1063 #endif
1064  }
1065 
1066  /* we also set it to a global var, as it is easier to access it */
1068 }
1069 
1070 const char *SCLogLevel2Name(const SCLogLevel lvl)
1071 {
1073 }
1074 
1076 {
1077  return sc_log_global_log_level;
1078 }
1079 
1080 static inline const char *SCLogGetDefaultLogFormat(const SCLogLevel lvl)
1081 {
1082  const char *prog_ver = GetProgramVersion();
1083  if (strstr(prog_ver, "RELEASE") != NULL) {
1084  if (lvl <= SC_LOG_NOTICE)
1086  else if (lvl <= SC_LOG_INFO)
1088  else if (lvl <= SC_LOG_CONFIG)
1090  }
1092 }
1093 
1094 /**
1095  * \brief Internal function used to set the logging module global_log_format
1096  * during the initialization phase
1097  *
1098  * \param sc_lid The initialization data supplied.
1099  * \param sc_lc The logging module context which has to be updated.
1100  */
1101 static inline void SCLogSetLogFormat(SCLogInitData *sc_lid, SCLogConfig *sc_lc)
1102 {
1103  const char *format = NULL;
1104 
1105  /* envvar overrides config */
1106  format = getenv(SC_LOG_ENV_LOG_FORMAT);
1107  if (format == NULL) {
1108  if (sc_lid != NULL) {
1109  format = sc_lid->global_log_format;
1110  }
1111  }
1112 
1113  /* deal with the global log format to be used */
1114  if (format == NULL || strlen(format) > SC_LOG_MAX_LOG_FORMAT_LEN) {
1115  format = SCLogGetDefaultLogFormat(sc_lc->log_level);
1116 #ifndef UNITTESTS
1117  if (sc_lid != NULL) {
1118  printf("Warning: Invalid/No global_log_format supplied by user or format "
1119  "length exceeded limit of \"%d\" characters. Falling back on "
1120  "default log_format \"%s\"\n", SC_LOG_MAX_LOG_FORMAT_LEN,
1121  format);
1122  }
1123 #endif
1124  }
1125 
1126  if (format != NULL && (sc_lc->log_format = SCStrdup(format)) == NULL) {
1127  printf("Error allocating memory\n");
1128  exit(EXIT_FAILURE);
1129  }
1130 }
1131 
1132 /**
1133  * \brief Internal function used to set the logging module global_op_ifaces
1134  * during the initialization phase
1135  *
1136  * \param sc_lid The initialization data supplied.
1137  * \param sc_lc The logging module context which has to be updated.
1138  */
1139 static inline void SCLogSetOPIface(SCLogInitData *sc_lid, SCLogConfig *sc_lc)
1140 {
1141  SCLogOPIfaceCtx *op_ifaces_ctx = NULL;
1142  int op_iface = 0;
1143  const char *s = NULL;
1144 
1145  if (sc_lid != NULL && sc_lid->op_ifaces != NULL) {
1146  sc_lc->op_ifaces = sc_lid->op_ifaces;
1147  sc_lid->op_ifaces = NULL;
1148  sc_lc->op_ifaces_cnt = sc_lid->op_ifaces_cnt;
1149  } else {
1150  s = getenv(SC_LOG_ENV_LOG_OP_IFACE);
1151  if (s != NULL) {
1153 
1154  if(op_iface < 0 || op_iface >= SC_LOG_OP_IFACE_MAX) {
1155  op_iface = SC_LOG_DEF_LOG_OP_IFACE;
1156 #ifndef UNITTESTS
1157  printf("Warning: Invalid output interface supplied by user. "
1158  "Falling back on default_output_interface \"%s\"\n",
1160 #endif
1161  }
1162  }
1163  else {
1164  op_iface = SC_LOG_DEF_LOG_OP_IFACE;
1165 #ifndef UNITTESTS
1166  if (sc_lid != NULL) {
1167  printf("Warning: Output_interface not supplied by user. Falling "
1168  "back on default_output_interface \"%s\"\n",
1170  }
1171 #endif
1172  }
1173 
1174  switch (op_iface) {
1176  op_ifaces_ctx = SCLogInitConsoleOPIface(NULL, SC_LOG_LEVEL_MAX,0);
1177  break;
1178  case SC_LOG_OP_IFACE_FILE:
1179  s = getenv(SC_LOG_ENV_LOG_FILE);
1180  if (s == NULL) {
1181  char *str = SCLogGetLogFilename(SC_LOG_DEF_LOG_FILE);
1182  if (str != NULL) {
1183  op_ifaces_ctx = SCLogInitFileOPIface(str, 0, 0, NULL, SC_LOG_LEVEL_MAX, 0);
1184  SCFree(str);
1185  }
1186  } else {
1187  op_ifaces_ctx = SCLogInitFileOPIface(s, 0, 0, NULL, SC_LOG_LEVEL_MAX, 0);
1188  }
1189  break;
1191  s = getenv(SC_LOG_ENV_LOG_FACILITY);
1192  if (s == NULL)
1194 
1195  op_ifaces_ctx = SCLogInitSyslogOPIface(SCMapEnumNameToValue(s, SCSyslogGetFacilityMap()), NULL, -1,0);
1196  break;
1197  }
1198  sc_lc->op_ifaces = op_ifaces_ctx;
1199  sc_lc->op_ifaces_cnt++;
1200  }
1201 }
1202 
1203 /**
1204  * \brief Internal function used to set the logging module op_filter
1205  * during the initialization phase
1206  *
1207  * \param sc_lid The initialization data supplied.
1208  * \param sc_lc The logging module context which has to be updated.
1209  */
1210 static inline void SCLogSetOPFilter(SCLogInitData *sc_lid, SCLogConfig *sc_lc)
1211 {
1212  const char *filter = NULL;
1213 
1214  int opts = 0;
1215  int en;
1216  PCRE2_SIZE eo = 0;
1217 
1218  /* envvar overrides */
1219  filter = getenv(SC_LOG_ENV_LOG_OP_FILTER);
1220  if (filter == NULL) {
1221  if (sc_lid != NULL) {
1222  filter = sc_lid->op_filter;
1223  }
1224  }
1225 
1226  if (filter != NULL && strcmp(filter, "") != 0) {
1227  sc_lc->op_filter = SCStrdup(filter);
1228  if (sc_lc->op_filter == NULL) {
1229  printf("pcre filter alloc failed\n");
1230  return;
1231  }
1232  sc_lc->op_filter_regex =
1233  pcre2_compile((PCRE2_SPTR8)filter, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
1234  if (sc_lc->op_filter_regex == NULL) {
1235  SCFree(sc_lc->op_filter);
1236  PCRE2_UCHAR errbuffer[256];
1237  pcre2_get_error_message(en, errbuffer, sizeof(errbuffer));
1238  printf("pcre2 compile of \"%s\" failed at offset %d : %s\n", filter, (int)eo,
1239  errbuffer);
1240  return;
1241  }
1242  sc_lc->op_filter_regex_match =
1243  pcre2_match_data_create_from_pattern(sc_lc->op_filter_regex, NULL);
1244  }
1245 }
1246 
1247 /**
1248  * \brief Returns a pointer to a new SCLogInitData. This is a public interface
1249  * intended to be used after the logging parameters are read from the
1250  * conf file
1251  *
1252  * \retval sc_lid Pointer to the newly created SCLogInitData
1253  * \initonly
1254  */
1256 {
1257  SCLogInitData *sc_lid = NULL;
1258 
1259  if ((sc_lid = SCCalloc(1, sizeof(SCLogInitData))) == NULL)
1260  return NULL;
1261 
1262  return sc_lid;
1263 }
1264 
1265 #ifdef UNITTESTS
1266 #ifndef OS_WIN32
1267 /**
1268  * \brief Frees a SCLogInitData
1269  *
1270  * \param sc_lid Pointer to the SCLogInitData to be freed
1271  */
1272 static void SCLogFreeLogInitData(SCLogInitData *sc_lid)
1273 {
1274  if (sc_lid != NULL) {
1275  SCLogFreeLogOPIfaceCtx(sc_lid->op_ifaces);
1276  SCFree(sc_lid);
1277  }
1278 }
1279 #endif
1280 #endif
1281 
1282 /**
1283  * \brief Frees the logging module context
1284  */
1285 static inline void SCLogFreeLogConfig(SCLogConfig *sc_lc)
1286 {
1287  if (sc_lc != NULL) {
1288  if (sc_lc->startup_message != NULL)
1289  SCFree(sc_lc->startup_message);
1290  if (sc_lc->log_format != NULL)
1291  SCFree(sc_lc->log_format);
1292  if (sc_lc->op_filter != NULL)
1293  SCFree(sc_lc->op_filter);
1294 
1295  if (sc_lc->op_filter_regex != NULL)
1296  pcre2_code_free(sc_lc->op_filter_regex);
1297  if (sc_lc->op_filter_regex_match)
1298  pcre2_match_data_free(sc_lc->op_filter_regex_match);
1299 
1300  SCLogFreeLogOPIfaceCtx(sc_lc->op_ifaces);
1301  SCFree(sc_lc);
1302  }
1303 }
1304 
1305 /**
1306  * \brief Appends an output_interface to the output_interface list sent in head
1307  *
1308  * \param iface_ctx Pointer to the output_interface that has to be added to head
1309  * \param head Pointer to the output_interface list
1310  */
1312 {
1313  SCLogOPIfaceCtx *temp = NULL, *prev = NULL;
1314  SCLogOPIfaceCtx **head = &sc_lid->op_ifaces;
1315 
1316  if (iface_ctx == NULL) {
1317 #ifdef DEBUG
1318  printf("Argument(s) to SCLogAppendOPIfaceCtx() NULL\n");
1319 #endif
1320  return;
1321  }
1322 
1323  temp = *head;
1324  while (temp != NULL) {
1325  prev = temp;
1326  temp = temp->next;
1327  }
1328 
1329  if (prev == NULL)
1330  *head = iface_ctx;
1331  else
1332  prev->next = iface_ctx;
1333 
1334  sc_lid->op_ifaces_cnt++;
1335 }
1336 
1337 #ifdef UNITTESTS
1338 #ifndef OS_WIN32
1339 /**
1340  * \internal
1341  * \brief Creates a new output interface based on the arguments sent. The kind
1342  * of output interface to be created is decided by the iface_name arg.
1343  * If iface_name is "file", the arg argument will hold the filename to be
1344  * used for logging purposes. If iface_name is "syslog", the arg
1345  * argument holds the facility code. If iface_name is "console", arg is
1346  * NULL.
1347  *
1348  * \param iface_name Interface name. Can be "console", "file" or "syslog"
1349  * \param log_format Override for the global_log_format
1350  * \param log_level Override for the global_log_level
1351  * \param log_level Parameter required by a particular interface. Explained in
1352  * the function description
1353  *
1354  * \retval iface_ctx Pointer to the newly created output interface
1355  */
1356 static SCLogOPIfaceCtx *SCLogInitOPIfaceCtx(
1357  const char *iface_name, const char *log_format, int log_level, const char *arg)
1358 {
1359  int iface = SCMapEnumNameToValue(iface_name, sc_log_op_iface_map);
1360 
1361  if (log_level < SC_LOG_NONE || log_level > SC_LOG_DEBUG) {
1362  printf("Warning: Supplied log_level_override for op_interface \"%s\" "
1363  "is invalid. Defaulting to not specifying an override\n",
1364  iface_name);
1365  log_level = SC_LOG_NOTSET;
1366  }
1367 
1368  switch (iface) {
1370  return SCLogInitConsoleOPIface(log_format, log_level, SC_LOG_OP_TYPE_REGULAR);
1371  case SC_LOG_OP_IFACE_FILE:
1372  return SCLogInitFileOPIface(arg, 0, 0, log_format, log_level, SC_LOG_OP_TYPE_REGULAR);
1374  return SCLogInitSyslogOPIface(SCMapEnumNameToValue(arg, SCSyslogGetFacilityMap()),
1375  log_format, log_level, SC_LOG_OP_TYPE_REGULAR);
1376  default:
1377 #ifdef DEBUG
1378  printf("Output Interface \"%s\" not supported by the logging module",
1379  iface_name);
1380 #endif
1381  return NULL;
1382  }
1383 }
1384 #endif
1385 #endif
1386 
1387 /**
1388  * \brief Initializes the logging module.
1389  *
1390  * \param sc_lid The initialization data for the logging module. If sc_lid is
1391  * NULL, we would stick to the default configuration for the
1392  * logging subsystem.
1393  * \initonly
1394  */
1396 {
1397  /* De-initialize the logging context, if it has already init by the
1398  * environment variables at the start of the engine */
1400 
1401 #if defined (OS_WIN32)
1402  if (SCMutexInit(&sc_log_stream_lock, NULL) != 0) {
1403  FatalError("Failed to initialize log mutex.");
1404  }
1405 #endif /* OS_WIN32 */
1406 
1407  /* sc_log_config is a global variable */
1408  if ((sc_log_config = SCCalloc(1, sizeof(SCLogConfig))) == NULL) {
1409  FatalError("Fatal error encountered in SCLogInitLogModule. Exiting...");
1410  }
1411 
1412  SCLogSetLogLevel(sc_lid, sc_log_config);
1413  SCLogSetLogFormat(sc_lid, sc_log_config);
1414  SCLogSetOPIface(sc_lid, sc_log_config);
1415  SCLogSetOPFilter(sc_lid, sc_log_config);
1416 
1419 
1420  //SCOutputPrint(sc_did->startup_message);
1421 
1422  SCSetRustLogLevel(sc_log_global_log_level);
1423 }
1424 
1425 void SCLogLoadConfig(int daemon, int verbose, uint32_t userid, uint32_t groupid)
1426 {
1427  SCConfNode *outputs;
1428  SCLogInitData *sc_lid;
1429  int have_logging = 0;
1430  int max_level = 0;
1431  SCLogLevel min_level = 0;
1432 
1433  /* If verbose logging was requested, set the minimum as
1434  * SC_LOG_NOTICE plus the extra verbosity. */
1435  if (verbose) {
1436  min_level = SC_LOG_NOTICE + verbose;
1437  }
1438 
1439  outputs = SCConfGetNode("logging.outputs");
1440  if (outputs == NULL) {
1441  SCLogDebug("No logging.output configuration section found.");
1442  return;
1443  }
1444 
1445  sc_lid = SCLogAllocLogInitData();
1446  if (sc_lid == NULL) {
1447  SCLogDebug("Could not allocate memory for log init data");
1448  return;
1449  }
1450 
1451  /* Get default log level and format. */
1452  const char *default_log_level_s = NULL;
1453  if (SCConfGetNonNull("logging.default-log-level", &default_log_level_s) == 1) {
1454  SCLogLevel default_log_level =
1455  SCMapEnumNameToValue(default_log_level_s, sc_log_level_map);
1456  if (default_log_level == -1) {
1457  SCLogError("Invalid default log level: %s", default_log_level_s);
1458  exit(EXIT_FAILURE);
1459  }
1460  sc_lid->global_log_level = MAX(min_level, default_log_level);
1461  } else {
1462  sc_lid->global_log_level = MAX(min_level, SC_LOG_NOTICE);
1463  }
1464 
1465  if (SCConfGetNonNull("logging.default-log-format", &sc_lid->global_log_format) != 1)
1466  sc_lid->global_log_format = SCLogGetDefaultLogFormat(sc_lid->global_log_level);
1467 
1468  (void)SCConfGet("logging.default-output-filter", &sc_lid->op_filter);
1469 
1470  SCConfNode *seq_node, *output;
1471  TAILQ_FOREACH(seq_node, &outputs->head, next) {
1472  SCLogLevel level = sc_lid->global_log_level;
1473  SCLogOPIfaceCtx *op_iface_ctx = NULL;
1474  const char *format;
1475  const char *level_s;
1476 
1477  output = SCConfNodeLookupChild(seq_node, seq_node->val);
1478  if (output == NULL)
1479  continue;
1480 
1481  /* By default an output is enabled. */
1482  const char *enabled = SCConfNodeLookupChildValue(output, "enabled");
1483  if (enabled != NULL && SCConfValIsFalse(enabled))
1484  continue;
1485 
1487  const char *type_s = SCConfNodeLookupChildValue(output, "type");
1488  if (type_s != NULL) {
1489  if (strcmp(type_s, "regular") == 0)
1491  else if (strcmp(type_s, "json") == 0) {
1493  }
1494  }
1495 
1496  format = SCConfNodeLookupChildValue(output, "format");
1497 
1498  level_s = SCConfNodeLookupChildValue(output, "level");
1499  if (level_s != NULL) {
1500  level = SCMapEnumNameToValue(level_s, sc_log_level_map);
1501  if (level == -1) {
1502  SCLogError("Invalid log level: %s", level_s);
1503  exit(EXIT_FAILURE);
1504  }
1505  max_level = MAX(max_level, level);
1506  }
1507 
1508  /* Increase the level of extra verbosity was requested. */
1509  level = MAX(min_level, level);
1510 
1511  if (strcmp(output->name, "console") == 0) {
1512  op_iface_ctx = SCLogInitConsoleOPIface(format, level, type);
1513  }
1514  else if (strcmp(output->name, "file") == 0) {
1515  if (format == NULL) {
1516  format = SC_LOG_DEF_FILE_FORMAT;
1517  }
1518 
1519  const char *filename = SCConfNodeLookupChildValue(output, "filename");
1520  if (filename == NULL) {
1521  FatalError("Logging to file requires a filename");
1522  }
1523  char *path = NULL;
1524  if (!(PathIsAbsolute(filename))) {
1525  path = SCLogGetLogFilename(filename);
1526  } else {
1527  path = SCStrdup(filename);
1528  }
1529  if (path == NULL)
1530  FatalError("failed to setup output to file");
1531  have_logging = 1;
1532  op_iface_ctx = SCLogInitFileOPIface(path, userid, groupid, format, level, type);
1533  SCFree(path);
1534  }
1535  else if (strcmp(output->name, "syslog") == 0) {
1536  int facility = SC_LOG_DEF_SYSLOG_FACILITY;
1537  const char *facility_s = SCConfNodeLookupChildValue(output, "facility");
1538  if (facility_s != NULL) {
1539  facility = SCMapEnumNameToValue(facility_s, SCSyslogGetFacilityMap());
1540  if (facility == -1) {
1541  SCLogWarning("Invalid syslog "
1542  "facility: \"%s\", now using \"%s\" as syslog "
1543  "facility",
1544  facility_s, SC_LOG_DEF_SYSLOG_FACILITY_STR);
1545  facility = SC_LOG_DEF_SYSLOG_FACILITY;
1546  }
1547  }
1548  SCLogDebug("Initializing syslog logging with format \"%s\"", format);
1549  have_logging = 1;
1550  op_iface_ctx = SCLogInitSyslogOPIface(facility, format, level, type);
1551  }
1552  else {
1553  SCLogWarning("invalid logging method: %s, ignoring", output->name);
1554  }
1555  if (op_iface_ctx != NULL) {
1556  SCLogAppendOPIfaceCtx(op_iface_ctx, sc_lid);
1557  }
1558  }
1559 
1560  if (daemon && (have_logging == 0)) {
1561  SCLogWarning("no logging compatible with daemon mode selected,"
1562  " suricata won't be able to log. Please update "
1563  " 'logging.outputs' in the YAML.");
1564  }
1565 
1566  /* Set the global log level to that of the max level used. */
1567  sc_lid->global_log_level = MAX(sc_lid->global_log_level, max_level);
1568  SCLogInitLogModule(sc_lid);
1569 
1570  SCLogDebug("sc_log_global_log_level: %d", sc_log_global_log_level);
1571  SCLogDebug("sc_lc->log_format: %s", sc_log_config->log_format);
1572  SCLogDebug("SCLogSetOPFilter: filter: %s", sc_log_config->op_filter);
1573 
1574  SCFree(sc_lid);
1575 }
1576 
1577 /**
1578  * \brief Returns a full file path given a filename uses log dir specified in
1579  * conf or DEFAULT_LOG_DIR
1580  *
1581  * \param filearg The relative filename for which we want a full path include
1582  * log directory
1583  *
1584  * \retval log_filename The fullpath of the logfile to open
1585  */
1586 static char *SCLogGetLogFilename(const char *filearg)
1587 {
1588  const char *log_dir = SCConfigGetLogDirectory();
1589  char *log_filename = SCMalloc(PATH_MAX);
1590  if (unlikely(log_filename == NULL))
1591  return NULL;
1592  snprintf(log_filename, PATH_MAX, "%s/%s", log_dir, filearg);
1593  return log_filename;
1594 }
1595 
1596 /**
1597  * \brief De-Initializes the logging module
1598  */
1600 {
1601  SCLogFreeLogConfig(sc_log_config);
1602 
1603  /* reset the global logging_module variables */
1607  sc_log_config = NULL;
1608 
1609  /* de-init the FD filters */
1611  /* de-init the FG filters */
1613 
1614 #if defined (OS_WIN32)
1615  SCMutexDestroy(&sc_log_stream_lock);
1616 #endif /* OS_WIN32 */
1617 }
1618 
1619 void SCFatalErrorOnInitStatic(const char *arg)
1620 {
1621  FatalErrorOnInit("%s", arg);
1622 }
1623 
1624 //------------------------------------Unit_Tests--------------------------------
1625 
1626 /* The logging engine should be tested to the maximum extent possible, since
1627  * logging code would be used throughout the codebase, and hence we can't afford
1628  * to have a single bug here(not that you can afford to have a bug
1629  * elsewhere ;) ). Please report a bug, if you get a slightest hint of a bug
1630  * from the logging module.
1631  */
1632 
1633 #ifdef UNITTESTS
1634 
1635 static int SCLogTestInit01(void)
1636 {
1637 #ifndef OS_WIN32
1638  /* unset any environment variables set for the logging module */
1642 
1643  SCLogInitLogModule(NULL);
1644 
1645  FAIL_IF_NULL(sc_log_config);
1646 
1647  FAIL_IF_NOT(SC_LOG_DEF_LOG_LEVEL == sc_log_config->log_level);
1648  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1649  SC_LOG_DEF_LOG_OP_IFACE == sc_log_config->op_ifaces->iface);
1650  FAIL_IF_NOT(sc_log_config->log_format != NULL &&
1651  strcmp(SCLogGetDefaultLogFormat(sc_log_config->log_level),
1652  sc_log_config->log_format) == 0);
1653 
1655 
1656  setenv(SC_LOG_ENV_LOG_LEVEL, "Debug", 1);
1657  setenv(SC_LOG_ENV_LOG_OP_IFACE, "Console", 1);
1658  setenv(SC_LOG_ENV_LOG_FORMAT, "%n- %l", 1);
1659 
1660  SCLogInitLogModule(NULL);
1661 
1662  FAIL_IF_NOT(SC_LOG_DEBUG == sc_log_config->log_level);
1663  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1664  SC_LOG_OP_IFACE_CONSOLE == sc_log_config->op_ifaces->iface);
1665  FAIL_IF_NOT(sc_log_config->log_format != NULL &&
1666  !strcmp("%n- %l", sc_log_config->log_format));
1667 
1671 
1673 #endif
1674  PASS;
1675 }
1676 
1677 static int SCLogTestInit02(void)
1678 {
1679 #ifndef OS_WIN32
1680  SCLogInitData *sc_lid = NULL;
1681  SCLogOPIfaceCtx *sc_iface_ctx = NULL;
1682  char *logfile = SCLogGetLogFilename("boo.txt");
1683  sc_lid = SCLogAllocLogInitData();
1684  FAIL_IF_NULL(sc_lid);
1685  sc_lid->startup_message = "Test02";
1686  sc_lid->global_log_level = SC_LOG_DEBUG;
1687  sc_lid->op_filter = "boo";
1688  sc_iface_ctx = SCLogInitOPIfaceCtx("file", "%m - %d", SC_LOG_WARNING, logfile);
1689  SCLogAppendOPIfaceCtx(sc_iface_ctx, sc_lid);
1690  sc_iface_ctx = SCLogInitOPIfaceCtx("console", NULL, SC_LOG_ERROR,
1691  NULL);
1692  SCLogAppendOPIfaceCtx(sc_iface_ctx, sc_lid);
1693 
1694  SCLogInitLogModule(sc_lid);
1695 
1696  FAIL_IF_NULL(sc_log_config);
1697 
1698  FAIL_IF_NOT(SC_LOG_DEBUG == sc_log_config->log_level);
1699  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1700  SC_LOG_OP_IFACE_FILE == sc_log_config->op_ifaces->iface);
1701  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1702  sc_log_config->op_ifaces->next != NULL &&
1703  SC_LOG_OP_IFACE_CONSOLE == sc_log_config->op_ifaces->next->iface);
1704  FAIL_IF_NOT(sc_log_config->log_format != NULL &&
1705  strcmp(SCLogGetDefaultLogFormat(sc_log_config->log_level),
1706  sc_log_config->log_format) == 0);
1707  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1708  sc_log_config->op_ifaces->log_format != NULL &&
1709  strcmp("%m - %d", sc_log_config->op_ifaces->log_format) == 0);
1710  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1711  sc_log_config->op_ifaces->next != NULL &&
1712  sc_log_config->op_ifaces->next->log_format == NULL);
1713 
1714  SCLogFreeLogInitData(sc_lid);
1716 
1717  sc_lid = SCLogAllocLogInitData();
1718  FAIL_IF_NULL(sc_lid);
1719  sc_lid->startup_message = "Test02";
1720  sc_lid->global_log_level = SC_LOG_DEBUG;
1721  sc_lid->op_filter = "boo";
1722  sc_lid->global_log_format = "kaboo";
1723 
1724  SCLogInitLogModule(sc_lid);
1725 
1726  FAIL_IF_NULL(sc_log_config);
1727 
1728  FAIL_IF_NOT(SC_LOG_DEBUG == sc_log_config->log_level);
1729  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1730  SC_LOG_OP_IFACE_CONSOLE == sc_log_config->op_ifaces->iface);
1731  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1732  sc_log_config->op_ifaces->next == NULL);
1733  FAIL_IF_NOT(sc_log_config->log_format != NULL &&
1734  strcmp("kaboo", sc_log_config->log_format) == 0);
1735  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1736  sc_log_config->op_ifaces->log_format == NULL);
1737  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1738  sc_log_config->op_ifaces->next == NULL);
1739 
1740  SCLogFreeLogInitData(sc_lid);
1742  SCFree(logfile);
1743 #endif
1744  PASS;
1745 }
1746 
1747 static int SCLogTestInit03(void)
1748 {
1749  SCLogInitLogModule(NULL);
1750 
1751  SCLogAddFGFilterBL(NULL, "bamboo", -1);
1752  SCLogAddFGFilterBL(NULL, "soo", -1);
1753  SCLogAddFGFilterBL(NULL, "dummy", -1);
1754 
1756 
1757  SCLogAddFGFilterBL(NULL, "dummy1", -1);
1758  SCLogAddFGFilterBL(NULL, "dummy2", -1);
1759 
1761 
1763 
1764  PASS;
1765 }
1766 
1767 static int SCLogTestInit04(void)
1768 {
1769  SCLogInitLogModule(NULL);
1770 
1771  SCLogAddFDFilter("bamboo");
1772  SCLogAddFDFilter("soo");
1773  SCLogAddFDFilter("foo");
1774  SCLogAddFDFilter("roo");
1775 
1777 
1778  SCLogAddFDFilter("loo");
1779  SCLogAddFDFilter("soo");
1780 
1782 
1783  SCLogRemoveFDFilter("bamboo");
1784  SCLogRemoveFDFilter("soo");
1785  SCLogRemoveFDFilter("foo");
1786  SCLogRemoveFDFilter("noo");
1787 
1789 
1791 
1792  PASS;
1793 }
1794 
1795 static int SCLogTestInit05(void)
1796 {
1797  char str[4096];
1798  memset(str, 'A', sizeof(str));
1799  str[sizeof(str) - 1] = '\0';
1800  SCLogInfo("%s", str);
1801 
1802  PASS;
1803 }
1804 
1805 #endif /* UNITTESTS */
1806 
1808 {
1809 
1810 #ifdef UNITTESTS
1811 
1812  UtRegisterTest("SCLogTestInit01", SCLogTestInit01);
1813  UtRegisterTest("SCLogTestInit02", SCLogTestInit02);
1814  UtRegisterTest("SCLogTestInit03", SCLogTestInit03);
1815  UtRegisterTest("SCLogTestInit04", SCLogTestInit04);
1816  UtRegisterTest("SCLogTestInit05", SCLogTestInit05);
1817 
1818 #endif /* UNITTESTS */
1819 
1820  return;
1821 }
SCJsonBuilder
struct SCJsonBuilder SCJsonBuilder
Definition: detect-engine-helper.h:83
SC_LOG_DEF_SYSLOG_FACILITY
#define SC_LOG_DEF_SYSLOG_FACILITY
Definition: util-debug.h:108
SCLogConfig_::op_ifaces
SCLogOPIfaceCtx * op_ifaces
Definition: util-debug.h:189
ts
uint64_t ts
Definition: source-erf-file.c:68
SCLogMatchFGFilterBL
int SCLogMatchFGFilterBL(const char *file, const char *function, int line)
Checks if there is a match for the incoming log_message with any of the FG filters....
Definition: util-debug-filters.c:312
SC_LOG_DEF_SYSLOG_FACILITY_STR
#define SC_LOG_DEF_SYSLOG_FACILITY_STR
Definition: util-debug.h:107
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SC_LOG_FMT_MESSAGE
#define SC_LOG_FMT_MESSAGE
Definition: util-debug.h:207
SCLogConfig_::op_filter_regex_match
pcre2_match_data * op_filter_regex_match
Definition: util-debug.h:186
SCLog
void SCLog(int x, const char *file, const char *func, const int line, const char *module, const char *fmt,...)
Definition: util-debug.c:723
SCLogInitLogModule
void SCLogInitLogModule(SCLogInitData *sc_lid)
Initializes the logging module.
Definition: util-debug.c:1395
syslog
#define syslog(__pri, __fmt, __param)
Definition: win32-syslog.h:78
SCLogOPIfaceCtx_::log_level
SCLogLevel log_level
Definition: util-debug.h:141
sc_log_level_map
SCEnumCharMap sc_log_level_map[]
Definition: util-debug.c:40
CreateIsoTimeString
void CreateIsoTimeString(const SCTime_t ts, char *str, size_t size)
Definition: util-time.c:209
SCLogOPIfaceCtx_::facility
int facility
Definition: util-debug.h:138
SC_LOG_DEBUG
@ SC_LOG_DEBUG
Definition: util-debug.h:44
sc_log_fg_filters_present
int sc_log_fg_filters_present
Definition: util-debug-filters.c:36
unsetenv
void unsetenv(const char *name)
SC_LOG_OP_TYPE_REGULAR
@ SC_LOG_OP_TYPE_REGULAR
Definition: util-debug.h:80
SC_LOG_CONFIG
@ SC_LOG_CONFIG
Definition: util-debug.h:43
SCLogAllocLogOPBuffer
SCLogOPBuffer * SCLogAllocLogOPBuffer(void)
Allocates an output buffer for an output interface. Used when we want the op_interface log_format to ...
Definition: util-debug.c:786
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
SC_LOG_NOTSET
@ SC_LOG_NOTSET
Definition: util-debug.h:36
SC_LOG_FMT_PREFIX
#define SC_LOG_FMT_PREFIX
Definition: util-debug.h:210
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:101
SC_LOG_FMT_FILE_NAME
#define SC_LOG_FMT_FILE_NAME
Definition: util-debug.h:202
SCLogInitData_::global_log_format
const char * global_log_format
Definition: util-debug.h:164
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
SC_LOG_OP_TYPE_JSON
@ SC_LOG_OP_TYPE_JSON
Definition: util-debug.h:81
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
SCLogOPBuffer_
Structure to be used when log_level override support would be provided by the logging module.
Definition: util-debug.h:114
SCLogOPIfaceCtx_::fp_mutex
SCMutex fp_mutex
Definition: util-debug.h:147
SC_LOG_ENV_LOG_OP_IFACE
#define SC_LOG_ENV_LOG_OP_IFACE
Definition: util-debug.h:63
type
uint8_t type
Definition: decode-sctp.h:0
SCLogOPIfaceCtx_::use_color
bool use_color
Definition: util-debug.h:126
SCLogConfig_::op_filter
char * op_filter
Definition: util-debug.h:183
util-syslog.h
SC_LOG_ENV_LOG_FACILITY
#define SC_LOG_ENV_LOG_FACILITY
Definition: util-debug.h:65
SC_LOG_DEF_LOG_FORMAT_DEBUG
#define SC_LOG_DEF_LOG_FORMAT_DEBUG
Definition: util-debug.h:89
SCLogDeInitLogModule
void SCLogDeInitLogModule(void)
De-Initializes the logging module.
Definition: util-debug.c:1599
SCConfGet
int SCConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:352
LOG_DEBUG
#define LOG_DEBUG
Definition: win32-syslog.h:46
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
sc_log_module_initialized
int sc_log_module_initialized
Used to indicate whether the logging module has been init or not.
Definition: util-debug.c:105
SC_LOG_NOTICE
@ SC_LOG_NOTICE
Definition: util-debug.h:40
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
SC_LOG_DEF_LOG_OP_IFACE
#define SC_LOG_DEF_LOG_OP_IFACE
Definition: util-debug.h:101
MIN
#define MIN(x, y)
Definition: suricata-common.h:413
SCLogOPIfaceCtx_::log_format
const char * log_format
Definition: util-debug.h:144
SCConfValIsFalse
int SCConfValIsFalse(const char *val)
Check if a value is false.
Definition: conf.c:602
SCLogInitData_
Structure containing init data, that would be passed to SCInitDebugModule()
Definition: util-debug.h:156
SC_LOG_FMT_TIME_LEGACY
#define SC_LOG_FMT_TIME_LEGACY
Definition: util-debug.h:196
SC_LOG_FMT_LOG_LEVEL
#define SC_LOG_FMT_LOG_LEVEL
Definition: util-debug.h:200
SCConfNodeLookupChildValue
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:877
SCLogOPType
SCLogOPType
Definition: util-debug.h:79
MAX
#define MAX(x, y)
Definition: suricata-common.h:417
SCLogMatchFDFilter
int SCLogMatchFDFilter(const char *function)
Checks if there is a match for the incoming log_message with any of the FD filters.
Definition: util-debug-filters.c:456
SCLogOPIfaceCtx_::type
SCLogOPType type
Definition: util-debug.h:127
SC_LOG_LEVEL_MAX
@ SC_LOG_LEVEL_MAX
Definition: util-debug.h:45
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
closelog
#define closelog()
Definition: win32-syslog.h:75
t_thread_name
thread_local char t_thread_name[THREAD_NAME_LEN+1]
Definition: threads.c:32
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
SCLogReleaseFGFilters
void SCLogReleaseFGFilters(void)
Definition: util-debug-filters.c:338
SC_LOG_DEF_LOG_FORMAT_REL_INFO
#define SC_LOG_DEF_LOG_FORMAT_REL_INFO
Definition: util-debug.h:87
SCLogOPIfaceCtx_
The output interface context for the logging module.
Definition: util-debug.h:123
OutputRegisterFileRotationFlag
void OutputRegisterFileRotationFlag(int *flag)
Register a flag for file rotation notification.
Definition: output.c:698
SC_LOG_INFO
@ SC_LOG_INFO
Definition: util-debug.h:41
SC_LOG_ERROR
@ SC_LOG_ERROR
Definition: util-debug.h:38
SC_LOG_ENV_LOG_LEVEL
#define SC_LOG_ENV_LOG_LEVEL
ENV vars that can be used to set the properties for the logging module.
Definition: util-debug.h:62
util-debug.h
JB_SET_STRING
#define JB_SET_STRING(jb, key, val)
Definition: rust.h:36
SCLogReleaseFDFilters
void SCLogReleaseFDFilters(void)
Releases all the FD filters added to the logging module.
Definition: util-debug-filters.c:698
SC_LOG_FMT_THREAD_NAME
#define SC_LOG_FMT_THREAD_NAME
Definition: util-debug.h:206
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
SCLogConfig_::op_filter_regex
pcre2_code * op_filter_regex
Definition: util-debug.h:185
SCLogLevel2Name
const char * SCLogLevel2Name(const SCLogLevel lvl)
Definition: util-debug.c:1070
strlcat
size_t strlcat(char *, const char *src, size_t siz)
Definition: util-strlcatu.c:45
SCSyslogGetFacilityMap
SCEnumCharMap * SCSyslogGetFacilityMap(void)
returns the syslog facility enum map
Definition: util-syslog.c:61
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:120
SCLogConfig_::op_ifaces_cnt
uint8_t op_ifaces_cnt
Definition: util-debug.h:191
LOG_NOTICE
#define LOG_NOTICE
Definition: win32-syslog.h:44
SCConfGetNonNull
int SCConfGetNonNull(const char *name, const char **vptr)
Retrieve the non-null value of a configuration node.
Definition: conf.c:380
SCTIME_FROM_TIMEVAL
#define SCTIME_FROM_TIMEVAL(tv)
Definition: util-time.h:79
SCLogConfig_::log_level
SCLogLevel log_level
Definition: util-debug.h:180
SC_LOG_OP_IFACE_MAX
@ SC_LOG_OP_IFACE_MAX
Definition: util-debug.h:76
SCLogOPIfaceCtx_::iface
SCLogOPIface iface
Definition: util-debug.h:124
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:262
SCLogErr
void SCLogErr(int x, const char *file, const char *func, const int line, const char *module, const char *fmt,...)
Definition: util-debug.c:742
GetProgramVersion
const char * GetProgramVersion(void)
get string with program version
Definition: suricata.c:1237
SCLogOPBuffer_::log_format
const char * log_format
Definition: util-debug.h:117
SCLogOPIfaceCtx_::file
const char * file
Definition: util-debug.h:130
SC_LOG_ENV_LOG_FILE
#define SC_LOG_ENV_LOG_FILE
Definition: util-debug.h:64
SCLocalTime
struct tm * SCLocalTime(time_t timep, struct tm *result)
Definition: util-time.c:267
SCLogMatchFGFilterWL
int SCLogMatchFGFilterWL(const char *file, const char *function, int line)
Checks if there is a match for the incoming log_message with any of the FG filters....
Definition: util-debug-filters.c:294
SCConfigGetLogDirectory
const char * SCConfigGetLogDirectory(void)
Definition: util-conf.c:38
sc_log_module_cleaned
int sc_log_module_cleaned
Used to indicate whether the logging module has been cleaned or not.
Definition: util-debug.c:110
SCLogConfig_::startup_message
char * startup_message
Definition: util-debug.h:179
SCLogOPBuffer_::msg
char msg[SC_LOG_MAX_LOG_MSG_LEN]
Definition: util-debug.h:115
SCLogInitData_::global_log_level
SCLogLevel global_log_level
Definition: util-debug.h:161
SC_OK
@ SC_OK
Definition: util-error.h:27
SCTime_t
Definition: util-time.h:40
SCLogRegisterTests
void SCLogRegisterTests(void)
Definition: util-debug.c:1807
SC_LOG_DEF_LOG_FILE
#define SC_LOG_DEF_LOG_FILE
Definition: util-debug.h:104
SC_LOG_OP_IFACE_FILE
@ SC_LOG_OP_IFACE_FILE
Definition: util-debug.h:74
setenv
void setenv(const char *name, const char *value, int overwrite)
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:232
SCLogLevel
SCLogLevel
The various log levels NOTE: when adding new level, don't forget to update SCLogMapLogLevelToSyslogLe...
Definition: util-debug.h:35
SCMutexInit
#define SCMutexInit(mut, mutattrs)
Definition: threads-debug.h:116
LOG_EMERG
#define LOG_EMERG
Definition: win32-syslog.h:39
SC_LOG_WARNING
@ SC_LOG_WARNING
Definition: util-debug.h:39
SCLogInitData_::op_filter
const char * op_filter
Definition: util-debug.h:167
SC_LOG_MAX_LOG_FORMAT_LEN
#define SC_LOG_MAX_LOG_FORMAT_LEN
Definition: util-debug.h:95
SCGetThreadIdLong
#define SCGetThreadIdLong(...)
Definition: threads.h:256
sc_log_op_iface_map
SCEnumCharMap sc_log_op_iface_map[]
Definition: util-debug.c:67
SCConfNodeLookupChild
SCConfNode * SCConfNodeLookupChild(const SCConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:849
SC_LOG_FMT_SUBSYSTEM
#define SC_LOG_FMT_SUBSYSTEM
Definition: util-debug.h:205
util-conf.h
SCMapEnumValueToName
const char * SCMapEnumValueToName(int enum_value, SCEnumCharMap *table)
Maps an enum value to a string name, from the supplied table.
Definition: util-enum.c:68
SCLogPrintFDFilters
int SCLogPrintFDFilters(void)
Prints the FG filters(both WL and BL). Used for debugging purposes.
Definition: util-debug-filters.c:785
SCMapEnumNameToValue
int SCMapEnumNameToValue(const char *enum_name, SCEnumCharMap *table)
Maps a string name to an enum value from the supplied table. Please specify the last element of any m...
Definition: util-enum.c:40
SCLogMessage
SCError SCLogMessage(const SCLogLevel log_level, const char *file, const unsigned int line, const char *function, const char *module, const char *message)
Adds the global log_format to the outgoing buffer.
Definition: util-debug.c:652
suricata-common.h
util-path.h
SC_LOG_DEF_LOG_LEVEL
#define SC_LOG_DEF_LOG_LEVEL
Definition: util-debug.h:98
SCFatalErrorOnInitStatic
void SCFatalErrorOnInitStatic(const char *arg)
Definition: util-debug.c:1619
FatalErrorOnInit
#define FatalErrorOnInit(...)
Fatal error IF we're starting up, and configured to consider errors to be fatal errors.
Definition: util-debug.h:526
SCEnumCharMap_
Definition: util-enum.h:27
SC_LOG_ENV_LOG_OP_FILTER
#define SC_LOG_ENV_LOG_OP_FILTER
Definition: util-debug.h:67
SCLogConfig_::log_format
char * log_format
Definition: util-debug.h:181
SCLogOPIfaceCtx_::next
struct SCLogOPIfaceCtx_ * next
Definition: util-debug.h:149
SCTIME_SECS
#define SCTIME_SECS(t)
Definition: util-time.h:57
SCError
SCError
Definition: util-error.h:26
SC_LOG_ENV_LOG_FORMAT
#define SC_LOG_ENV_LOG_FORMAT
Definition: util-debug.h:66
PathIsAbsolute
int PathIsAbsolute(const char *path)
Check if a path is absolute.
Definition: util-path.c:44
SC_LOG_PERF
@ SC_LOG_PERF
Definition: util-debug.h:42
SCLogConfig_
Holds the config state used by the logging api.
Definition: util-debug.h:178
SC_LOG_FMT_LOG_SLEVEL
#define SC_LOG_FMT_LOG_SLEVEL
Definition: util-debug.h:201
SCLogInitData_::op_ifaces_cnt
uint8_t op_ifaces_cnt
Definition: util-debug.h:172
SCLogOPIfaceCtx_::rotation_flag
int rotation_flag
Definition: util-debug.h:135
sc_log_fd_filters_present
int sc_log_fd_filters_present
Definition: util-debug-filters.c:39
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
FatalError
#define FatalError(...)
Definition: util-debug.h:517
LOG_WARNING
#define LOG_WARNING
Definition: win32-syslog.h:43
SC_LOG_OP_IFACE_SYSLOG
@ SC_LOG_OP_IFACE_SYSLOG
Definition: util-debug.h:75
SCLogAllocLogInitData
SCLogInitData * SCLogAllocLogInitData(void)
Returns a pointer to a new SCLogInitData. This is a public interface intended to be used after the lo...
Definition: util-debug.c:1255
SC_LOG_DEF_LOG_FORMAT_REL_CONFIG
#define SC_LOG_DEF_LOG_FORMAT_REL_CONFIG
Definition: util-debug.h:88
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
str
#define str(s)
Definition: suricata-common.h:313
SCConfGetNode
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
Definition: conf.c:183
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
head
Flow * head
Definition: flow-hash.h:1
SCFree
#define SCFree(p)
Definition: util-mem.h:61
SC_LOG_MAX_LOG_MSG_LEN
#define SC_LOG_MAX_LOG_MSG_LEN
Definition: util-debug.h:92
SCLogOPBuffer_::temp
char * temp
Definition: util-debug.h:116
SC_LOG_FMT_FUNCTION
#define SC_LOG_FMT_FUNCTION
Definition: util-debug.h:204
SC_LOG_FMT_PID
#define SC_LOG_FMT_PID
Definition: util-debug.h:197
SCLogRemoveFDFilter
int SCLogRemoveFDFilter(const char *function)
Removes a Function-Dependent(FD) filter.
Definition: util-debug-filters.c:725
SCLogPrintFGFilters
int SCLogPrintFGFilters(void)
Prints the FG filters(both WL and BL). Used for debugging purposes.
Definition: util-debug-filters.c:388
SC_LOG_NONE
@ SC_LOG_NONE
Definition: util-debug.h:37
sc_log_global_log_level
SCLogLevel sc_log_global_log_level
Holds the global log level. Is the same as sc_log_config->log_level.
Definition: util-debug.c:100
SCLogAddFGFilterBL
int SCLogAddFGFilterBL(const char *file, const char *function, int line)
Adds a Blacklist(BL) fine-grained(FG) filter. A FG filter BL filter allows messages that don't match ...
Definition: util-debug-filters.c:333
SC_LOG_FMT_TID
#define SC_LOG_FMT_TID
Definition: util-debug.h:198
suricata.h
SCConfNode_::name
char * name
Definition: conf.h:38
SCLogOPIfaceCtx_::file_d
FILE * file_d
Definition: util-debug.h:132
SCLogLoadConfig
void SCLogLoadConfig(int daemon, int verbose, uint32_t userid, uint32_t groupid)
Definition: util-debug.c:1425
SCLogAppendOPIfaceCtx
void SCLogAppendOPIfaceCtx(SCLogOPIfaceCtx *iface_ctx, SCLogInitData *sc_lid)
Appends an output_interface to the output_interface list sent in head.
Definition: util-debug.c:1311
SC_LOG_FMT_TIME
#define SC_LOG_FMT_TIME
Definition: util-debug.h:195
SCLogInitData_::startup_message
const char * startup_message
Definition: util-debug.h:158
SCLogAddFDFilter
int SCLogAddFDFilter(const char *function)
Adds a Function-Dependent(FD) filter.
Definition: util-debug-filters.c:639
openlog
#define openlog(__ident, __option, __facility)
Definition: win32-syslog.h:76
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
util-enum.h
SCMutexDestroy
#define SCMutexDestroy
Definition: threads-debug.h:121
SCConfNode_
Definition: conf.h:37
SC_LOG_FMT_LINE
#define SC_LOG_FMT_LINE
Definition: util-debug.h:203
SCLogInitData_::op_ifaces
SCLogOPIfaceCtx * op_ifaces
Definition: util-debug.h:170
SCLogGetLogLevel
SCLogLevel SCLogGetLogLevel(void)
Definition: util-debug.c:1075
SCConfNode_::val
char * val
Definition: conf.h:39
SC_LOG_OP_IFACE_CONSOLE
@ SC_LOG_OP_IFACE_CONSOLE
Definition: util-debug.h:73
SCMutex
#define SCMutex
Definition: threads-debug.h:114
SCLogDebugEnabled
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition: util-debug.c:767
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:109
SC_LOG_DEF_FILE_FORMAT
#define SC_LOG_DEF_FILE_FORMAT
Definition: util-debug.h:85
SC_LOG_DEF_LOG_FORMAT_REL_NOTICE
#define SC_LOG_DEF_LOG_FORMAT_REL_NOTICE
Definition: util-debug.h:86
output.h
sc_log_slevel_map
SCEnumCharMap sc_log_slevel_map[]
Definition: util-debug.c:53
LOG_INFO
#define LOG_INFO
Definition: win32-syslog.h:45
LOG_ERR
#define LOG_ERR
Definition: win32-syslog.h:42
SC_LOG_FMT_TM
#define SC_LOG_FMT_TM
Definition: util-debug.h:199