33 #if defined(HAVE_DIRENT_H) && defined(HAVE_FNMATCH_H)
34 #define INIT_RING_BUFFER
57 #define DEFAULT_LOG_FILENAME "pcaplog"
58 #define MODULE_NAME "PcapLog"
59 #define MIN_LIMIT 4 * 1024 * 1024
60 #define DEFAULT_LIMIT 100 * 1024 * 1024
61 #define DEFAULT_FILE_LIMIT 0
63 #define LOGMODE_NORMAL 0
64 #define LOGMODE_MULTI 1
72 #define RING_BUFFER_MODE_DISABLED 0
73 #define RING_BUFFER_MODE_ENABLED 1
75 #define TS_FORMAT_SEC 0
76 #define TS_FORMAT_USEC 1
78 #define USE_STREAM_DEPTH_DISABLED 0
79 #define USE_STREAM_DEPTH_ENABLED 1
81 #define HONOR_PASS_RULES_DISABLED 0
82 #define HONOR_PASS_RULES_ENABLED 1
84 #define PCAP_SNAPLEN 262144
85 #define PCAP_BUFFER_TIMEOUT 1000000 // microseconds
86 #define PCAP_PKTHDR_SIZE 16
89 #ifndef PCAP_NETMASK_UNKNOWN
90 #define PCAP_NETMASK_UNKNOWN 0xffffffff
117 #define MAX_FILENAMELEN 513
129 LZ4F_compressionContext_t lz4f_context;
130 LZ4F_preferences_t lz4f_prefs;
131 FILE *pcap_buf_wrapper;
150 struct pcap_pkthdr *
h;
176 uint32_t thread_number;
178 int timestamp_format;
185 int filename_part_cnt;
186 struct timeval last_pcap_dump;
202 static const char timestamp_pattern[] =
".*?(\\d+)(\\.(\\d+))?";
203 static pcre2_code *pcre_timestamp_code = NULL;
204 static pcre2_match_data *pcre_timestamp_match = NULL;
214 static void PcapLogFileDeInitCtx(
OutputCtx *);
223 .ConditionFunc = PcapLogCondition,
224 .ThreadInitFunc = PcapLogDataInit,
225 .ThreadDeinitFunc = PcapLogDataDeinit,
226 .ThreadExitPrintStatsFunc = NULL,
235 #define PCAPLOG_PROFILE_START \
236 uint64_t pcaplog_profile_ticks = UtilCpuGetTicks()
238 #define PCAPLOG_PROFILE_END(prof) \
239 (prof).total += (UtilCpuGetTicks() - pcaplog_profile_ticks); \
260 return !PacketIsTunnelChild(
p);
279 comp->pcap_buf_wrapper = NULL;
296 uint64_t bytes_written = LZ4F_compressEnd(comp->lz4f_context,
298 if (LZ4F_isError(bytes_written)) {
299 SCLogError(
"LZ4F_compressEnd: %s", LZ4F_getErrorName(bytes_written));
302 if (fwrite(comp->
buffer, 1, bytes_written, comp->
file) < bytes_written) {
303 SCLogError(
"fwrite failed: %s", strerror(errno));
345 if (PcapLogCloseFile(t,pl) < 0) {
362 PcapFileNameFree(pf);
366 if (PcapLogOpenFileCtx(pl) < 0) {
367 SCLogError(
"opening new pcap log file failed");
382 if (PacketIsTunnelChild(
p)) {
387 SCLogDebug(
"Setting pcap-log link type to %u", datalink);
394 struct bpf_program bpfp;
401 if (pl->
bpfp == NULL) {
402 FatalError(
"Failed to allocate memory for BPF filter, aborting");
413 if (!pl->pcap_open_err) {
415 pl->pcap_open_err =
true;
419 pl->pcap_open_err =
false;
427 if (comp->
file == NULL) {
428 if (errno != pl->fopen_err) {
429 SCLogError(
"Error opening file for compressed output: %s", strerror(errno));
430 pl->fopen_err = errno;
438 if (comp->pcap_buf_wrapper == NULL) {
445 if (!pl->pcap_open_err) {
447 pl->pcap_open_err =
true;
451 fclose(comp->pcap_buf_wrapper);
452 comp->pcap_buf_wrapper = NULL;
455 pl->pcap_open_err =
false;
458 uint64_t bytes_written = LZ4F_compressBegin(comp->lz4f_context,
460 if (LZ4F_isError(bytes_written)) {
461 SCLogError(
"LZ4F_compressBegin: %s", LZ4F_getErrorName(bytes_written));
464 if (fwrite(comp->
buffer, 1, bytes_written, comp->
file) < bytes_written) {
465 SCLogError(
"fwrite failed: %s", strerror(errno));
502 static inline int PcapWrite(
505 struct timeval current_dump;
506 gettimeofday(¤t_dump, NULL);
510 if (pcap_offline_filter(pl->
bpfp, pl->
h, data) == 0) {
511 SCLogDebug(
"Packet doesn't match filter, will not be logged.");
527 long in_size = ftell(comp->pcap_buf_wrapper);
529 SCLogError(
"ftell failed with: %s", strerror(errno));
532 uint64_t out_size = LZ4F_compressUpdate(comp->lz4f_context, comp->
buffer, comp->
buffer_size,
533 comp->
pcap_buf, (uint64_t)in_size, NULL);
534 if (LZ4F_isError(
len)) {
535 SCLogError(
"LZ4F_compressUpdate: %s", LZ4F_getErrorName(
len));
538 if (fseek(comp->pcap_buf_wrapper, 0, SEEK_SET) != 0) {
539 SCLogError(
"fseek failed: %s", strerror(errno));
542 if (fwrite(comp->
buffer, 1, out_size, comp->
file) < out_size) {
543 SCLogError(
"fwrite failed: %s", strerror(errno));
557 pl->last_pcap_dump = current_dump;
566 static int PcapLogSegmentCallback(
567 const Packet *
p,
TcpSegment *seg,
void *data,
const uint8_t *buf, uint32_t buflen)
580 const uint32_t total_len = pktlen + buflen;
584 if (expand_by % 4096 != 0) {
585 expand_by = expand_by - (expand_by % 4096) + 4096;
588 SCLogWarning(
"Failed to expand pcap-log buffer for segment "
597 MemBufferReset(pctx->
td->
buf);
601 PcapWrite(pctx->
tv, pctx->
td, (uint8_t *)pctx->
td->
buf->
buffer, total_len);
644 if (PacketIsTunnelChild(
p)) {
656 ret = PcapLogOpenFileCtx(pl);
667 if (PcapLogRotateFile(
tv, pl) < 0) {
683 if (PcapLogRotateFile(
tv, pl) < 0) {
706 if (PacketIsTCP(
p)) {
708 PcapLogDumpSegments(
tv,
td,
p);
718 if (PacketIsTunnelChild(
p)) {
731 if (PacketIsTunnelChild(
p)) {
746 SCLogDebug(
"pl->size_current %"PRIu64
", pl->size_limit %"PRIu64,
767 copy->prefix =
SCStrdup(pl->prefix);
768 if (
unlikely(copy->prefix == NULL)) {
774 copy->suffix = pl->suffix;
780 copy->use_ringbuffer = pl->use_ringbuffer;
781 copy->timestamp_format = pl->timestamp_format;
797 copy_comp->lz4f_prefs = comp->lz4f_prefs;
802 if (copy_comp->
buffer == NULL) {
803 SCLogError(
"SCMalloc failed: %s", strerror(errno));
811 SCLogError(
"SCMalloc failed: %s", strerror(errno));
820 if (copy_comp->pcap_buf_wrapper == NULL) {
821 SCLogError(
"SCFmemopen failed: %s", strerror(errno));
832 LZ4F_errorCode_t errcode =
833 LZ4F_createCompressionContext(©_comp->lz4f_context, 1);
834 if (LZ4F_isError(errcode)) {
835 SCLogError(
"LZ4F_createCompressionContext failed: %s", LZ4F_getErrorName(errcode));
836 fclose(copy_comp->pcap_buf_wrapper);
847 copy_comp->
file = NULL;
855 strlcpy(copy->dir, pl->dir,
sizeof(copy->dir));
857 for (
int i = 0; i < pl->filename_part_cnt && i <
MAX_TOKS; i++)
858 copy->filename_parts[i] = pl->filename_parts[i];
859 copy->filename_part_cnt = pl->filename_part_cnt;
868 #ifdef INIT_RING_BUFFER
869 static int PcapLogGetTimeOfFile(
const char *filename, uint64_t *secs,
875 int n = pcre2_match(pcre_timestamp_code, (PCRE2_SPTR8)filename, strlen(filename), 0, 0,
876 pcre_timestamp_match, NULL);
877 if (n != 2 && n != 4) {
884 copylen =
sizeof(buf);
885 if (pcre2_substring_copy_bynumber(pcre_timestamp_match, 1, (PCRE2_UCHAR8 *)buf, ©len) <
895 copylen =
sizeof(buf);
896 if (pcre2_substring_copy_bynumber(pcre_timestamp_match, 3, (PCRE2_UCHAR8 *)buf, ©len) <
910 char pattern[PATH_MAX];
912 SCLogInfo(
"Initializing PCAP ring buffer for %s/%s.",
913 pl->dir, pl->prefix);
915 strlcpy(pattern, pl->dir, PATH_MAX);
916 if (pattern[strlen(pattern) - 1] !=
'/') {
917 strlcat(pattern,
"/", PATH_MAX);
920 for (
int i = 0; i < pl->filename_part_cnt; i++) {
921 char *part = pl->filename_parts[i];
922 if (part == NULL || strlen(part) == 0) {
925 if (part[0] !=
'%' || strlen(part) < 2) {
926 strlcat(pattern, part, PATH_MAX);
931 SCLogError(
"Thread ID not allowed in ring buffer mode.");
935 snprintf(tmp, PATH_MAX,
"%"PRIu32, pl->thread_number);
936 strlcat(pattern, tmp, PATH_MAX);
940 strlcat(pattern,
"*", PATH_MAX);
943 SCLogError(
"Unsupported format character: %%%s", part);
948 strlcat(pattern, pl->prefix, PATH_MAX);
949 strlcat(pattern,
".*", PATH_MAX);
951 strlcat(pattern, pl->suffix, PATH_MAX);
953 char *basename = strrchr(pattern,
'/');
957 DIR *dir = opendir(pattern);
959 SCLogWarning(
"Failed to open directory %s: %s", pattern, strerror(errno));
964 struct dirent *entry = readdir(dir);
968 if (fnmatch(basename, entry->d_name, 0) != 0) {
975 if (!PcapLogGetTimeOfFile(entry->d_name, &secs, &usecs)) {
986 if (
PathMerge(path,
sizeof(path), pattern, entry->d_name) < 0)
1042 PcapFileNameFree(pf);
1058 static TmEcode PcapLogDataInit(
ThreadVars *t,
const void *initdata,
void **data)
1060 if (initdata == NULL) {
1061 SCLogDebug(
"Error getting context for LogPcap. \"initdata\" argument NULL");
1075 td->
pcap_log = PcapLogDataCopy(pl);
1082 FatalError(
"Pcap logging with multiple link type is not supported.");
1093 FatalError(
"Can't have multiple link types in pcap conditional mode.");
1096 SCLogWarning(
"Using multiple link types can result in invalid pcap output");
1132 #ifdef INIT_RING_BUFFER
1137 SCLogInfo(
"Unable to initialize ring buffer on this platform.");
1148 PcapLogOpenFileCtx(pl);
1158 dst->profile_open.total +=
src->profile_open.total;
1159 dst->profile_open.cnt +=
src->profile_open.cnt;
1161 dst->profile_close.total +=
src->profile_close.total;
1162 dst->profile_close.cnt +=
src->profile_close.cnt;
1164 dst->profile_write.total +=
src->profile_write.total;
1165 dst->profile_write.cnt +=
src->profile_write.cnt;
1167 dst->profile_rotate.total +=
src->profile_rotate.total;
1168 dst->profile_rotate.cnt +=
src->profile_rotate.cnt;
1170 dst->profile_handles.total +=
src->profile_handles.total;
1171 dst->profile_handles.cnt +=
src->profile_handles.cnt;
1173 dst->profile_lock.total +=
src->profile_lock.total;
1174 dst->profile_lock.cnt +=
src->profile_lock.cnt;
1176 dst->profile_unlock.total +=
src->profile_unlock.total;
1177 dst->profile_unlock.cnt +=
src->profile_unlock.cnt;
1179 dst->profile_data_size +=
src->profile_data_size;
1186 while ((pf =
TAILQ_FIRST(&pl->pcap_file_list)) != NULL) {
1189 PcapFileNameFree(pf);
1191 if (pl == g_pcap_data) {
1192 for (
int i = 0; i <
MAX_TOKS; i++) {
1193 if (pl->filename_parts[i] != NULL) {
1194 SCFree(pl->filename_parts[i]);
1207 pcap_freecode(pl->
bpfp);
1213 SCFree(pl->compression.buffer);
1214 if (pl->compression.pcap_buf_wrapper)
1215 fclose(pl->compression.pcap_buf_wrapper);
1216 SCFree(pl->compression.pcap_buf);
1217 LZ4F_errorCode_t errcode =
1218 LZ4F_freeCompressionContext(pl->compression.lz4f_context);
1219 if (LZ4F_isError(errcode)) {
1248 StatsMerge(g_pcap_data, pl);
1249 g_pcap_data->reported++;
1250 if (g_pcap_data->threads == g_pcap_data->reported)
1251 PcapLogProfilingDump(g_pcap_data);
1254 if (pl->reported == 0) {
1255 PcapLogProfilingDump(pl);
1260 if (pl != g_pcap_data) {
1261 PcapLogDataFree(pl);
1272 static int ParseFilename(
PcapLogData *pl,
const char *filename)
1279 size_t filename_len = 0;
1282 filename_len = strlen(filename);
1288 for (
int i = 0; i < (int)strlen(filename); i++) {
1290 SCLogError(
"invalid filename option. Max 2 %%-sign options");
1294 str[s++] = filename[i];
1296 if (filename[i] ==
'%') {
1307 if (i+1 < (
int)strlen(filename)) {
1309 SCLogError(
"invalid filename option. Max 2 %%-sign options");
1313 if (filename[i+1] !=
'n' && filename[i+1] !=
't' && filename[i+1] !=
'i') {
1315 "invalid filename option. Valid %%-sign options: %%n, %%i and %%t");
1319 str[1] = filename[i+1];
1331 SCLogError(
"Invalid filename for multimode. Need at least one %%-sign option");
1337 SCLogError(
"invalid filename option. Max 3 %%-sign options");
1349 for (
int i = 0; i < tok; i++) {
1350 if (toks[i] == NULL)
1354 pl->filename_parts[i] = toks[i];
1356 pl->filename_part_cnt = tok;
1360 for (
int x = 0; x <
MAX_TOKS; x++) {
1361 if (toks[x] != NULL)
1378 FatalError(
"A pcap-log instance is already active, only one can be enabled.");
1383 FatalError(
"Failed to allocate Memory for PcapLogData");
1387 if (pl->
h == NULL) {
1388 FatalError(
"Failed to allocate Memory for pcap header struct");
1405 pcre_timestamp_code =
1406 pcre2_compile((PCRE2_SPTR8)timestamp_pattern, PCRE2_ZERO_TERMINATED, 0, &en, &eo, NULL);
1407 if (pcre_timestamp_code == NULL) {
1408 PCRE2_UCHAR errbuffer[256];
1409 pcre2_get_error_message(en, errbuffer,
sizeof(errbuffer));
1411 "Failed to compile \"%s\" at offset %d: %s", timestamp_pattern, (
int)eo, errbuffer);
1413 pcre_timestamp_match = pcre2_match_data_create_from_pattern(pcre_timestamp_code, NULL);
1417 const char *filename = NULL;
1423 if (filename == NULL)
1426 if ((pl->prefix =
SCStrdup(filename)) == NULL) {
1434 const char *s_limit = NULL;
1436 if (s_limit != NULL) {
1438 SCLogError(
"Failed to initialize pcap output, invalid limit: %s", s_limit);
1442 SCLogInfo(
"pcap-log \"limit\" value of %"PRIu64
" assumed to be pre-1.2 "
1444 uint64_t size = pl->
size_limit * 1024 * 1024;
1447 FatalError(
"Fail to initialize pcap-log output, limit less than "
1448 "allowed minimum of %d bytes.",
1455 const char *s_mode = NULL;
1457 if (s_mode != NULL) {
1458 if (strcasecmp(s_mode,
"multi") == 0) {
1460 }
else if (strcasecmp(s_mode,
"normal") != 0) {
1461 FatalError(
"log-pcap: invalid mode \"%s\". Valid options: \"normal\""
1462 "or \"multi\" mode ",
1467 const char *s_dir = NULL;
1469 if (s_dir == NULL) {
1470 const char *log_dir = NULL;
1473 strlcpy(pl->dir, log_dir,
sizeof(pl->dir));
1478 s_dir,
sizeof(pl->dir));
1480 const char *log_dir = NULL;
1483 snprintf(pl->dir,
sizeof(pl->dir),
"%s/%s",
1487 struct stat stat_buf;
1488 if (stat(pl->dir, &stat_buf) != 0) {
1490 "supplied doesn't exist. Shutting down the engine",
1499 if (compression_str == NULL || strcmp(compression_str,
"none") == 0) {
1507 comp->pcap_buf_wrapper = NULL;
1509 }
else if (strcmp(compression_str,
"lz4") == 0) {
1519 SCLogError(
"SCMalloc failed: %s", strerror(errno));
1524 if (comp->pcap_buf_wrapper == NULL) {
1525 SCLogError(
"SCFmemopen failed: %s", strerror(errno));
1531 memset(&comp->lz4f_prefs,
'\0',
sizeof(comp->lz4f_prefs));
1532 comp->lz4f_prefs.frameInfo.blockSizeID = LZ4F_max4MB;
1533 comp->lz4f_prefs.frameInfo.blockMode = LZ4F_blockLinked;
1535 comp->lz4f_prefs.frameInfo.contentChecksumFlag = 1;
1537 comp->lz4f_prefs.frameInfo.contentChecksumFlag = 0;
1543 }
else if (lvl < 0) {
1549 comp->lz4f_prefs.compressionLevel = (int)lvl;
1553 LZ4F_errorCode_t errcode =
1554 LZ4F_createCompressionContext(&pl->compression.lz4f_context, 1);
1556 if (LZ4F_isError(errcode)) {
1557 SCLogError(
"LZ4F_createCompressionContext failed: %s", LZ4F_getErrorName(errcode));
1569 "lz4 output buffer.");
1576 pl->suffix =
".lz4";
1579 "in pcap-log, but suricata was not compiled with lz4 "
1581 PcapLogDataFree(pl);
1587 "compression format: %s",
1589 PcapLogDataFree(pl);
1593 SCLogInfo(
"Selected pcap-log compression method: %s",
1594 compression_str ? compression_str :
"none");
1597 if (s_conditional != NULL) {
1598 if (strcasecmp(s_conditional,
"alerts") == 0) {
1601 }
else if (strcasecmp(s_conditional,
"tag") == 0) {
1604 }
else if (strcasecmp(s_conditional,
"all") != 0) {
1605 FatalError(
"log-pcap: invalid conditional \"%s\". Valid options: \"all\", "
1606 "\"alerts\", or \"tag\" mode ",
1612 "Selected pcap-log conditional logging: %s", s_conditional ? s_conditional :
"all");
1615 if (ParseFilename(pl, filename) != 0)
1622 const char *max_number_of_files_s = NULL;
1624 if (max_number_of_files_s != NULL) {
1626 max_number_of_files_s) == -1) {
1628 "pcap-log output, invalid number of files limit: %s",
1629 max_number_of_files_s);
1631 }
else if (max_file_limit < 1) {
1632 FatalError(
"Failed to initialize pcap-log output, limit less than "
1633 "allowed minimum.");
1641 const char *ts_format = NULL;
1645 if (ts_format != NULL) {
1646 if (strcasecmp(ts_format,
"usec") == 0) {
1648 }
else if (strcasecmp(ts_format,
"sec") != 0) {
1649 SCLogError(
"log-pcap ts_format specified %s is invalid must be"
1650 " \"sec\" or \"usec\"",
1656 const char *use_stream_depth = NULL;
1660 if (use_stream_depth != NULL) {
1666 FatalError(
"log-pcap use_stream_depth specified is invalid must be");
1670 const char *honor_pass_rules = NULL;
1674 if (honor_pass_rules != NULL) {
1680 FatalError(
"log-pcap honor-pass-rules specified is invalid");
1689 if (
unlikely(output_ctx == NULL)) {
1690 FatalError(
"Failed to allocate memory for OutputCtx.");
1692 output_ctx->
data = pl;
1693 output_ctx->
DeInit = PcapLogFileDeInitCtx;
1696 result.
ctx = output_ctx;
1701 static void PcapLogFileDeInitCtx(
OutputCtx *output_ctx)
1703 if (output_ctx == NULL)
1712 PcapLogDataFree(pl);
1715 pcre2_code_free(pcre_timestamp_code);
1716 pcre2_match_data_free(pcre_timestamp_match);
1752 char file[PATH_MAX] =
"";
1757 ret = snprintf(file,
sizeof(file),
"%s.%" PRIu32
"%s", pl->prefix,
1760 ret = snprintf(file,
sizeof(file),
"%s.%" PRIu32
".%" PRIu32
"%s", pl->prefix,
1763 if (ret < 0 || (
size_t)ret >= PATH_MAX) {
1768 if (pl->filename_part_cnt > 0) {
1771 for (
int i = 0; i < pl->filename_part_cnt; i++) {
1772 if (pl->filename_parts[i] == NULL ||strlen(pl->filename_parts[i]) == 0)
1776 if (pl->filename_parts[i][0] ==
'%') {
1778 if (strlen(pl->filename_parts[i]) < 2)
1781 switch(pl->filename_parts[i][1]) {
1783 snprintf(
str,
sizeof(
str),
"%u", pl->thread_number);
1788 snprintf(
str,
sizeof(
str),
"%"PRIu64, (uint64_t)thread_id);
1796 snprintf(
str,
sizeof(
str),
"%" PRIu32
".%" PRIu32,
1804 strlcat(file, pl->filename_parts[i],
sizeof(file));
1807 strlcat(file, pl->suffix,
sizeof(file));
1812 ret = snprintf(file,
sizeof(file),
"%s.%u.%" PRIu32
"%s", pl->prefix,
1815 ret = snprintf(file,
sizeof(file),
"%s.%u.%" PRIu32
".%" PRIu32
"%s", pl->prefix,
1819 if (ret < 0 || (
size_t)ret >= PATH_MAX) {
1826 if (
PathMerge(path, PATH_MAX, pl->dir, file) < 0) {
1832 SCLogError(
"Error allocating memory. For filename");
1845 PcapFileNameFree(pf);
1858 static int profiling_pcaplog_enabled = 0;
1859 static int profiling_pcaplog_output_to_file = 0;
1860 static char *profiling_pcaplog_file_name = NULL;
1861 static const char *profiling_pcaplog_file_mode =
"a";
1863 static void FormatNumber(uint64_t num,
char *
str,
size_t size)
1866 snprintf(
str, size,
"%"PRIu64, num);
1867 else if (num < 1000000UL)
1868 snprintf(
str, size,
"%3.1fk", (
float)num/1000UL);
1869 else if (num < 1000000000UL)
1870 snprintf(
str, size,
"%3.1fm", (
float)num/1000000UL);
1872 snprintf(
str, size,
"%3.1fb", (
float)num/1000000000UL);
1877 char ticks_str[32] =
"n/a";
1878 char cnt_str[32] =
"n/a";
1879 char avg_str[32] =
"n/a";
1881 FormatNumber((uint64_t)
p->cnt, cnt_str,
sizeof(cnt_str));
1882 FormatNumber((uint64_t)
p->total, ticks_str,
sizeof(ticks_str));
1883 if (
p->cnt &&
p->total)
1884 FormatNumber((uint64_t)(
p->total/
p->cnt), avg_str,
sizeof(avg_str));
1886 fprintf(fp,
"%-28s %-10s %-10s %-10s\n",
name, cnt_str, avg_str, ticks_str);
1889 static void ProfileReport(FILE *fp,
const PcapLogData *pl)
1894 ProfileReportPair(fp,
"rotate (incl open/close)", &pl->
profile_rotate);
1900 static void FormatBytes(uint64_t num,
char *
str,
size_t size)
1903 snprintf(
str, size,
"%"PRIu64, num);
1904 else if (num < 1048576UL)
1905 snprintf(
str, size,
"%3.1fKiB", (
float)num/1000UL);
1906 else if (num < 1073741824UL)
1907 snprintf(
str, size,
"%3.1fMiB", (
float)num/1000000UL);
1909 snprintf(
str, size,
"%3.1fGiB", (
float)num/1000000000UL);
1912 static void DoDump(
const PcapLogData *pl, FILE *fp)
1915 fprintf(fp,
"\n\nOperation Cnt Avg ticks Total ticks\n");
1916 fprintf(fp,
"---------------------------- ---------- ---------- -----------\n");
1918 ProfileReport(fp, pl);
1925 fprintf(fp,
"\nOverall: %"PRIu64
" bytes written, average %d bytes per write.\n",
1928 fprintf(fp,
" PCAP data structure overhead: %"PRIuMAX
" per write.\n",
1929 (uintmax_t)
sizeof(
struct pcap_pkthdr));
1934 fprintf(fp,
" Size written: %s\n", bytes_str);
1937 uint64_t ticks_per_mib = 0, ticks_per_gib = 0;
1940 ticks_per_mib = total/mib;
1941 char ticks_per_mib_str[32] =
"n/a";
1942 if (ticks_per_mib > 0)
1943 FormatNumber(ticks_per_mib, ticks_per_mib_str,
sizeof(ticks_per_mib_str));
1944 fprintf(fp,
" Ticks per MiB: %s\n", ticks_per_mib_str);
1948 ticks_per_gib = total/gib;
1949 char ticks_per_gib_str[32] =
"n/a";
1950 if (ticks_per_gib > 0)
1951 FormatNumber(ticks_per_gib, ticks_per_gib_str,
sizeof(ticks_per_gib_str));
1952 fprintf(fp,
" Ticks per GiB: %s\n", ticks_per_gib_str);
1957 if (profiling_pcaplog_enabled == 0)
1960 if (profiling_pcaplog_output_to_file == 1) {
1961 FILE *fp = fopen(profiling_pcaplog_file_name, profiling_pcaplog_file_mode);
1963 SCLogError(
"failed to open %s: %s", profiling_pcaplog_file_name, strerror(errno));
1977 profiling_pcaplog_enabled = 1;
1978 SCLogInfo(
"pcap-log profiling enabled");
1981 if (filename != NULL) {
1982 const char *log_dir;
1985 profiling_pcaplog_file_name =
SCMalloc(PATH_MAX);
1986 if (
unlikely(profiling_pcaplog_file_name == NULL)) {
1990 snprintf(profiling_pcaplog_file_name, PATH_MAX,
"%s/%s", log_dir, filename);
1994 profiling_pcaplog_file_mode =
"a";
1996 profiling_pcaplog_file_mode =
"w";
1999 profiling_pcaplog_output_to_file = 1;
2000 SCLogInfo(
"pcap-log profiling output goes to %s (mode %s)",
2001 profiling_pcaplog_file_name, profiling_pcaplog_file_mode);