]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
pcap-file: improve setvbuf implementation
authorVictor Julien <vjulien@oisf.net>
Tue, 9 Jul 2024 07:12:46 +0000 (09:12 +0200)
committerVictor Julien <victor@inliniac.net>
Fri, 30 Aug 2024 13:18:59 +0000 (15:18 +0200)
Make optional through `pcap-file.buffer-size` config option.

Make sure to check through configure.

Ticket: #7155.

configure.ac
src/source-pcap-file-directory-helper.c
src/source-pcap-file-helper.c
src/source-pcap-file-helper.h
src/source-pcap-file.c

index d19680e091d31a34c48b90faee2676ef34442ece..1bdf823506e6baef4961a7028848f43ac645d453 100644 (file)
     AC_CHECK_FUNCS([gethostname inet_ntoa uname])
     AC_CHECK_FUNCS([gettimeofday clock_gettime utime strptime tzset localtime_r])
     AC_CHECK_FUNCS([socket setenv select putenv dup2 endgrent endpwent atexit munmap])
-    AC_CHECK_FUNCS([setrlimit])
+    AC_CHECK_FUNCS([setrlimit setvbuf])
 
     AC_CHECK_FUNCS([fwrite_unlocked])
 
index 91e40f6e7a5d5ae846ae06d5774c7f034e317923..a963f2e4881688afe7e691bc3a4a3e9420632647 100644 (file)
@@ -45,6 +45,8 @@ static TmEcode PcapDirectoryPopulateBuffer(PcapFileDirectoryVars *ptv,
 static TmEcode PcapDirectoryDispatchForTimeRange(PcapFileDirectoryVars *pv,
                                                  struct timespec *older_than);
 
+extern PcapFileGlobalVars pcap_g;
+
 void GetTime(struct timespec *tm)
 {
     struct timeval now;
@@ -414,7 +416,8 @@ TmEcode PcapDirectoryDispatchForTimeRange(PcapFileDirectoryVars *pv,
             } else {
                 SCLogDebug("Processing file %s", current_file->filename);
 
-                PcapFileFileVars *pftv = SCCalloc(1, sizeof(PcapFileFileVars));
+                const size_t toalloc = sizeof(PcapFileFileVars) + pcap_g.read_buffer_size;
+                PcapFileFileVars *pftv = SCCalloc(1, toalloc);
                 if (unlikely(pftv == NULL)) {
                     SCLogError("Failed to allocate PcapFileFileVars");
                     SCReturnInt(TM_ECODE_FAILED);
index a93a9558313eb63cb6572354dda390d43ee06904..c7303fa3995097eb85329cedaa7377e0d7b4b123 100644 (file)
@@ -208,10 +208,15 @@ TmEcode InitPcapFile(PcapFileFileVars *pfv)
         SCReturnInt(TM_ECODE_FAILED);
     }
 
-    errno = 0;
-    if (setvbuf(pcap_file(pfv->pcap_handle), pfv->buffer, _IOFBF, sizeof(pfv->buffer)) < 0) {
-        SCLogWarning("Failed to setvbuf on PCAP file handle: %s", strerror(errno));
+#if defined(HAVE_SETVBUF) && !defined(OS_WIN32)
+    if (pcap_g.read_buffer_size > 0) {
+        errno = 0;
+        if (setvbuf(pcap_file(pfv->pcap_handle), pfv->buffer, _IOFBF, pcap_g.read_buffer_size) <
+                0) {
+            SCLogWarning("Failed to setvbuf on PCAP file handle: %s", strerror(errno));
+        }
     }
+#endif
 
     if (pfv->shared != NULL && pfv->shared->bpf_string != NULL) {
         SCLogInfo("using bpf-filter \"%s\"", pfv->shared->bpf_string);
index c2d9ed6f2020dce6b51571f2fcbb15bdf0e4c5f8..3068c14e3cf67ad36b37aa76e281e31a26bdabf0 100644 (file)
@@ -32,6 +32,7 @@ typedef struct PcapFileGlobalVars_ {
     ChecksumValidationMode conf_checksum_mode;
     ChecksumValidationMode checksum_mode;
     SC_ATOMIC_DECLARE(unsigned int, invalid_checksums);
+    uint32_t read_buffer_size;
 } PcapFileGlobalVars;
 
 /**
@@ -81,7 +82,11 @@ typedef struct PcapFileFileVars_
     struct pcap_pkthdr *first_pkt_hdr;
     struct timeval first_pkt_ts;
 
-    char buffer[131072];
+    /** flex array member for the libc io read buffer. Size controlled by
+     * PcapFileGlobalVars::read_buffer_size. */
+#if defined(HAVE_SETVBUF) && !defined(OS_WIN32)
+    char buffer[];
+#endif
 } PcapFileFileVars;
 
 /**
index e16970f3f1ee46ebce7bf0ca58e00c004ef99e92..85f992d5ca960db0bf29c868611224fc77143a0d 100644 (file)
@@ -32,6 +32,7 @@
 #include "runmode-unix-socket.h"
 #include "suricata.h"
 #include "conf.h"
+#include "util-misc.h"
 
 extern uint32_t max_pending_packets;
 PcapFileGlobalVars pcap_g;
@@ -136,10 +137,33 @@ void TmModuleDecodePcapFileRegister (void)
     tmm_modules[TMM_DECODEPCAPFILE].flags = TM_FLAG_DECODE_TM;
 }
 
+#define PCAP_FILE_BUFFER_SIZE_DEFAULT 131072U   // 128 KiB
+#define PCAP_FILE_BUFFER_SIZE_MIN     4096U     // 4 KiB
+#define PCAP_FILE_BUFFER_SIZE_MAX     67108864U // 64MiB
+
 void PcapFileGlobalInit(void)
 {
     memset(&pcap_g, 0x00, sizeof(pcap_g));
     SC_ATOMIC_INIT(pcap_g.invalid_checksums);
+
+#if defined(HAVE_SETVBUF) && !defined(OS_WIN32)
+    pcap_g.read_buffer_size = PCAP_FILE_BUFFER_SIZE_DEFAULT;
+
+    const char *str = NULL;
+    if (ConfGet("pcap-file.buffer-size", &str) == 1) {
+        uint32_t value = 0;
+        if (ParseSizeStringU32(str, &value) < 0) {
+            SCLogWarning("failed to parse pcap-file.buffer-size %s", str);
+        }
+        if (value >= PCAP_FILE_BUFFER_SIZE_MIN && value <= PCAP_FILE_BUFFER_SIZE_MAX) {
+            SCLogInfo("Pcap-file will use %u buffer size", value);
+            pcap_g.read_buffer_size = value;
+        } else {
+            SCLogWarning("pcap-file.buffer-size value of %u is invalid. Valid range is %u-%u",
+                    value, PCAP_FILE_BUFFER_SIZE_MIN, PCAP_FILE_BUFFER_SIZE_MAX);
+        }
+    }
+#endif
 }
 
 TmEcode PcapFileExit(TmEcode status, struct timespec *last_processed)
@@ -250,7 +274,8 @@ TmEcode ReceivePcapFileThreadInit(ThreadVars *tv, const void *initdata, void **d
 
     if(directory == NULL) {
         SCLogDebug("argument %s was a file", (char *)initdata);
-        PcapFileFileVars *pv = SCCalloc(1, sizeof(PcapFileFileVars));
+        const size_t toalloc = sizeof(PcapFileFileVars) + pcap_g.read_buffer_size;
+        PcapFileFileVars *pv = SCCalloc(1, toalloc);
         if (unlikely(pv == NULL)) {
             SCLogError("Failed to allocate file vars");
             CleanupPcapFileThreadVars(ptv);