pcap-file: skip setvbuf on non-seekable streams

Reading a pcap from /dev/stdin or a named pipe currently fails with "failed to get first packet timestamp. pcap_next_ex(): -1" because InitPcapFile calls setvbuf on the FILE* underlying the pcap handle after libpcap has already consumed the pcap header. On a non-seekable fd glibc cannot recover from that and the next read returns -1.

Detect non-regular files via fstat and skip setvbuf in that case so the read keeps working on pipes, fifos and stdin.

Accept pcap-file.buffer-size values of 0, which disables setvbuf buffering as an explicit opt-out, or PCAP_FILE_BUFFER_SIZE_MIN (4 KiB) to PCAP_FILE_BUFFER_SIZE_MAX (64 MiB). Treat any non-zero setvbuf return value as an error, not just negative values.

When pcap-file.buffer-size fails to parse, retain the default buffer size instead of falling through and setting it to 0. The branches are now mutually exclusive so only one of the parse-error, accepted, or out-of-range messages is logged.

Update the user guide: --pcap-file-buffer-size now documents valid values of 0 (disables setvbuf buffering) or 4 KiB to 64 MiB, and pcap-file.rst notes that 0 is the opt-out for non-seekable sources such as stdin and named pipes.
Bug: #8464.
pull/15636/head
Samaresh Kumar Singh 2 months ago committed by Victor Julien
parent df353242bd
commit 565e138754

@ -33,6 +33,10 @@ This can improve performance, especially for large files.
The size can be specified through the command line option, see
:ref:`--pcap-file-buffer-size <cmdline-option-pcap-file-buffer-size>`
Setting ``buffer-size`` to ``0`` disables ``setvbuf`` buffering. This is the
explicit opt-out for non-seekable sources such as ``/dev/stdin`` or named
pipes, where buffering the underlying file descriptor is not supported.
Directory-related options
-------------------------

@ -103,7 +103,8 @@
.. option:: --pcap-file-buffer-size <value>
Set read buffer size using ``setvbuf`` to speed up pcap reading. Valid values
are 4 KiB to 64 MiB. Default value is 128 KiB. Supported on Linux only.
are 0, which disables ``setvbuf`` buffering, or 4 KiB to 64 MiB. Default
value is 128 KiB. Supported on Linux only.
.. option:: -i <interface>

@ -271,10 +271,16 @@ TmEcode InitPcapFile(PcapFileFileVars *pfv)
#if defined(HAVE_SETVBUF) && defined(OS_LINUX)
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));
struct stat sb;
int fd = fileno(pcap_file(pfv->pcap_handle));
if (fd >= 0 && fstat(fd, &sb) == 0 && !S_ISREG(sb.st_mode)) {
SCLogInfo("%s: skipping setvbuf, underlying fd is not a regular file", pfv->filename);
} else {
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

@ -1,4 +1,4 @@
/* Copyright (C) 2007-2016 Open Information Security Foundation
/* Copyright (C) 2007-2026 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
@ -158,13 +158,19 @@ void PcapFileGlobalInit(void)
if (SCConfGetNonNull("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);
SCLogWarning("failed to parse pcap-file.buffer-size %s; keeping default %u", str,
PCAP_FILE_BUFFER_SIZE_DEFAULT);
} else if (value == 0 ||
(value >= PCAP_FILE_BUFFER_SIZE_MIN && value <= PCAP_FILE_BUFFER_SIZE_MAX)) {
if (value == 0) {
SCLogInfo("Pcap-file buffering disabled");
} else {
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",
SCLogWarning("pcap-file.buffer-size value of %u is invalid. Valid values are 0 to "
"disable buffering, or %u-%u",
value, PCAP_FILE_BUFFER_SIZE_MIN, PCAP_FILE_BUFFER_SIZE_MAX);
}
}

Loading…
Cancel
Save