Import libpcap 1.10.6

This commit is contained in:
Joseph Mingrone 2026-01-07 12:56:48 -04:00
parent 025be3f592
commit 0a1fbf4c24
No known key found for this signature in database
GPG key ID: 36A40C83B0D6EF9E
69 changed files with 3222 additions and 1406 deletions

107
CHANGES
View file

@ -1,3 +1,110 @@
Tuesday, December 30, 2025 / The Tcpdump Group
Summary for 1.10.6 libpcap release
General:
Fix "tcpdump -i <n>" for something-only libpcap builds.
gencode: Fix an undefined behavior in gen_mcode().
gencode: Add a missing free() in gen_scode().
Remove "DLT_" from the descriptions of two dlt_choices[] entries.
Report the size of time_t in the version string.
Validate remote capture source strings better.
CVE-2025-11961: Fix OOBR and OOBW in pcap_ether_aton().
Source code:
Remove some unneeded includes.
pcapint_find_function() changed to return "void *" to avoid
warnings.
Clean up code that computes the length of a netmask.
Mind netmap support in pcap_lib_version().
Link-layer types:
Add LINKTYPE_ETW/DLT_ETW.
Add LINKTYPE_NETANALYZER_NG/DLT_NETANALYZER_NG (pull request
#1008).
Add LINKTYPE_ZBOSS_NCP/DLT_ZBOSS_NCP.
Add LINKTYPE_USB_2_0_LOW_SPEED/DLT_USB_2_0_LOW_SPEED,
LINKTYPE_USB_2_0_FULL_SPEED/DLT_USB_2_0_FULL_SPEED,
LINKTYPE_USB_2_0_HIGH_SPEED/DLT_USB_2_0_HIGH_SPEED
Add LINKTYPE_AUERSWALD_LOG/DLT_AUERSWALD_LOG.
Add LINKTYPE_ZWAVE_TAP/DLT_ZWAVE_TAP.
Add LINKTYPE_SILABS_DEBUG_CHANNEL/DLT_SILABS_DEBUG_CHANNEL.
Add LINKTYPE_FIRA_UCI/DLT_FIRA_UCI.
Rename LINKTYPE_IPMB_LINUX/DLT_IPMB_LINUX to
LINKTYPE_I2C_LINUX/DLT_I2C_LINUX, as it's really just an
encapsulation of I2C, and is also being used for HDMI DDC.
Keep DLT_IPMB_LINUX around as a #define for backwards
compatibility.
Add LINKTYPE_MDB/DLT_MDB.
Add LINKTYPE_DECT_NR/DLT_DECT_NR.
Add LINKTYPE_EDK2_MM/DLT_EDK2_MM.
Add LINKTYPE_DEBUG_ONLY/DLT_DEBUG_ONLY.
Packet filtering:
Make the chunk allocator's alignment more general and
platform-independent.
IEEE 802.11: Fix three undefined behaviors in grammar.y.
Fix IPv4 multicast filtering to only include 224.0.0.0/4.
Fix "(arp|rarp) host NAME" to ignore IPv6 quietly.
Fix ARCnet address parsing.
Linux:
Fix check for mac80211 phydev.
Don't create monitor-mode interface if we're capturing on one.
Expand the table of DSA tag types to include all current types.
Fix an error message when deleting a monN interface.
Fix returning PCAP_ERROR_RFMON_NOTSUP with libnl.
Fix the error message when capure permission is denied.
Fix the error message if PF_PACKET sockets aren't supported.
Fix a file descriptor leak in an error case (pull request #1537).
Handle errors better when checking for a DSA-tagged interface.
Use DLT_DEBUG_ONLY for DSA tags that do not [yet] have a better support.
FreeBSD:
Fix detection and enabling of zero-copy support.
Fix errors in the zero-copy code.
Solaris:
Fix not to ignore logical interfaces in fad-gifc.c and
fad-glifc.c.
Fix attempts to open all-numeric device names with DLPI to
return "no such device".
Fix error returns and messages when an interface has no DLPI
device.
Return all interfaces in pcap_findalldevs() even if they can't be
opened.
HP-UX:
Fix attempts to open all-numeric device names to return
"no such device".
Fix error message if there's no /dev/dlpi device.
Return all interfaces in pcap_findalldevs() even if they can't be
opened.
Windows:
Fix filtering for VLAN-tagged frames.
Add support for Npcap's nanosecond-resolution time stamps in
captures.
CVE-2025-11964: Fix a bug in error message character encoding mapping
from UTF-16 to UTF-8.
Check at create time whether the NPF driver supports nanosecond
precision.
D-Bus:
Fix message leak.
Capture file writing:
Don't close the output stream if it's stdout, just flush it.
Documentation:
Explicitly document that closing a pcap_t for a savefile opened
with pcap_fopen_offline() will close the standard I/O stream.
Building and testing:
Makefile.in: Include instrument-functions.c in the release tarball.
CMake: Fix libnl usage with pkg-config.
CMake: Fix build with CMake 3.31.
CI: Report CMake version in builds.
CI: Visual Studio 2022 builds added, including ARM64 builds;
Visual Studio 2015 builds dropped.
Don't build with sslutils.c if we don't have a TLS library.
Build on Windows with a newer version of OpenSSL.
CMake: generalize handling of non-x86 Windows architectures.
CI: use the -A flag for all Visual Studio generators.
Remove the fuzzing props from the release tarball.
Autoconf: Use AC_SYS_YEAR2038_RECOMMENDED when possible if the
environment variable BUILD_YEAR2038 = yes (via autogen.sh)
DPDK: don't enable it by default.
Update Npcap SDK to 1.15.
autogen.sh: Allow to configure Autoconf warnings.
autogen.sh: Delete all trailing blank lines at end of configure.
Friday, August 30, 2024 / The Tcpdump Group
Summary for 1.10.5 libpcap release
Source code:

View file

@ -13,14 +13,21 @@ else(WIN32)
# on a "long-term support" version # of some OS and that
# version supplies an older version of CMake;
#
# otherwise, require 3.5, so we don't get messages warning
# that support for versions of CMake lower than 3.5 is
# otherwise, if it's a version less than 3.10, require only
# 3.5, just in case somebody is configuring with CMake
# on a "long-term support" version # of some OS and that
# version supplies an older version of CMake;
#
# otherwise, require 3.10, so we don't get messages warning
# that support for versions of CMake lower than 3.10 is
# deprecated.
#
if(CMAKE_VERSION VERSION_LESS "3.5")
cmake_minimum_required(VERSION 2.8.12)
else()
elseif(CMAKE_VERSION VERSION_LESS "3.10")
cmake_minimum_required(VERSION 3.5)
else()
cmake_minimum_required(VERSION 3.10)
endif()
endif(WIN32)
@ -506,7 +513,13 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
endif()
option(DISABLE_BLUETOOTH "Disable Bluetooth sniffing support" OFF)
option(DISABLE_NETMAP "Disable netmap support" OFF)
option(DISABLE_DPDK "Disable DPDK support" OFF)
#
# Require that DPDK support be explicitly enabled, as the code is
# immensely hard to keep compiling for every random API change
# the DPDK folks make.
#
set(DISABLE_DPDK ON)
#
# We don't support D-Bus sniffing on macOS; see
@ -578,6 +591,7 @@ include_directories(
include(CheckFunctionExists)
include(CMakePushCheckState)
include(CheckSymbolExists)
include(CheckIncludeFile)
if(WIN32)
@ -595,8 +609,11 @@ if(WIN32)
#
cmake_push_check_state()
set(CMAKE_REQUIRED_LIBRARIES ${Packet_LIBRARIES})
set(CMAKE_REQUIRED_INCLUDES ${Packet_INCLUDE_DIRS})
check_function_exists(PacketIsLoopbackAdapter HAVE_PACKET_IS_LOOPBACK_ADAPTER)
check_function_exists(PacketGetTimestampModes HAVE_PACKET_GET_TIMESTAMP_MODES)
check_function_exists(PacketGetInfo HAVE_PACKET_GET_INFO)
check_include_file(npcap-bpf.h HAVE_NPCAP_BPF_H)
cmake_pop_check_state()
endif(Packet_FOUND)
@ -634,7 +651,6 @@ endif(USE_STATIC_RT)
# Detect available platform features
###################################################################
include(CheckIncludeFile)
include(CheckIncludeFiles)
include(CheckStructHasMember)
include(CheckTypeSize)
@ -1244,6 +1260,19 @@ if(NOT WIN32)
endif()
endif()
#
# Find and print the size of time_t.
#
cmake_push_check_state()
set(CMAKE_EXTRA_INCLUDE_FILES time.h)
check_type_size("time_t" SIZEOF_TIME_T)
if(SIZEOF_TIME_T EQUAL 4)
message(STATUS "32-bit time_t")
elseif(SIZEOF_TIME_T EQUAL 8)
message(STATUS "64-bit time_t")
endif()
cmake_pop_check_state()
if(INET6)
message(STATUS "Support IPv6")
endif(INET6)
@ -1984,6 +2013,7 @@ else(WIN32)
#
check_include_file(sys/bufmod.h HAVE_SYS_BUFMOD_H)
check_include_file(sys/dlpi_ext.h HAVE_SYS_DLPI_EXT_H)
check_include_file(zone.h HAVE_ZONE_H)
#
# Checks to see if Solaris has the public libdlpi(3LIB) library.
@ -2025,12 +2055,6 @@ else(WIN32)
check_type_size(dl_passive_req_t DL_PASSIVE_REQ_T)
cmake_pop_check_state()
elseif(PCAP_TYPE STREQUAL "linux")
#
# Do we have the wireless extensions?
# linux/wireless.h requires sys/socket.h.
#
check_include_files("sys/socket.h;linux/wireless.h" HAVE_LINUX_WIRELESS_H)
#
# Do we have libnl?
# We only want version 3. Version 2 was, apparently,
@ -2043,6 +2067,8 @@ else(WIN32)
if(BUILD_WITH_LIBNL)
pkg_check_modules(LIBNL libnl-genl-3.0)
if(LIBNL_FOUND)
set(HAVE_LIBNL TRUE)
include_directories(${LIBNL_INCLUDE_DIRS})
set(PCAP_LINK_LIBRARIES ${LIBNL_LIBRARIES} ${PCAP_LINK_LIBRARIES})
#
@ -2698,7 +2724,10 @@ if(ENABLE_REMOTE)
check_struct_has_member("struct msghdr" msg_flags "ftmacros.h;sys/socket.h" HAVE_STRUCT_MSGHDR_MSG_FLAGS)
cmake_pop_check_state()
set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C}
pcap-new.c pcap-rpcap.c rpcap-protocol.c sockutils.c sslutils.c)
pcap-new.c pcap-rpcap.c rpcap-protocol.c sockutils.c)
if(OPENSSL_FOUND)
set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} sslutils.c)
endif()
endif(ENABLE_REMOTE)
###################################################################
@ -2917,7 +2946,6 @@ endif()
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/scanner.c ${CMAKE_CURRENT_BINARY_DIR}/scanner.h
SOURCE ${pcap_SOURCE_DIR}/scanner.l
COMMAND ${LEX_EXECUTABLE} -P pcap_ --header-file=scanner.h --nounput -o${CMAKE_CURRENT_BINARY_DIR}/scanner.c ${pcap_SOURCE_DIR}/scanner.l
DEPENDS ${pcap_SOURCE_DIR}/scanner.l
)
@ -2992,7 +3020,6 @@ message(STATUS "Parser generator: ${YACC_EXECUTABLE}")
#
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/grammar.c ${CMAKE_CURRENT_BINARY_DIR}/grammar.h
SOURCE ${pcap_BINARY_DIR}/grammar.y
COMMAND ${YACC_EXECUTABLE} -p pcap_ -o ${CMAKE_CURRENT_BINARY_DIR}/grammar.c -d ${pcap_BINARY_DIR}/grammar.y
DEPENDS ${pcap_BINARY_DIR}/grammar.y
)

13
CREDITS
View file

@ -14,6 +14,7 @@ Additional people who have contributed patches (in alphabetical order):
Alexander Galanin <al at galanin dot nnov dot ru>
Alexander 'Leo' Bergolth <Leo dot Bergolth at wu-wien dot ac dot at>
Alexey Kuznetsov <kuznet at ms2 dot inr dot ac dot ru>
Alexey Vishnyakov <vishnya at ispras dot ru>
Alex Smith <44322503+MadAlexUK at users dot noreply dot github dot com>
Alfredo Alvarez Fernandez <alfredoalvarezernandez at gmail dot com>
Ali Abdulkadir <autostart dot ini at gmail dot com>
@ -34,6 +35,7 @@ Additional people who have contributed patches (in alphabetical order):
Assar Westerlund <assar at sics dot se>
Atzm Watanabe <atzm at atzm dot org>
Baptiste Peugnez <baptiste dot peugnez at cea dot fr>
Barnabás Pőcze <pobrn at protonmail dot com>
Baruch Siach <baruch at tkos dot co dot il>
Bill Parker <wp02855 at gmail dot com>
Biswapriyo Nath <nathbappai at gmail dot com>
@ -78,6 +80,7 @@ Additional people who have contributed patches (in alphabetical order):
Eli Schwartz <eschwartz93 at gmail dot com>
Eric Anderson <anderse at hpl dot hp dot com>
Erik de Castro Lopo <erik dot de dot castro dot lopo at sensorynetworks dot com>
Eugene Exarevsky <eugene dot exarevsky at dsr-corporation dot com>
Fedor Sakharov <fedor dot sakharov at gmail dot com>
Felix Janda <felix dot janda at posteo dot de>
Felix Obenhuber <felix at obenhuber dot de>
@ -85,6 +88,7 @@ Additional people who have contributed patches (in alphabetical order):
Florent Drouin <Florent dot Drouin at alcatel-lucent dot fr>
Florian Fainelli <f dot fainelli at gmail dot com>
François Revol <revol at free dot fr>
Frank Gorgas-Waller <frank dot gorgas-waller at auerswald dot de>
Franz Schaefer <schaefer at mond dot at>
frederich <frederich at sourceforge dot net>
Fulko Hew <fulko dot hew at gmail dot com>
@ -95,6 +99,7 @@ Additional people who have contributed patches (in alphabetical order):
George Neville-Neil <gnn at freebsd dot org>
Gerald Combs <gerald at zing dot org>
Gerard Garcia <nouboh at gmail dot com>
Gerd Hoffmann <kraxel at redhat dot com>
Gianluca Varenni <gianluca dot varenni at gmail dot com>
Gilbert Hoyek <gil_hoyek at hotmail dot com>
Gisle Vanem <gvanem at yahoo dot no>
@ -106,14 +111,17 @@ Additional people who have contributed patches (in alphabetical order):
Gustavo Zacarias <gustavo at zacarias dot com dot ar>
Hagen Paul Pfeifer <hagen at jauu dot net>
headshog <craaaaaachind at gmail dot com>
Henri Chataing <henrichataing at google dot com>
Henri Doreau <hdoreau at sourceforge dot net>
Hiroaki KAWAI <kawai at stratosphere dot co dot jp>
hopper-vul <hopper dot vul at gmail dot com>
Hyung Sik Yoon <hsyn at kr dot ibm dot com>
Ido Yariv <yarivido at gmail dot com>
Igor Khristophorov <igor at atdot dot org>
Jakub Sitnicki <jsitnicki at gmail dot com>
Jakub Zawadzki <darkjames at darkjames dot pl>
James Ko <jck at exegin dot com>
Jan Adam <jadam at hilscher dot com>
Jan-Philip Velders <jpv at veldersjes dot net>
Jason R. Thorpe <thorpej at netbsd dot org>
Javier Achirica <achirica at ttd dot net>
@ -124,6 +132,7 @@ Additional people who have contributed patches (in alphabetical order):
Jesper Dangaard Brouer <hawk at comx dot dk>
Jesper Peterson <jesper at endace dot com>
Jesse Gross <jesse at nicira dot com>
Jessica Clarke <jrtc27 at jrtc27 dot com>
JHA <jon dot anderson at oracle dot com>
jingyu yang <jingleyang at users dot noreply dot github dot com>
Jiri Slaby <jirislaby at gmail dot com>
@ -131,6 +140,7 @@ Additional people who have contributed patches (in alphabetical order):
Joel <82591719+joelg989 at users dot noreply dot github dot com>
Joerg Mayer <jmayer at loplof dot de>
John Bankier <jbankier at rainfinity dot com>
John Thacker <johnthacker at gmail dot com>
Jon Lindgren <jonl at yubyub dot net>
Jon Smirl <jonsmirl at gmail dot com>
Jorge Boncompte [DTI2] <jorge at dti2 dot net>
@ -165,6 +175,7 @@ Additional people who have contributed patches (in alphabetical order):
Mark Pizzolato <List-tcpdump-workers at subscriptions dot pizzolato dot net>
Markus Mayer <markus_mayer at sourceforge dot net>
Martin Husemann <martin at netbsd dot org>
Martin Kaiser <martin at kaiser dot cx>
Márton Németh <nm127 at freemail dot hu>
Matias Karhumaa <matias dot karhumaa at gmail dot com>
Matt Eaton <agnosticdev at gmail dot com>
@ -183,6 +194,7 @@ Additional people who have contributed patches (in alphabetical order):
Milosz Kaniewski <milosz dot kaniewski at gmail dot com>
Miroslav Lichvar <mlichvar at redhat dot com>
Monroe Williams <monroe at pobox dot com>
mooon04 <mirae dot kim040506 at gmail dot com>
Myricom Help <myri at users dot noreply dot github dot com>
Nan Xiao <nan at chinadtrace dot org>
nic-kaczinsky <68271784+nic-kaczinsky at users dot noreply dot github dot com>
@ -240,6 +252,7 @@ Additional people who have contributed patches (in alphabetical order):
Stefan Hudson <hudson at mbay dot net>
Stephen Donnelly <stephen at endace dot com>
Steve Karg <skarg at users dot sourceforge dot net>
Stig Bjørlykke <stig at bjorlykke dot org>
stubbfel <stubbfel at gmail dot com>
Takashi Yamamoto <yamt at mwd dot biglobe dot ne dot jp>
Tanaka Shin-ya <zstanaka at archer dot livedoor dot com>

View file

@ -8,6 +8,10 @@ To build libpcap with the configure script and `make`:
run `./autogen.sh` (a shell script). The autogen.sh script will
build the `configure` and `config.h.in` files.
* If you build on a Linux 32-bit system, with Autoconf version >= 2.72
and GNU C Library version >= 2.34, run `export BUILD_YEAR2038=yes`
before running `./autogen.sh` to build with 64-bit time_t (Y2038-safe).
On some system, you may need to set the `AUTORECONF` variable, like:
`AUTORECONF=autoreconf-2.69 ./autogen.sh`
to select the `autoreconf` version you want to use.

View file

@ -291,6 +291,7 @@ EXTRA_DIST = \
fad-glifc.c \
grammar.y.in \
install-sh \
instrument-functions.c \
lbl/os-aix4.h \
lbl/os-aix7.h \
lbl/os-hpux11.h \
@ -402,14 +403,6 @@ EXTRA_DIST = \
testprogs/filtertest.c \
testprogs/findalldevstest.c \
testprogs/findalldevstest-perf.c \
testprogs/fuzz/CMakeLists.txt \
testprogs/fuzz/fuzz_both.c \
testprogs/fuzz/fuzz_both.options \
testprogs/fuzz/fuzz_filter.c \
testprogs/fuzz/fuzz_filter.options \
testprogs/fuzz/fuzz_pcap.c \
testprogs/fuzz/fuzz_pcap.options \
testprogs/fuzz/onefile.c \
testprogs/nonblocktest.c \
testprogs/opentest.c \
testprogs/reactivatetest.c \
@ -417,6 +410,7 @@ EXTRA_DIST = \
testprogs/threadsignaltest.c \
testprogs/unix.h \
testprogs/valgrindtest.c \
testprogs/versiontest.c \
testprogs/visopts.py \
testprogs/writecaptest.c
@ -858,7 +852,7 @@ releasetar:
tar xf -) && \
echo "No $$TAG tag. Archive build from HEAD."; \
fi && \
(cd "$$TAG" && "$${AUTORECONF:-autoreconf}" && rm -rf autom4te.cache) && \
(cd "$$TAG" && ./autogen.sh && rm -rf autom4te.cache) && \
tar cf "$$DIR/$$TAG".tar "$$TAG" && \
rm -f "$$DIR/$$TAG".tar.gz && \
gzip --best "$$DIR/$$TAG".tar && \

View file

@ -1 +1 @@
1.10.5
1.10.6

11
aclocal.m4 vendored
View file

@ -825,6 +825,11 @@ dnl os-proto.h (symlinked)
dnl
AC_DEFUN(AC_LBL_DEVEL,
[rm -f os-proto.h
#
# MKDEP defaults to no-op (":") if we don't test whether the compiler
# supports generating dependencies
#
MKDEP=:
if test "${LBL_CFLAGS+set}" = set; then
$1="$$1 ${LBL_CFLAGS}"
fi
@ -901,14 +906,16 @@ testme(unsigned short a)
# .devel file; why should the ABI for which we produce code
# depend on .devel?
#
AC_MSG_CHECKING([whether to use an os-proto.h header])
os=`echo $host_os | sed -e 's/\([[0-9]][[0-9]]*\)[[^0-9]].*$/\1/'`
name="lbl/os-$os.h"
if test -f $name ; then
AC_MSG_RESULT([yes, at "$name"])
ln -s $name os-proto.h
AC_DEFINE(HAVE_OS_PROTO_H, 1,
[if there's an os_proto.h for this platform, to use additional prototypes])
[if there's an os-proto.h for this platform, to use additional prototypes])
else
AC_MSG_WARN(can't find $name)
AC_MSG_RESULT([no])
fi
fi])

View file

@ -1,6 +1,7 @@
#!/bin/sh -e
: "${AUTORECONF:=autoreconf}"
: "${BUILD_YEAR2038:=no}"
AUTORECONFVERSION=`$AUTORECONF --version 2>&1 | grep "^autoreconf" | sed 's/.*) *//'`
@ -21,5 +22,43 @@ if [ "$maj" = "" ] || [ "$min" = "" ] || \
exit 1
fi
# On Linux, if Autoconf version >= 2.72 and GNU C Library version >= 2.34,
# s/AC_SYS_LARGEFILE/AC_SYS_YEAR2038_RECOMMENDED/ to ensure time_t
# is Y2038-safe.
if [ "$BUILD_YEAR2038" = yes ] && [ "`uname -s`" = Linux ]; then
if [ "$maj" -gt 2 ] || { [ "$maj" -eq 2 ] && [ "$min" -ge 72 ]; }; then
GLIBC_VERSION=`ldd --version|head -1|grep GLIBC|sed 's/.* //'`
maj_glibc=`echo "$GLIBC_VERSION" | cut -d. -f1`
min_glibc=`echo "$GLIBC_VERSION" | cut -d. -f2`
echo "GNU C Library identification: $GLIBC_VERSION"
if [ "$maj_glibc" -gt 2 ] || { [ "$maj_glibc" -eq 2 ] && \
[ "$min_glibc" -ge 34 ]; }; then
CONFIGURE_AC_NEW="configure.ac.new$$"
sed 's/^AC_SYS_LARGEFILE/AC_SYS_YEAR2038_RECOMMENDED/' \
<configure.ac >"$CONFIGURE_AC_NEW"
cmp -s configure.ac "$CONFIGURE_AC_NEW" || \
cat "$CONFIGURE_AC_NEW" >configure.ac
rm -f "$CONFIGURE_AC_NEW"
echo 'Setup to ensure time_t is Y2038-safe.'
fi
fi
fi
echo "$AUTORECONF identification: $AUTORECONFVERSION"
"$AUTORECONF" -f
# configure.ac is an Autoconf 2.69 file, but it works as expected even with
# Autoconf 2.72. However, in Autoconf versions 2.70 and later obsolete
# construct warnings are enabled by default, which adds varying (depending on
# the branch) amount of noise to the build matrix output, so provide a means
# to silence that.
env ${AUTOCONF_WARNINGS:+WARNINGS="$AUTOCONF_WARNINGS"} "$AUTORECONF" -f
# Autoconf 2.71 adds a blank line after the final "exit 0" on Linux, but not
# on OpenBSD. Remove this difference to make it easier to compare the result
# of "make releasetar" across different platforms. From sed one-liners:
# "delete all trailing blank lines at end of file (works on all seds)". Don't
# use mktemp(1) because AIX does not have it.
CONFIGURE_NEW="configure.new$$"
sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' <configure >"$CONFIGURE_NEW"
cmp -s configure "$CONFIGURE_NEW" || cat "$CONFIGURE_NEW" >configure
rm -f "$CONFIGURE_NEW"

View file

@ -47,42 +47,27 @@
# (e.g cmake -DPacket_ROOT=C:\path\to\packet [...])
#
# The 64-bit Packet.lib is located under /x64
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
if(CMAKE_GENERATOR_PLATFORM STREQUAL "Win32")
#
# 32-bit x86; no need to look in subdirectories of the SDK's
# Lib directory for the libraries, as the libraries are in
# the Lib directory
#
else()
#
# Platform other than 32-bit x86.
#
# For the WinPcap and Npcap SDKs, the Lib subdirectory of the top-level
# directory contains 32-bit libraries; the 64-bit libraries are in the
# Lib/x64 directory.
# directory contains 32-bit x86 libraries; the libraries for other
# platforms are in subdirectories of the Lib directory whose names
# are the names of the supported platforms.
#
# The only way to *FORCE* CMake to look in the Lib/x64 directory
# without searching in the Lib directory first appears to be to set
# CMAKE_LIBRARY_ARCHITECTURE to "x64".
# The only way to *FORCE* CMake to look in the appropriate
# subdirectory of Lib for libraries without searching in the
# Lib directory first appears to be to set
# CMAKE_LIBRARY_ARCHITECTURE to the name of the subdirectory.
#
# In newer versions of CMake, CMAKE_LIBRARY_ARCHITECTURE is set according to
# the language, e.g., CMAKE_<LANG>_LIBRARY_ARCHITECTURE. So, set the new
# variable, CMAKE_C_LIBRARY_ARCHITECTURE, so that CMAKE_LIBRARY_ARCHITECTURE
# inherits the correct value.
#
set(archdetect_c_code "
#ifndef _M_ARM64
#error Not ARM64
#endif
int main() { return 0; }
")
file(WRITE "${CMAKE_BINARY_DIR}/archdetect.c" "${archdetect_c_code}")
try_compile(
IsArm64
"${CMAKE_BINARY_DIR}/archdetect"
"${CMAKE_BINARY_DIR}/archdetect.c"
)
if(IsArm64)
set(CMAKE_C_LIBRARY_ARCHITECTURE "ARM64")
set(CMAKE_LIBRARY_ARCHITECTURE "ARM64")
else()
set(CMAKE_C_LIBRARY_ARCHITECTURE "x64")
set(CMAKE_LIBRARY_ARCHITECTURE "x64")
endif()
set(CMAKE_LIBRARY_ARCHITECTURE "${CMAKE_GENERATOR_PLATFORM}")
endif()
# Find the header

View file

@ -93,9 +93,6 @@
/* Define to 1 if you have the <linux/usbdevice_fs.h> header file. */
#cmakedefine HAVE_LINUX_USBDEVICE_FS_H 1
/* Define to 1 if you have the <linux/wireless.h> header file. */
#cmakedefine HAVE_LINUX_WIRELESS_H 1
/* Define to 1 if you have the <memory.h> header file. */
#cmakedefine HAVE_MEMORY_H 1
@ -129,6 +126,9 @@
/* Define to 1 if Packet32 API (Npcap driver) is available */
#cmakedefine HAVE_PACKET32 1
/* Define to 1 if Npcap BPF extension definitions are available */
#cmakedefine HAVE_NPCAP_BPF_H 1
/* Define to 1 if NPcap's version.h is available */
#cmakedefine HAVE_VERSION_H 1
@ -265,6 +265,9 @@
/* Define to 1 if you have the `PacketIsLoopbackAdapter' function. */
#cmakedefine HAVE_PACKET_IS_LOOPBACK_ADAPTER 1
/* Define to 1 if you have the `PacketGetInfo' function. */
#cmakedefine HAVE_PACKET_GET_INFO 1
/* IPv6 */
#cmakedefine INET6 1
@ -325,6 +328,9 @@
/* target host supports RDMA sniffing */
#cmakedefine PCAP_SUPPORT_RDMASNIFF 1
/* The size of `time_t', as computed by sizeof. */
#cmakedefine SIZEOF_TIME_T @SIZEOF_TIME_T@
/* Define to 1 if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS 1

View file

@ -102,9 +102,6 @@
/* Define to 1 if you have the <linux/usbdevice_fs.h> header file. */
#undef HAVE_LINUX_USBDEVICE_FS_H
/* Define to 1 if you have the <linux/wireless.h> header file. */
#undef HAVE_LINUX_WIRELESS_H
/* Define to 1 if you have the <netpacket/packet.h> header file. */
#undef HAVE_NETPACKET_PACKET_H
@ -138,7 +135,7 @@
/* Use OpenSSL */
#undef HAVE_OPENSSL
/* if there's an os_proto.h for this platform, to use additional prototypes */
/* if there's an os-proto.h for this platform, to use additional prototypes */
#undef HAVE_OS_PROTO_H
/* Define to 1 if you have a POSIX-style `strerror_r' function. */
@ -256,6 +253,9 @@
/* Define to 1 if you have the `vsyslog' function. */
#undef HAVE_VSYSLOG
/* Define to 1 if you have the <zone.h> header file. */
#undef HAVE_ZONE_H
/* Define to 1 if you have the `_wcserror_s' function. */
#undef HAVE__WCSERROR_S

721
configure vendored
View file

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.71 for pcap 1.10.5.
# Generated by GNU Autoconf 2.71 for pcap 1.10.6.
#
#
# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
@ -608,8 +608,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='pcap'
PACKAGE_TARNAME='pcap'
PACKAGE_VERSION='1.10.5'
PACKAGE_STRING='pcap 1.10.5'
PACKAGE_VERSION='1.10.6'
PACKAGE_STRING='pcap 1.10.6'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@ -1380,7 +1380,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures pcap 1.10.5 to adapt to many kinds of systems.
\`configure' configures pcap 1.10.6 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1447,7 +1447,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of pcap 1.10.5:";;
short | recursive ) echo "Configuration of pcap 1.10.6:";;
esac
cat <<\_ACEOF
@ -1502,7 +1502,7 @@ Optional Packages:
directory DIR, if supplied). [default=yes, if
present]
--with-dpdk[=DIR] include DPDK support (located in directory DIR, if
supplied). [default=yes, if present]
supplied). [default=no]
Some influential environment variables:
CC C compiler command
@ -1611,7 +1611,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
pcap configure 1.10.5
pcap configure 1.10.6
generated by GNU Autoconf 2.71
Copyright (C) 2021 Free Software Foundation, Inc.
@ -1664,6 +1664,53 @@ fi
} # ac_fn_c_try_compile
# ac_fn_c_try_link LINENO
# -----------------------
# Try to link conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_link ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
grep -v '^ *+' conftest.err >conftest.er1
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
test -x conftest$ac_exeext
}
then :
ac_retval=0
else $as_nop
printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
fi
# Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
# created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
# interfere with the next link command; also delete a directory that is
# left behind by Apple's compiler. We do this before executing the actions.
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_c_try_link
# ac_fn_c_try_run LINENO
# ----------------------
# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that
@ -2183,7 +2230,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by pcap $as_me 1.10.5, which was
It was created by pcap $as_me 1.10.6, which was
generated by GNU Autoconf 2.71. Invocation command line was
$ $0$ac_configure_args_raw
@ -4220,11 +4267,288 @@ if test "$ac_cv_prog_cc_c99" = "no"; then
as_fn_error $? "The C compiler does not support C99" "$LINENO" 5
fi
#
# Try to arrange for large file support.
#
# Check whether --enable-largefile was given.
if test ${enable_largefile+y}
then :
enableval=$enable_largefile;
fi
if test "$enable_largefile" != no; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
printf %s "checking for special C compiler options needed for large files... " >&6; }
if test ${ac_cv_sys_largefile_CC+y}
then :
printf %s "(cached) " >&6
else $as_nop
ac_cv_sys_largefile_CC=no
if test "$GCC" != yes; then
ac_save_CC=$CC
while :; do
# IRIX 6.2 and later do not support large files by default,
# so use the C compiler's -n32 option if that helps.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
CC="$CC -n32"
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_sys_largefile_CC=' -n32'; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
break
done
CC=$ac_save_CC
rm -f conftest.$ac_ext
fi
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
printf "%s\n" "$ac_cv_sys_largefile_CC" >&6; }
if test "$ac_cv_sys_largefile_CC" != no; then
CC=$CC$ac_cv_sys_largefile_CC
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
printf %s "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
if test ${ac_cv_sys_file_offset_bits+y}
then :
printf %s "(cached) " >&6
else $as_nop
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_sys_file_offset_bits=no; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _FILE_OFFSET_BITS 64
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_sys_file_offset_bits=64; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_sys_file_offset_bits=unknown
break
done
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
printf "%s\n" "$ac_cv_sys_file_offset_bits" >&6; }
case $ac_cv_sys_file_offset_bits in #(
no | unknown) ;;
*)
printf "%s\n" "#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits" >>confdefs.h
;;
esac
rm -rf conftest*
if test $ac_cv_sys_file_offset_bits = unknown; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
printf %s "checking for _LARGE_FILES value needed for large files... " >&6; }
if test ${ac_cv_sys_large_files+y}
then :
printf %s "(cached) " >&6
else $as_nop
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_sys_large_files=no; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _LARGE_FILES 1
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_sys_large_files=1; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_sys_large_files=unknown
break
done
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
printf "%s\n" "$ac_cv_sys_large_files" >&6; }
case $ac_cv_sys_large_files in #(
no | unknown) ;;
*)
printf "%s\n" "#define _LARGE_FILES $ac_cv_sys_large_files" >>confdefs.h
;;
esac
rm -rf conftest*
fi
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _LARGEFILE_SOURCE value needed for large files" >&5
printf %s "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; }
if test ${ac_cv_sys_largefile_source+y}
then :
printf %s "(cached) " >&6
else $as_nop
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h> /* for off_t */
#include <stdio.h>
int
main (void)
{
int (*fp) (FILE *, off_t, int) = fseeko;
return fseeko (stdin, 0, 0) && fp (stdin, 0, 0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_sys_largefile_source=no; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _LARGEFILE_SOURCE 1
#include <sys/types.h> /* for off_t */
#include <stdio.h>
int
main (void)
{
int (*fp) (FILE *, off_t, int) = fseeko;
return fseeko (stdin, 0, 0) && fp (stdin, 0, 0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_sys_largefile_source=1; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
ac_cv_sys_largefile_source=unknown
break
done
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_source" >&5
printf "%s\n" "$ac_cv_sys_largefile_source" >&6; }
case $ac_cv_sys_largefile_source in #(
no | unknown) ;;
*)
printf "%s\n" "#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source" >>confdefs.h
;;
esac
rm -rf conftest*
# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug
# in glibc 2.1.3, but that breaks too many other things.
# If you want fseeko and ftello with glibc, upgrade to a fixed glibc.
if test $ac_cv_sys_largefile_source != unknown; then
printf "%s\n" "#define HAVE_FSEEKO 1" >>confdefs.h
fi
#
# Get the size of a void *, to determine whether this is a 32-bit
# or 64-bit build.
#
ac_header= ac_cache=
for ac_item in $ac_header_c_list
do
@ -4986,54 +5310,7 @@ printf %s "checking for __atomic_load_n... " >&6; }
then :
printf %s "(cached) " >&6
else $as_nop
# ac_fn_c_try_link LINENO
# -----------------------
# Try to link conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_link ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
grep -v '^ *+' conftest.err >conftest.er1
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
test -x conftest$ac_exeext
}
then :
ac_retval=0
else $as_nop
printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
fi
# Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
# created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
# interfere with the next link command; also delete a directory that is
# left behind by Apple's compiler. We do this before executing the actions.
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_c_try_link
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@ -5104,283 +5381,6 @@ printf "%s\n" "#define HAVE___ATOMIC_STORE_N 1" >>confdefs.h
fi
#
# Try to arrange for large file support.
#
# Check whether --enable-largefile was given.
if test ${enable_largefile+y}
then :
enableval=$enable_largefile;
fi
if test "$enable_largefile" != no; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
printf %s "checking for special C compiler options needed for large files... " >&6; }
if test ${ac_cv_sys_largefile_CC+y}
then :
printf %s "(cached) " >&6
else $as_nop
ac_cv_sys_largefile_CC=no
if test "$GCC" != yes; then
ac_save_CC=$CC
while :; do
# IRIX 6.2 and later do not support large files by default,
# so use the C compiler's -n32 option if that helps.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
CC="$CC -n32"
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_sys_largefile_CC=' -n32'; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
break
done
CC=$ac_save_CC
rm -f conftest.$ac_ext
fi
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
printf "%s\n" "$ac_cv_sys_largefile_CC" >&6; }
if test "$ac_cv_sys_largefile_CC" != no; then
CC=$CC$ac_cv_sys_largefile_CC
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
printf %s "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
if test ${ac_cv_sys_file_offset_bits+y}
then :
printf %s "(cached) " >&6
else $as_nop
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_sys_file_offset_bits=no; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _FILE_OFFSET_BITS 64
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_sys_file_offset_bits=64; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_sys_file_offset_bits=unknown
break
done
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
printf "%s\n" "$ac_cv_sys_file_offset_bits" >&6; }
case $ac_cv_sys_file_offset_bits in #(
no | unknown) ;;
*)
printf "%s\n" "#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits" >>confdefs.h
;;
esac
rm -rf conftest*
if test $ac_cv_sys_file_offset_bits = unknown; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
printf %s "checking for _LARGE_FILES value needed for large files... " >&6; }
if test ${ac_cv_sys_large_files+y}
then :
printf %s "(cached) " >&6
else $as_nop
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_sys_large_files=no; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _LARGE_FILES 1
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_sys_large_files=1; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_sys_large_files=unknown
break
done
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
printf "%s\n" "$ac_cv_sys_large_files" >&6; }
case $ac_cv_sys_large_files in #(
no | unknown) ;;
*)
printf "%s\n" "#define _LARGE_FILES $ac_cv_sys_large_files" >>confdefs.h
;;
esac
rm -rf conftest*
fi
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _LARGEFILE_SOURCE value needed for large files" >&5
printf %s "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; }
if test ${ac_cv_sys_largefile_source+y}
then :
printf %s "(cached) " >&6
else $as_nop
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h> /* for off_t */
#include <stdio.h>
int
main (void)
{
int (*fp) (FILE *, off_t, int) = fseeko;
return fseeko (stdin, 0, 0) && fp (stdin, 0, 0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_sys_largefile_source=no; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _LARGEFILE_SOURCE 1
#include <sys/types.h> /* for off_t */
#include <stdio.h>
int
main (void)
{
int (*fp) (FILE *, off_t, int) = fseeko;
return fseeko (stdin, 0, 0) && fp (stdin, 0, 0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_sys_largefile_source=1; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
ac_cv_sys_largefile_source=unknown
break
done
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_source" >&5
printf "%s\n" "$ac_cv_sys_largefile_source" >&6; }
case $ac_cv_sys_largefile_source in #(
no | unknown) ;;
*)
printf "%s\n" "#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source" >>confdefs.h
;;
esac
rm -rf conftest*
# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug
# in glibc 2.1.3, but that breaks too many other things.
# If you want fseeko and ftello with glibc, upgrade to a fixed glibc.
if test $ac_cv_sys_largefile_source != unknown; then
printf "%s\n" "#define HAVE_FSEEKO 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "sys/ioccom.h" "ac_cv_header_sys_ioccom_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_ioccom_h" = xyes
then :
@ -7232,6 +7232,12 @@ if test "x$ac_cv_header_sys_dlpi_ext_h" = xyes
then :
printf "%s\n" "#define HAVE_SYS_DLPI_EXT_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "zone.h" "ac_cv_header_zone_h" "$ac_includes_default"
if test "x$ac_cv_header_zone_h" = xyes
then :
printf "%s\n" "#define HAVE_ZONE_H 1" >>confdefs.h
fi
@ -7418,22 +7424,6 @@ linux)
#
PLATFORM_C_SRC="pcap-linux.c"
#
# Do we have the wireless extensions?
#
ac_fn_c_check_header_compile "$LINENO" "linux/wireless.h" "ac_cv_header_linux_wireless_h" "
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/types.h>
"
if test "x$ac_cv_header_linux_wireless_h" = xyes
then :
printf "%s\n" "#define HAVE_LINUX_WIRELESS_H 1" >>confdefs.h
fi
#
# Do we have libnl?
# We only want version 3. Version 2 was, apparently,
@ -10444,6 +10434,11 @@ fi
rm -f os-proto.h
#
# MKDEP defaults to no-op (":") if we don't test whether the compiler
# supports generating dependencies
#
MKDEP=:
if test "${LBL_CFLAGS+set}" = set; then
V_CCOPT="$V_CCOPT ${LBL_CFLAGS}"
fi
@ -12550,16 +12545,20 @@ printf "%s\n" "no" >&6; }
# .devel file; why should the ABI for which we produce code
# depend on .devel?
#
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to use an os-proto.h header" >&5
printf %s "checking whether to use an os-proto.h header... " >&6; }
os=`echo $host_os | sed -e 's/\([0-9][0-9]*\)[^0-9].*$/\1/'`
name="lbl/os-$os.h"
if test -f $name ; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes, at \"$name\"" >&5
printf "%s\n" "yes, at \"$name\"" >&6; }
ln -s $name os-proto.h
printf "%s\n" "#define HAVE_OS_PROTO_H 1" >>confdefs.h
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: can't find $name" >&5
printf "%s\n" "$as_me: WARNING: can't find $name" >&2;}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
@ -12870,9 +12869,12 @@ else $as_nop
want_dpdk=no
else
#
# Use DPDK API if present, otherwise don't
# User didn't explicitly request DPDK; don't give it
# to them without their consent, as the code is
# immensely hard to keep compiling for every random
# API change the DPDK folks make.
#
want_dpdk=ifpresent
want_dpdk=no
fi
fi
@ -13282,10 +13284,10 @@ else $as_nop
# Bluetooth sniffing.
#
if test "x$enable_bluetooth" = "xyes" ; then
as_fn_error $? "Bluetooth sniffing is not supported; install bluez-lib devel to enable it" "$LINENO" 5
as_fn_error $? "Bluetooth sniffing is not supported; install a Bluetooth devel library (libbluetooth-dev|bluez-libs-devel|bluez-dev|libbluetooth-devel|...) to enable it" "$LINENO" 5
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: Bluetooth sniffing is not supported; install bluez-lib devel to enable it" >&5
printf "%s\n" "$as_me: Bluetooth sniffing is not supported; install bluez-lib devel to enable it" >&6;}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: Bluetooth sniffing is not supported; install a Bluetooth devel library (libbluetooth-dev|bluez-libs-devel|bluez-dev|libbluetooth-devel|...) to enable it" >&5
printf "%s\n" "$as_me: Bluetooth sniffing is not supported; install a Bluetooth devel library (libbluetooth-dev|bluez-libs-devel|bluez-dev|libbluetooth-devel|...) to enable it" >&6;}
fi
fi
@ -14460,7 +14462,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by pcap $as_me 1.10.5, which was
This file was extended by pcap $as_me 1.10.6, which was
generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -14528,7 +14530,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
pcap config.status 1.10.5
pcap config.status 1.10.6
configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"
@ -15278,4 +15280,3 @@ printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2
fi
exit 0

View file

@ -111,6 +111,12 @@ if test "$ac_cv_prog_cc_c99" = "no"; then
AC_MSG_ERROR([The C compiler does not support C99])
fi
#
# Try to arrange for large file support.
#
AC_SYS_LARGEFILE
AC_FUNC_FSEEKO
#
# Get the size of a void *, to determine whether this is a 32-bit
# or 64-bit build.
@ -128,12 +134,6 @@ AC_LBL_SHLIBS_INIT
AC_LBL_C_INLINE
AC_PCAP_C___ATOMICS
#
# Try to arrange for large file support.
#
AC_SYS_LARGEFILE
AC_FUNC_FSEEKO
dnl
dnl Even if <net/bpf.h> were, on all OSes that support BPF, fixed to
dnl include <sys/ioccom.h>, and we were to drop support for older
@ -905,7 +905,7 @@ dlpi)
#
# Checks for some header files.
#
AC_CHECK_HEADERS(sys/bufmod.h sys/dlpi_ext.h)
AC_CHECK_HEADERS(sys/bufmod.h sys/dlpi_ext.h zone.h)
#
# Checks to see if Solaris has the public libdlpi(3LIB) library.
@ -1003,16 +1003,6 @@ linux)
#
PLATFORM_C_SRC="pcap-linux.c"
#
# Do we have the wireless extensions?
#
AC_CHECK_HEADERS(linux/wireless.h, [], [],
[
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/types.h>
])
#
# Do we have libnl?
# We only want version 3. Version 2 was, apparently,
@ -2682,7 +2672,7 @@ fi
# Check for DPDK support.
AC_ARG_WITH([dpdk],
AS_HELP_STRING([--with-dpdk@<:@=DIR@:>@],[include DPDK support (located in directory DIR, if supplied). @<:@default=yes, if present@:>@]),
AS_HELP_STRING([--with-dpdk@<:@=DIR@:>@],[include DPDK support (located in directory DIR, if supplied). @<:@default=no@:>@]),
[
if test "$withval" = no
then
@ -2709,9 +2699,12 @@ AS_HELP_STRING([--with-dpdk@<:@=DIR@:>@],[include DPDK support (located in direc
want_dpdk=no
else
#
# Use DPDK API if present, otherwise don't
# User didn't explicitly request DPDK; don't give it
# to them without their consent, as the code is
# immensely hard to keep compiling for every random
# API change the DPDK folks make.
#
want_dpdk=ifpresent
want_dpdk=no
fi
])
@ -2951,9 +2944,9 @@ if test "x$enable_bluetooth" != "xno" ; then
# Bluetooth sniffing.
#
if test "x$enable_bluetooth" = "xyes" ; then
AC_MSG_ERROR(Bluetooth sniffing is not supported; install bluez-lib devel to enable it)
AC_MSG_ERROR(Bluetooth sniffing is not supported; install a Bluetooth devel library (libbluetooth-dev|bluez-libs-devel|bluez-dev|libbluetooth-devel|...) to enable it)
else
AC_MSG_NOTICE(Bluetooth sniffing is not supported; install bluez-lib devel to enable it)
AC_MSG_NOTICE(Bluetooth sniffing is not supported; install a Bluetooth devel library (libbluetooth-dev|bluez-libs-devel|bluez-dev|libbluetooth-devel|...) to enable it)
fi
])
;;

View file

@ -60,10 +60,20 @@
#include <stropts.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <net/if.h>
#ifdef HAVE_LIBDLPI
#include <libdlpi.h>
#endif
#ifdef HAVE_ZONE_H
#include <zone.h>
#endif
#include "pcap-int.h"
#include "dlpisubs.h"
@ -413,3 +423,117 @@ pcap_stream_err(const char *func, int err, char *errbuf)
pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, err, "%s", func);
}
#endif
int
handle_nonexistent_dlpi_device(const char *ifname, char *errbuf)
{
int fd;
int status;
#ifdef LIFNAMSIZ
struct lifreq lifr;
#else
struct ifreq ifr;
#endif
#ifdef LIFNAMSIZ
if (strlen(ifname) >= sizeof(lifr.lifr_name)) {
#else
if (strlen(ifname) >= sizeof(ifr.ifr_name)) {
#endif
/*
* The name is too long, so it can't possibly exist.
*/
strlcpy(errbuf, "", PCAP_ERRBUF_SIZE);
return (PCAP_ERROR_NO_SUCH_DEVICE);
}
/*
* Try to get a socket on which to do an ioctl to get the
* interface's flags.
*/
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
/* That failed; report that as the error. */
pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
errno, "Can't open socket to get interface flags");
return (PCAP_ERROR);
}
#ifdef LIFNAMSIZ
pcapint_strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
status = ioctl(fd, SIOCGLIFFLAGS, (char *)&lifr);
#else
pcapint_strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
status = ioctl(fd, SIOCGIFFLAGS, (char *)&ifr);
#endif
if (status < 0) {
if (errno == ENXIO || errno == EINVAL) {
/*
* macOS, *BSD, and Solaris return one of
* those two errors if the device doesn't exist.
*/
strlcpy(errbuf, "", PCAP_ERRBUF_SIZE);
close(fd);
return (PCAP_ERROR_NO_SUCH_DEVICE);
}
/*
* Some other error.
*/
pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno,
"Can't get interface flags");
close(fd);
return (PCAP_ERROR);
}
/*
* The interface exists.
*/
close(fd);
#ifdef HAVE_ZONE_H
/*
* If we're not in a global zone, the problem is probably
* that the zone we're in doesn't happen to have any
* DLPI devices. Exclusive-IP non-global zones have
* their own interfaces and have DLPI devices for them:
*
* https://docs.oracle.com/cd/E37838_01/html/E61040/z.config.ov-6.html#VLZCRgekkb
*
* https://docs.oracle.com/cd/E19044-01/sol.containers/817-1592/geprv/index.html
*
* but shared-IP non-global zones don't:
*
* https://docs.oracle.com/cd/E37838_01/html/E61040/z.config.ov-6.html#VLZCRgekku
*/
if (getzoneid() != GLOBAL_ZONEID) {
/*
* Not a global zone; note that capturing on network
* interfaces is only supported for interfaces
* in an exclusive-IP zone.
*/
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Capturing on interfaces in a non-global zone is supported only for interfaces in exclusive-IP zones");
return (PCAP_ERROR_CAPTURE_NOTSUP);
}
#endif /* HAVE_ZONE_H */
/*
* Some other problem; just report it as not having
* a DLPI device. We don't report the DLPI device
* name, so people don't get confused and think, for
* example, that if they can't capture on that interface
* on Solaris prior to Solaris 11 the fix is to change
* libpcap (or the application that uses it) to look
* for something other than "/dev/{ifname}", as the fix
* is to use Solaris 11 or some operating system other
* than Solaris - you just *can't* capture on that
* interface on Solaris prior to Solaris 11, the lack
* of a DLPI device for the loopback interface is just
* a symptom of that inability.
*/
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Capturing on that interface is not supported - no DLPI device found");
return (PCAP_ERROR_CAPTURE_NOTSUP);
}

View file

@ -30,6 +30,7 @@ int pcap_conf_bufmod(pcap_t *, int);
#endif
int pcap_alloc_databuf(pcap_t *);
int strioctl(int, int, int, char *);
int handle_nonexistent_dlpi_device(const char *ifname, char *errbuf);
#ifdef __cplusplus
}

View file

@ -2,10 +2,9 @@
Haiku R1/beta4 and earlier versions do not support packet capture on the
loopback interface. Using this version of libpcap, loopback capture works
since Haiku revision hrev57585 and is expected to work in Haiku R1/beta5 when
the latter becomes available. Packet timestamping and filtering always occur
in userland. Wireless monitor mode is not supported. The "any"
pseudo-interface is not supported.
since Haiku revision hrev57585, including Haiku R1/beta5 and later versions.
Packet timestamping and filtering always occur in userland. Wireless monitor
mode is not supported. The "any" pseudo-interface is not supported.
[**pcap_set_buffer_size**](https://www.tcpdump.org/manpages/pcap_set_buffer_size.3pcap.html)(3PCAP)
has no effect.
[**pcap_setdirection**](https://www.tcpdump.org/manpages/pcap_setdirection.3pcap.html)(3PCAP)
@ -22,36 +21,19 @@ on Haiku are as follows:
* `ps_ifdrop` is the number of packets dropped by the network interface (as
seen via `SIOCGIFSTATS`) since the capture handle became active.
## 64-bit x86 R1/beta4
## 64-bit x86 R1/beta5
* Autoconf 2.71 works.
* CMake 3.28.3 works.
* GCC 13.2.0 works.
* Clang 12.0.1 works with the latest llvm12_clang-12.0.1-5 version.
* Autoconf 2.72 works.
* CMake 4.1.4 works.
* GCC 13.3.0 works.
* Clang 21.1.8
* flex 2.6.4 works.
* bison 3.8.2 works.
* GNU Bison 3.8.2 works.
The following command will install respective non-default packages:
```
pkgman install cmake llvm12_clang
pkgman install cmake llvm21_clang
```
For reference, the tests were done using a system installed from
`haiku-r1beta4-x86_64-anyboot.iso`.
## 32-bit x86 R1/beta4
* Autoconf 2.71 works.
* CMake 3.24.2 works.
* GCC 11.2.0 works.
* Clang does not work.
* flex 2.6.4 works.
* bison 3.0.5 works.
The following command will install respective non-default packages:
```
pkgman install cmake_x86
```
For reference, the tests were done using a system installed from
`haiku-r1beta4-x86_gcc2h-anyboot.iso`.
`haiku-r1beta5-x86_64-anyboot.iso`.

View file

@ -5,6 +5,12 @@
* Neither illumos lex nor illumos yacc are suitable.
* Solaris m4 and illumos m4 are suitable.
## OmniOS r151054/AMD64
* flex 2.6.4 and GNU Bison 3.8.2 work.
* CMake 4.0.3 works.
* GCC 14.2.0 and Clang 19.1.7 work.
## OmniOS r151042/AMD64
* flex 2.6.4 and GNU Bison 3.8.2 work.
@ -30,15 +36,18 @@ developer/clang-90
ENDOFTEXT
```
## Solaris 11/AMD64
## Solaris CBE 11.4.81.193.1/AMD64
* flex 2.6.4 and GNU Bison 3.8.2 work.
* CMake 3.24.0 works.
* Clang 19.1.7 works, GCC 14.2.0 works.
## Solaris CBE 11.4.42.111.0/AMD64
* flex 2.6.4 and GNU Bison 3.7.3 work.
* CMake 3.21.0 works.
* Clang 11.0 works, GCC 11.2 works.
For reference, the tests were done using Oracle Solaris 11.4.42.111.0.
## Solaris 11/SPARC
## Solaris 11.3/SPARC
* flex 2.6.4 and GNU Bison 3.7.1 work.
* CMake 3.14.3 works.
@ -51,8 +60,7 @@ For reference, the tests were done using Oracle Solaris 11.4.42.111.0.
* CMake 3.14.3 works.
* Sun C 5.13 works, GCC 5.5.0 works.
## Solaris 9/SPARC
## Solaris 9
* flex 2.5.35 and GNU Bison 3.0.2 work.
* CMake 2.8.9 does not work.
* Neither Sun C 5.8 nor Sun C 5.9 work, GCC 4.6.4 works.
This version of this OS is not supported because the snprintf(3) implementation
in its libc is not suitable.

View file

@ -26,48 +26,43 @@ only if there is some other requirement to use it rather than Npcap,
such as a requirement to support versions of Windows earlier than
Windows Vista, which is the earliest version supported by Npcap.
Npcap and its SDK can be downloaded from its home page:
https://npcap.com
The SDK is a ZIP archive; create a folder on your C: drive, e.g.
C:\npcap-sdk, and put the contents of the ZIP archive into that folder.
Npcap and its SDK can be downloaded from its [home page](https://npcap.com).
The SDK is a ZIP archive; create a folder on your `C:` drive, e.g.
`C:\npcap-sdk`, and put the contents of the ZIP archive into that folder.
The WinPcap installer can be downloaded from
https://www.winpcap.org/install/default.htm
[here](https://www.winpcap.org/install/default.htm)
and the WinPcap Developer's Kit can be downloaded from
https://www.winpcap.org/devel.htm
[here](https://www.winpcap.org/devel.htm).
Required build tools
--------------------
The Developer's Kit is a ZIP archive; it contains a folder named
WpdPack, which you should place on your C: drive, e.g. C:\WpdPack.
`WpdPack`, which you should place on your `C:` drive, e.g. `C:\WpdPack`.
Building libpcap on Windows requires Visual Studio 2015 or later. The
Community Edition of Visual Studio can be downloaded at no cost from
https://visualstudio.microsoft.com
[here](https://visualstudio.microsoft.com).
Additional tools are also required. Chocolatey is a package manager for
Windows with which those tools, and other tools, can be installed; it
can be downloaded from
https://chocolatey.org
can be downloaded from [here](https://chocolatey.org).
It is a command-line tool; a GUI tool, Chocolatey GUI, is provided as a
Chocolatey package, which can be installed from the command line:
choco install chocolateygui
```
choco install chocolateygui
```
For convenience, the "choco install" command can be run with the "-y"
For convenience, the `choco install` command can be run with the `-y`
flag, forcing it to automatically answer all questions asked of the user
with "yes":
choco install -y chocolateygui
```
choco install -y chocolateygui
```
The required tools are:
@ -77,31 +72,31 @@ libpcap does not provide supported project files for Visual Studio
(there are currently unsupported project files provided, but we do not
guarantee that they will work or that we will continue to provide them).
It does provide files for CMake, which is a cross-platform tool that
runs on UN*Xes and on Windows and that can generate project files for
UN*X Make, the Ninja build system, and Visual Studio, among other build
runs on UN\*Xes and on Windows and that can generate project files for
UN\*X Make, the Ninja build system, and Visual Studio, among other build
systems.
Visual Studio 2015 does not provide CMake; an installer can be
downloaded from
https://cmake.org/download/
downloaded from [here](https://cmake.org/download/).
When you run the installer, you should choose to add CMake to the system
PATH for all users and to create the desktop icon.
`PATH` for all users and to create the desktop icon.
CMake can also be installed as the Chocolatey package "cmake":
choco install -y cmake
Visual Studio 2017 and later provide CMake, so you will not need to
install CMake if you have installed Visual Studio 2017 or later. They
include built-in support for CMake-based projects:
https://devblogs.microsoft.com/cppblog/cmake-support-in-visual-studio/
Visual Studio 2017, 2019, and 2022 provide CMake, so you will not need
to install CMake if you have installed one of those versions of Visual
Studio or later. They include built-in support for CMake-based projects
as described
[here](https://devblogs.microsoft.com/cppblog/cmake-support-in-visual-studio/).
For Visual Studio 2017, make sure "Visual C++ tools for CMake" is
installed; for Visual Studio 2019, make sure "C++ CMake tools for
Windows" is installed.
installed; for Visual Studio 2019 and 2022, make sure "C++ CMake tools
for Windows" is installed.
CMake can also be installed as the Chocolatey package `cmake`:
```
choco install -y cmake
```
### winflexbison ###
@ -140,19 +135,21 @@ Debug build.
In the CMakeSettings.json tab, change cmakeCommandArgs to include
-DPacket_ROOT={path-to-sdk}
```
-DPacket_ROOT={path-to-sdk}
```
where {path-to-sdk} is the path of the directory containing the Npcap or
where `{path-to-sdk}` is the path of the directory containing the Npcap or
WinPcap SDK. Note that backslashes in the path must be specified as two
backslashes.
Save the configuration changes with File > "Save CMakeSettings.json" or
with control-S.
with Control-S.
Visual Studio will then re-run CMake. If that completes without errors,
you can build with CMake > "Build All".
### Visual Studio 2019 ###
### Visual Studio 2019 and 2022 ###
Open the folder containing the libpcap source with Open > Folder.
Visual Studio will run CMake; however, you will need to indicate where
@ -169,7 +166,7 @@ the directory containing the Npcap or WinPcap SDK or use the "Browse..."
button to browse for that directory.
Save the configuration changes with File > "Save CMakeSettings.json" or
with control-S.
with Control-S.
Visual Studio will then re-run CMake. If that completes without errors,
you can build with Build > "Build All".
@ -177,6 +174,8 @@ you can build with Build > "Build All".
Building from the command line
------------------------------
### Visual Studio 2017 ###
Start the appropriate Native Tools command line prompt.
Change to the directory into which you want to build libpcap, possibly
@ -185,14 +184,96 @@ of the libpcap source directory.
Run the command
cmake "-DPacket_ROOT={path-to-sdk}" {path-to-libpcap-source}
```
cmake "-DPacket_ROOT={path-to-sdk}" -G {generator} {path-to-libpcap-source}
```
where {path-to-sdk} is the path of the directory containing the Npcap or
WinPcap SDK and {path-to-libpcap-source} is the pathname of the
top-level source directory for libpcap.
`{path-to-sdk}` is the path of the directory containing the Npcap or
WinPcap SDK.
`{generator}` is the string "Visual Studio 15 2017" to build a 32-bit
version of libpcap or the string "Visual Studio 15 2017 Win64" to build
a 64-bit version of libpcap.
`{path-to-libpcap-source}` is the pathname of the top-level source
directory for libpcap.
Run the command
msbuild/m pcap.sln
```
msbuild /m /nologo /p:Configuration={configuration} pcap.sln
```
to compile libpcap.
where `{configuration}` can be "Release", "Debug", or "RelWithDebInfo".
### Visual Studio 2019 ###
Start the appropriate Native Tools command line prompt.
Change to the directory into which you want to build libpcap, possibly
after creating it first. One choice is to create it as a subdirectory
of the libpcap source directory.
Run the command
```
cmake "-DPacket_ROOT={path-to-sdk}" -G "Visual Studio 16 2019" {platform} {path-to-libpcap-source}
```
`{path-to-sdk}` is the path of the directory containing the Npcap or
WinPcap SDK.
`{platform}` is `-A Win32` to build a 32-bit version of libpcap or `-A
x64` to build a 64-bit version of libpcap.
`{path-to-libpcap-source}` is the pathname of the top-level source
directory for libpcap.
Run the command
```
msbuild /m /nologo /p:Configuration={configuration} pcap.sln
```
where `{configuration}` can be "Release", "Debug", or "RelWithDebInfo".
### Visual Studio 2022 ###
Start the appropriate Native Tools command line prompt.
Change to the directory into which you want to build libpcap, possibly
after creating it first. One choice is to create it as a subdirectory
of the libpcap source directory.
Run the command
```
cmake "-DPacket_ROOT={path-to-sdk}" -G "Visual Studio 17 2022" {platform} {path-to-libpcap-source}
```
`{path-to-sdk}` is the path of the directory containing the Npcap or
WinPcap SDK.
`{platform}` is `-A Win32` to build a 32-bit version of libpcap or `-A
x64` to build a 64-bit version of libpcap.
`{path-to-libpcap-source}` is the pathname of the top-level source
directory for libpcap.
Run the command
```
msbuild /m /nologo /p:Configuration={configuration} pcap.sln
```
where `{configuration}` can be "Release", "Debug", or "RelWithDebInfo".
Building with MinGW
-------------------
MinGW is not supported because its snprintf(3) implementation is not suitable.
Building with SSL/TLS support
-----------------------------
This is currently not implemented on Windows.

View file

@ -162,7 +162,7 @@ pcapint_findalldevs_interfaces(pcap_if_list_t *devlistp, char *errbuf,
{
struct ifaddrs *ifap, *ifa;
struct sockaddr *addr, *netmask, *broadaddr, *dstaddr;
size_t addr_size, broadaddr_size, dstaddr_size;
size_t addr_size, netmask_size, broadaddr_size, dstaddr_size;
int ret = 0;
char *p, *q;
@ -235,11 +235,18 @@ pcapint_findalldevs_interfaces(pcap_if_list_t *devlistp, char *errbuf,
if (ifa->ifa_addr != NULL) {
addr = ifa->ifa_addr;
addr_size = SA_LEN(addr);
netmask = ifa->ifa_netmask;
if (ifa->ifa_netmask != NULL) {
netmask = ifa->ifa_netmask;
netmask_size = SA_LEN(ifa->ifa_netmask);
} else {
netmask = NULL;
netmask_size = 0;
}
} else {
addr = NULL;
addr_size = 0;
netmask = NULL;
netmask_size = 0;
}
/*
@ -279,7 +286,7 @@ pcapint_findalldevs_interfaces(pcap_if_list_t *devlistp, char *errbuf,
*/
if (pcapint_add_addr_to_if(devlistp, ifa->ifa_name, ifa->ifa_flags,
get_flags_func,
addr, addr_size, netmask, addr_size,
addr, addr_size, netmask, netmask_size,
broadaddr, broadaddr_size, dstaddr, dstaddr_size,
errbuf) < 0) {
ret = -1;

View file

@ -233,7 +233,7 @@ utf_16le_to_utf_8_truncated(const wchar_t *utf_16, char *utf_8,
*utf_8++ = ((uc >> 12) & 0x3F) | 0x80;
*utf_8++ = ((uc >> 6) & 0x3F) | 0x80;
*utf_8++ = ((uc >> 0) & 0x3F) | 0x80;
utf_8_len -= 3;
utf_8_len -= 4;
}
}

346
gencode.c
View file

@ -24,14 +24,7 @@
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#ifdef __NetBSD__
#include <sys/param.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#endif /* _WIN32 */
#include <stdlib.h>
@ -76,6 +69,10 @@
#endif
#ifdef _WIN32
#ifdef HAVE_NPCAP_BPF_H
/* Defines BPF extensions for Npcap */
#include <npcap-bpf.h>
#endif
#ifdef INET6
#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
/* IPv6 address */
@ -230,6 +227,26 @@ struct chunk {
void *m;
};
/*
* A chunk can store any of:
* - a string (guaranteed alignment 1 but present for completeness)
* - a block
* - an slist
* - an arth
* For this simple allocator every allocated chunk gets rounded up to the
* alignment needed for any chunk.
*/
struct chunk_align {
char dummy;
union {
char c;
struct block b;
struct slist s;
struct arth a;
} u;
};
#define CHUNK_ALIGN (offsetof(struct chunk_align, u))
/* Code generator state */
struct _compiler_state {
@ -526,7 +543,7 @@ static struct block *gen_hostop(compiler_state_t *, bpf_u_int32, bpf_u_int32,
static struct block *gen_hostop6(compiler_state_t *, struct in6_addr *,
struct in6_addr *, int, bpf_u_int32, u_int, u_int);
#endif
static struct block *gen_ahostop(compiler_state_t *, const u_char *, int);
static struct block *gen_ahostop(compiler_state_t *, const uint8_t, int);
static struct block *gen_ehostop(compiler_state_t *, const u_char *, int);
static struct block *gen_fhostop(compiler_state_t *, const u_char *, int);
static struct block *gen_thostop(compiler_state_t *, const u_char *, int);
@ -598,13 +615,8 @@ newchunk_nolongjmp(compiler_state_t *cstate, size_t n)
int k;
size_t size;
#ifndef __NetBSD__
/* XXX Round up to nearest long. */
n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1);
#else
/* XXX Round up to structure boundary. */
n = ALIGN(n);
#endif
/* Round up to chunk alignment. */
n = (n + CHUNK_ALIGN - 1) & ~(CHUNK_ALIGN - 1);
cp = &cstate->chunks[cstate->cur_chunk];
if (n > cp->n_left) {
@ -696,7 +708,7 @@ new_stmt(compiler_state_t *cstate, int code)
}
static struct block *
gen_retblk(compiler_state_t *cstate, int v)
gen_retblk_internal(compiler_state_t *cstate, int v)
{
struct block *b = new_block(cstate, BPF_RET|BPF_K);
@ -704,6 +716,22 @@ gen_retblk(compiler_state_t *cstate, int v)
return b;
}
static struct block *
gen_retblk(compiler_state_t *cstate, int v)
{
if (setjmp(cstate->top_ctx)) {
/*
* gen_retblk() only fails because a memory
* allocation failed in newchunk(), meaning
* that it can't return a pointer.
*
* Return NULL.
*/
return NULL;
}
return gen_retblk_internal(cstate, v);
}
static inline PCAP_NORETURN_DEF void
syntax(compiler_state_t *cstate)
{
@ -718,9 +746,8 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
static int done = 0;
#endif
compiler_state_t cstate;
const char * volatile xbuf = buf;
yyscan_t scanner = NULL;
volatile YY_BUFFER_STATE in_buffer = NULL;
YY_BUFFER_STATE in_buffer = NULL;
u_int len;
int rc;
@ -790,7 +817,7 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
rc = PCAP_ERROR;
goto quit;
}
in_buffer = pcap__scan_string(xbuf ? xbuf : "", scanner);
in_buffer = pcap__scan_string(buf ? buf : "", scanner);
/*
* Associate the compiler state with the lexical analyzer
@ -814,14 +841,15 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
}
if (cstate.ic.root == NULL) {
cstate.ic.root = gen_retblk(&cstate, cstate.snaplen);
/*
* Catch errors reported by gen_retblk().
*/
if (setjmp(cstate.top_ctx)) {
if (cstate.ic.root== NULL) {
rc = PCAP_ERROR;
goto quit;
}
cstate.ic.root = gen_retblk(&cstate, cstate.snaplen);
}
if (optimize && !cstate.no_optimize) {
@ -990,9 +1018,9 @@ finish_parse(compiler_state_t *cstate, struct block *p)
if (ppi_dlt_check != NULL)
gen_and(ppi_dlt_check, p);
backpatch(p, gen_retblk(cstate, cstate->snaplen));
backpatch(p, gen_retblk_internal(cstate, cstate->snaplen));
p->sense = !p->sense;
backpatch(p, gen_retblk(cstate, 0));
backpatch(p, gen_retblk_internal(cstate, 0));
cstate->ic.root = p->head;
return (0);
}
@ -1704,6 +1732,83 @@ init_linktype(compiler_state_t *cstate, pcap_t *p)
cstate->off_nl_nosnap = 3; /* 802.3+802.2 */
break;
case DLT_EN3MB:
/*
* Currently, only raw "link[N:M]" filtering is supported.
*/
cstate->off_linktype.constant_part = OFFSET_NOT_SET; /* variable, min 15, max 71 steps of 7 */
cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
cstate->off_nl = OFFSET_NOT_SET; /* variable, min 16, max 71 steps of 7 */
cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
break;
case DLT_AX25:
/*
* Currently, only raw "link[N:M]" filtering is supported.
*/
cstate->off_linktype.constant_part = OFFSET_NOT_SET; /* variable, min 15, max 71 steps of 7 */
cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
cstate->off_nl = OFFSET_NOT_SET; /* variable, min 16, max 71 steps of 7 */
cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
break;
case DLT_PRONET:
/*
* Currently, only raw "link[N:M]" filtering is supported.
*/
cstate->off_linktype.constant_part = OFFSET_NOT_SET; /* variable, min 15, max 71 steps of 7 */
cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
cstate->off_nl = OFFSET_NOT_SET; /* variable, min 16, max 71 steps of 7 */
cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
break;
case DLT_CHAOS:
/*
* Currently, only raw "link[N:M]" filtering is supported.
*/
cstate->off_linktype.constant_part = OFFSET_NOT_SET; /* variable, min 15, max 71 steps of 7 */
cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
cstate->off_nl = OFFSET_NOT_SET; /* variable, min 16, max 71 steps of 7 */
cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
break;
#ifdef DLT_HIPPI
case DLT_HIPPI:
/*
* Currently, only raw "link[N:M]" filtering is supported.
*/
cstate->off_linktype.constant_part = OFFSET_NOT_SET; /* variable, min 15, max 71 steps of 7 */
cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
cstate->off_nl = OFFSET_NOT_SET; /* variable, min 16, max 71 steps of 7 */
cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
break;
#endif
case DLT_REDBACK_SMARTEDGE:
/*
* Currently, only raw "link[N:M]" filtering is supported.
*/
cstate->off_linktype.constant_part = OFFSET_NOT_SET; /* variable, min 15, max 71 steps of 7 */
cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
cstate->off_nl = OFFSET_NOT_SET; /* variable, min 16, max 71 steps of 7 */
cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
break;
#ifdef DLT_HHDLC
case DLT_HHDLC:
/*
* Currently, only raw "link[N:M]" filtering is supported.
*/
cstate->off_linktype.constant_part = OFFSET_NOT_SET; /* variable, min 15, max 71 steps of 7 */
cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
cstate->off_nl = OFFSET_NOT_SET; /* variable, min 16, max 71 steps of 7 */
cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
break;
#endif
default:
/*
* For values in the range in which we've assigned new
@ -1716,8 +1821,8 @@ init_linktype(compiler_state_t *cstate, pcap_t *p)
cstate->off_nl = OFFSET_NOT_SET;
cstate->off_nl_nosnap = OFFSET_NOT_SET;
} else {
bpf_set_error(cstate, "unknown data link type %d (min %d, max %d)",
cstate->linktype, DLT_HIGH_MATCHING_MIN, DLT_HIGH_MATCHING_MAX);
bpf_set_error(cstate, "unknown data link type %d",
cstate->linktype);
return (-1);
}
break;
@ -6945,7 +7050,8 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
int proto = q.proto;
int dir = q.dir;
int tproto;
u_char *eaddr;
u_char *eaddrp;
u_char eaddr[6];
bpf_u_int32 mask, addr;
struct addrinfo *res, *res0;
struct sockaddr_in *sin4;
@ -6987,33 +7093,36 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
case DLT_EN10MB:
case DLT_NETANALYZER:
case DLT_NETANALYZER_TRANSPARENT:
eaddr = pcap_ether_hostton(name);
if (eaddr == NULL)
eaddrp = pcap_ether_hostton(name);
if (eaddrp == NULL)
bpf_error(cstate,
"unknown ether host '%s'", name);
memcpy(eaddr, eaddrp, sizeof(eaddr));
free(eaddrp);
tmp = gen_prevlinkhdr_check(cstate);
b = gen_ehostop(cstate, eaddr, dir);
if (tmp != NULL)
gen_and(tmp, b);
free(eaddr);
return b;
case DLT_FDDI:
eaddr = pcap_ether_hostton(name);
if (eaddr == NULL)
eaddrp = pcap_ether_hostton(name);
if (eaddrp == NULL)
bpf_error(cstate,
"unknown FDDI host '%s'", name);
memcpy(eaddr, eaddrp, sizeof(eaddr));
free(eaddrp);
b = gen_fhostop(cstate, eaddr, dir);
free(eaddr);
return b;
case DLT_IEEE802:
eaddr = pcap_ether_hostton(name);
if (eaddr == NULL)
eaddrp = pcap_ether_hostton(name);
if (eaddrp == NULL)
bpf_error(cstate,
"unknown token ring host '%s'", name);
memcpy(eaddr, eaddrp, sizeof(eaddr));
free(eaddrp);
b = gen_thostop(cstate, eaddr, dir);
free(eaddr);
return b;
case DLT_IEEE802_11:
@ -7021,21 +7130,23 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
case DLT_IEEE802_11_RADIO_AVS:
case DLT_IEEE802_11_RADIO:
case DLT_PPI:
eaddr = pcap_ether_hostton(name);
if (eaddr == NULL)
eaddrp = pcap_ether_hostton(name);
if (eaddrp == NULL)
bpf_error(cstate,
"unknown 802.11 host '%s'", name);
memcpy(eaddr, eaddrp, sizeof(eaddr));
free(eaddrp);
b = gen_wlanhostop(cstate, eaddr, dir);
free(eaddr);
return b;
case DLT_IP_OVER_FC:
eaddr = pcap_ether_hostton(name);
if (eaddr == NULL)
eaddrp = pcap_ether_hostton(name);
if (eaddrp == NULL)
bpf_error(cstate,
"unknown Fibre Channel host '%s'", name);
memcpy(eaddr, eaddrp, sizeof(eaddr));
free(eaddrp);
b = gen_ipfchostop(cstate, eaddr, dir);
free(eaddr);
return b;
}
@ -7080,6 +7191,11 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
switch (res->ai_family) {
case AF_INET:
#ifdef INET6
/*
* Ignore any IPv4 addresses when resolving
* "ip6 host NAME", validate all other proto
* qualifiers in gen_host().
*/
if (tproto == Q_IPV6)
continue;
#endif
@ -7091,7 +7207,13 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
break;
#ifdef INET6
case AF_INET6:
if (tproto6 == Q_IP)
/*
* Ignore any IPv6 addresses when resolving
* "(arp|ip|rarp) host NAME", validate all
* other proto qualifiers in gen_host6().
*/
if (tproto6 == Q_ARP || tproto6 == Q_IP ||
tproto6 == Q_RARP)
continue;
sin6 = (struct sockaddr_in6 *)
@ -7204,9 +7326,11 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
case Q_GATEWAY:
#ifndef INET6
eaddr = pcap_ether_hostton(name);
if (eaddr == NULL)
eaddrp = pcap_ether_hostton(name);
if (eaddrp == NULL)
bpf_error(cstate, "unknown ether host: %s", name);
memcpy(eaddr, eaddrp, sizeof(eaddr));
free(eaddrp);
res = pcap_nametoaddrinfo(name);
cstate->ai = res;
@ -7252,6 +7376,7 @@ gen_mcode(compiler_state_t *cstate, const char *s1, const char *s2,
{
register int nlen, mlen;
bpf_u_int32 n, m;
uint64_t m64;
/*
* Catch errors reported by us and routines below us, and return NULL
@ -7279,14 +7404,8 @@ gen_mcode(compiler_state_t *cstate, const char *s1, const char *s2,
/* Convert mask len to mask */
if (masklen > 32)
bpf_error(cstate, "mask length must be <= 32");
if (masklen == 0) {
/*
* X << 32 is not guaranteed by C to be 0; it's
* undefined.
*/
m = 0;
} else
m = 0xffffffff << (32 - masklen);
m64 = UINT64_C(0xffffffff) << (32 - masklen);
m = (bpf_u_int32)m64;
if ((n & ~m) != 0)
bpf_error(cstate, "non-network bits set in \"%s/%d\"",
s1, masklen);
@ -7501,6 +7620,11 @@ gen_ecode(compiler_state_t *cstate, const char *s, struct qual q)
return (NULL);
if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
/*
* Because the lexer guards the input string format, in this
* context the function returns NULL iff the implicit malloc()
* has failed.
*/
cstate->e = pcap_ether_aton(s);
if (cstate->e == NULL)
bpf_error(cstate, "malloc");
@ -8212,8 +8336,6 @@ gen_byteop(compiler_state_t *cstate, int op, int idx, bpf_u_int32 val)
return b;
}
static const u_char abroadcast[] = { 0x0 };
struct block *
gen_broadcast(compiler_state_t *cstate, int proto)
{
@ -8235,7 +8357,8 @@ gen_broadcast(compiler_state_t *cstate, int proto)
switch (cstate->linktype) {
case DLT_ARCNET:
case DLT_ARCNET_LINUX:
return gen_ahostop(cstate, abroadcast, Q_DST);
// ARCnet broadcast is [8-bit] destination address 0.
return gen_ahostop(cstate, 0, Q_DST);
case DLT_EN10MB:
case DLT_NETANALYZER:
case DLT_NETANALYZER_TRANSPARENT:
@ -8320,8 +8443,8 @@ gen_multicast(compiler_state_t *cstate, int proto)
switch (cstate->linktype) {
case DLT_ARCNET:
case DLT_ARCNET_LINUX:
/* all ARCnet multicasts use the same address */
return gen_ahostop(cstate, abroadcast, Q_DST);
// ARCnet multicast is the same as broadcast.
return gen_ahostop(cstate, 0, Q_DST);
case DLT_EN10MB:
case DLT_NETANALYZER:
case DLT_NETANALYZER_TRANSPARENT:
@ -8470,7 +8593,12 @@ gen_multicast(compiler_state_t *cstate, int proto)
case Q_IP:
b0 = gen_linktype(cstate, ETHERTYPE_IP);
b1 = gen_cmp_ge(cstate, OR_LINKPL, 16, BPF_B, 224);
/*
* Compare address with 224.0.0.0/4
*/
b1 = gen_mcmp(cstate, OR_LINKPL, 16, BPF_B, 0xe0, 0xf0);
gen_and(b0, b1);
return b1;
@ -8896,11 +9024,10 @@ gen_p80211_fcdir(compiler_state_t *cstate, bpf_u_int32 fcdir)
return (b0);
}
// Process an ARCnet host address string.
struct block *
gen_acode(compiler_state_t *cstate, const char *s, struct qual q)
{
struct block *b;
/*
* Catch errors reported by us and routines below us, and return NULL
* on an error.
@ -8914,13 +9041,16 @@ gen_acode(compiler_state_t *cstate, const char *s, struct qual q)
case DLT_ARCNET_LINUX:
if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) &&
q.proto == Q_LINK) {
cstate->e = pcap_ether_aton(s);
if (cstate->e == NULL)
bpf_error(cstate, "malloc");
b = gen_ahostop(cstate, cstate->e, (int)q.dir);
free(cstate->e);
cstate->e = NULL;
return (b);
uint8_t addr;
/*
* The lexer currently defines the address format in a
* way that makes this error condition never true.
* Let's check it anyway in case this part of the lexer
* changes in future.
*/
if (! pcapint_atoan(s, &addr))
bpf_error(cstate, "invalid ARCnet address '%s'", s);
return gen_ahostop(cstate, addr, (int)q.dir);
} else
bpf_error(cstate, "ARCnet address used in non-arc expression");
/*NOTREACHED*/
@ -8931,18 +9061,25 @@ gen_acode(compiler_state_t *cstate, const char *s, struct qual q)
}
}
// Compare an ARCnet host address with the given value.
static struct block *
gen_ahostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
gen_ahostop(compiler_state_t *cstate, const uint8_t eaddr, int dir)
{
register struct block *b0, *b1;
switch (dir) {
/* src comes first, different from Ethernet */
/*
* ARCnet is different from Ethernet: the source address comes before
* the destination address, each is one byte long. This holds for all
* three "buffer formats" in RFC 1201 Section 2.1, see also page 4-10
* in the 1983 edition of the "ARCNET Designer's Handbook" published
* by Datapoint (document number 61610-01).
*/
case Q_SRC:
return gen_bcmp(cstate, OR_LINKHDR, 0, 1, eaddr);
return gen_cmp(cstate, OR_LINKHDR, 0, BPF_B, eaddr);
case Q_DST:
return gen_bcmp(cstate, OR_LINKHDR, 1, 1, eaddr);
return gen_cmp(cstate, OR_LINKHDR, 1, BPF_B, eaddr);
case Q_AND:
b0 = gen_ahostop(cstate, eaddr, Q_SRC);
@ -9090,7 +9227,7 @@ gen_vlan_patch_vid_test(compiler_state_t *cstate, struct block *b_vid)
unsigned cnt;
s = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT;
s->s.k = (bpf_u_int32)(SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT);
/* true -> next instructions, false -> beginning of b_vid */
sjeq = new_stmt(cstate, JMP(BPF_JEQ));
@ -9098,8 +9235,8 @@ gen_vlan_patch_vid_test(compiler_state_t *cstate, struct block *b_vid)
sjeq->s.jf = b_vid->stmts;
sappend(s, sjeq);
s2 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
s2->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG;
s2 = new_stmt(cstate, BPF_LD|BPF_H|BPF_ABS);
s2->s.k = (bpf_u_int32)(SKF_AD_OFF + SKF_AD_VLAN_TAG);
sappend(s, s2);
sjeq->s.jt = s2;
@ -9137,7 +9274,7 @@ gen_vlan_bpf_extensions(compiler_state_t *cstate, bpf_u_int32 vlan_num,
/* generate new filter code based on extracting packet
* metadata */
s = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT;
s->s.k = (bpf_u_int32)(SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT);
b0 = new_block(cstate, JMP(BPF_JEQ));
b0->stmts = s;
@ -9272,20 +9409,12 @@ gen_vlan(compiler_state_t *cstate, bpf_u_int32 vlan_num, int has_vlan_tag)
* label_num might be clobbered by longjmp - yeah, it might, but *WHO CARES*?
* It's not *used* after setjmp returns.
*/
struct block *
gen_mpls(compiler_state_t *cstate, bpf_u_int32 label_num_arg,
static struct block *
gen_mpls_internal(compiler_state_t *cstate, bpf_u_int32 label_num,
int has_label_num)
{
volatile bpf_u_int32 label_num = label_num_arg;
struct block *b0, *b1;
/*
* Catch errors reported by us and routines below us, and return NULL
* on an error.
*/
if (setjmp(cstate->top_ctx))
return (NULL);
if (cstate->label_stack_depth > 0) {
/* just match the bottom-of-stack bit clear */
b0 = gen_mcmp(cstate, OR_PREVMPLSHDR, 2, BPF_B, 0, 0x01);
@ -9352,6 +9481,19 @@ gen_mpls(compiler_state_t *cstate, bpf_u_int32 label_num_arg,
return (b0);
}
struct block *
gen_mpls(compiler_state_t *cstate, bpf_u_int32 label_num, int has_label_num)
{
/*
* Catch errors reported by us and routines below us, and return NULL
* on an error.
*/
if (setjmp(cstate->top_ctx))
return (NULL);
return gen_mpls_internal(cstate, label_num, has_label_num);
}
/*
* Support PPPOE discovery and session.
*/
@ -10024,16 +10166,10 @@ gen_mtp2type_abbrev(compiler_state_t *cstate, int type)
return b0;
}
/*
* The jvalue_arg dance is to avoid annoying whining by compilers that
* jvalue might be clobbered by longjmp - yeah, it might, but *WHO CARES*?
* It's not *used* after setjmp returns.
*/
struct block *
gen_mtp3field_code(compiler_state_t *cstate, int mtp3field,
bpf_u_int32 jvalue_arg, int jtype, int reverse)
static struct block *
gen_mtp3field_code_internal(compiler_state_t *cstate, int mtp3field,
bpf_u_int32 jvalue, int jtype, int reverse)
{
volatile bpf_u_int32 jvalue = jvalue_arg;
struct block *b0;
bpf_u_int32 val1 , val2 , val3;
u_int newoff_sio;
@ -10041,13 +10177,6 @@ gen_mtp3field_code(compiler_state_t *cstate, int mtp3field,
u_int newoff_dpc;
u_int newoff_sls;
/*
* Catch errors reported by us and routines below us, and return NULL
* on an error.
*/
if (setjmp(cstate->top_ctx))
return (NULL);
newoff_sio = cstate->off_sio;
newoff_opc = cstate->off_opc;
newoff_dpc = cstate->off_dpc;
@ -10139,6 +10268,21 @@ gen_mtp3field_code(compiler_state_t *cstate, int mtp3field,
return b0;
}
struct block *
gen_mtp3field_code(compiler_state_t *cstate, int mtp3field,
bpf_u_int32 jvalue, int jtype, int reverse)
{
/*
* Catch errors reported by us and routines below us, and return NULL
* on an error.
*/
if (setjmp(cstate->top_ctx))
return (NULL);
return gen_mtp3field_code_internal(cstate, mtp3field, jvalue, jtype,
reverse);
}
static struct block *
gen_msg_abbrev(compiler_state_t *cstate, int type)
{

View file

@ -78,19 +78,6 @@
#include <stdlib.h>
#ifndef _WIN32
#include <sys/types.h>
#include <sys/socket.h>
#if __STDC__
struct mbuf;
struct rtentry;
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#endif /* _WIN32 */
#include <stdio.h>
#include "diag-control.h"

View file

@ -41,13 +41,13 @@
#define IEEE80211_FC0_VERSION_MASK 0x03
#define IEEE80211_FC0_VERSION_SHIFT 0
#define IEEE80211_FC0_VERSION_0 0x00
#define IEEE80211_FC0_TYPE_MASK 0x0c
#define IEEE80211_FC0_TYPE_MASK 0x0cU
#define IEEE80211_FC0_TYPE_SHIFT 2
#define IEEE80211_FC0_TYPE_MGT 0x00
#define IEEE80211_FC0_TYPE_CTL 0x04
#define IEEE80211_FC0_TYPE_DATA 0x08
#define IEEE80211_FC0_SUBTYPE_MASK 0xf0
#define IEEE80211_FC0_SUBTYPE_MASK 0xf0U
#define IEEE80211_FC0_SUBTYPE_SHIFT 4
/* for TYPE_MGT */
#define IEEE80211_FC0_SUBTYPE_ASSOC_REQ 0x00
@ -80,7 +80,7 @@
#define IEEE80211_FC0_SUBTYPE_QOS 0x80
#define IEEE80211_FC0_SUBTYPE_QOS_NULL 0xc0
#define IEEE80211_FC1_DIR_MASK 0x03
#define IEEE80211_FC1_DIR_MASK 0x03U
#define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */
#define IEEE80211_FC1_DIR_TODS 0x01 /* STA->AP */
#define IEEE80211_FC1_DIR_FROMDS 0x02 /* AP ->STA */

250
instrument-functions.c Normal file
View file

@ -0,0 +1,250 @@
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code
* distributions retain the above copyright notice and this paragraph
* in its entirety, and (2) distributions including binary code include
* the above copyright notice and this paragraph in its entirety in
* the documentation or other materials provided with the distribution.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND
* WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
* LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <bfd.h>
/*
* Generate instrumentation calls for entry and exit to functions.
* Just after function entry and just before function exit, the
* following profiling functions are called with the address of the
* current function and its call site (currently not use).
*
* The attribute 'no_instrument_function' causes this instrumentation is
* not done.
*
* These profiling functions call print_debug(). This function prints the
* current function name with indentation and call level.
* If entering in a function it prints also the calling function name with
* file name and line number.
*
* If the environment variable INSTRUMENT is
* unset or set to an empty string, print nothing, like with no instrumentation
* set to "all" or "a", print all the functions names
* set to "global" or "g", print only the global functions names
*/
#define ND_NO_INSTRUMENT __attribute__((no_instrument_function))
/* Store the function call level, used also in pretty_print_packet() */
extern int profile_func_level;
int profile_func_level = -1;
typedef enum {
ENTER,
EXIT
} action_type;
void __cyg_profile_func_enter(void *this_fn, void *call_site) ND_NO_INSTRUMENT;
void __cyg_profile_func_exit(void *this_fn, void *call_site) ND_NO_INSTRUMENT;
static void print_debug(void *this_fn, void *call_site, action_type action)
ND_NO_INSTRUMENT;
void
__cyg_profile_func_enter(void *this_fn, void *call_site)
{
print_debug(this_fn, call_site, ENTER);
}
void
__cyg_profile_func_exit(void *this_fn, void *call_site)
{
print_debug(this_fn, call_site, EXIT);
}
static void print_debug(void *this_fn, void *call_site, action_type action)
{
static bfd* abfd;
static asymbol **symtab;
static long symcount;
static asection *text;
static bfd_vma vma;
static int instrument_set;
static int instrument_off;
static int instrument_global;
if (!instrument_set) {
static char *instrument_type;
/* Get the configuration environment variable INSTRUMENT value if any */
instrument_type = getenv("INSTRUMENT");
/* unset or set to an empty string ? */
if (instrument_type == NULL ||
!strncmp(instrument_type, "", sizeof(""))) {
instrument_off = 1;
} else {
/* set to "global" or "g" ? */
if (!strncmp(instrument_type, "global", sizeof("global")) ||
!strncmp(instrument_type, "g", sizeof("g")))
instrument_global = 1;
else if (strncmp(instrument_type, "all", sizeof("all")) &&
strncmp(instrument_type, "a", sizeof("a"))) {
fprintf(stderr, "INSTRUMENT can be only \"\", \"all\", \"a\", "
"\"global\" or \"g\".\n");
exit(1);
}
}
instrument_set = 1;
}
if (instrument_off)
return;
/* If no errors, this block should be executed one time */
if (!abfd) {
char pgm_name[1024];
long symsize;
ssize_t ret = readlink("/proc/self/exe", pgm_name, sizeof(pgm_name));
if (ret == -1) {
perror("failed to find executable");
return;
}
if (ret == sizeof(pgm_name)) {
/* no space for the '\0' */
printf("truncation may have occurred\n");
return;
}
pgm_name[ret] = '\0';
bfd_init();
abfd = bfd_openr(pgm_name, NULL);
if (!abfd) {
bfd_perror("bfd_openr");
return;
}
if (!bfd_check_format(abfd, bfd_object)) {
bfd_perror("bfd_check_format");
return;
}
if((symsize = bfd_get_symtab_upper_bound(abfd)) == -1) {
bfd_perror("bfd_get_symtab_upper_bound");
return;
}
symtab = (asymbol **)malloc((size_t)symsize);
symcount = bfd_canonicalize_symtab(abfd, symtab);
if (symcount < 0) {
free(symtab);
bfd_perror("bfd_canonicalize_symtab");
return;
}
if ((text = bfd_get_section_by_name(abfd, ".text")) == NULL) {
bfd_perror("bfd_get_section_by_name");
return;
}
vma = text->vma;
}
if (instrument_global) {
symbol_info syminfo;
int found;
long i;
i = 0;
found = 0;
while (i < symcount && !found) {
bfd_get_symbol_info(abfd, symtab[i], &syminfo);
if ((void *)syminfo.value == this_fn) {
found = 1;
}
i++;
}
/* type == 'T' for a global function */
if (found == 1 && syminfo.type != 'T')
return;
}
/* Current function */
if ((bfd_vma)this_fn < vma) {
printf("[ERROR address this_fn]");
} else {
const char *file;
const char *func;
unsigned int line;
if (!bfd_find_nearest_line(abfd, text, symtab, (bfd_vma)this_fn - vma,
&file, &func, &line)) {
printf("[ERROR bfd_find_nearest_line this_fn]");
} else {
int i;
if (action == ENTER)
profile_func_level += 1;
/* Indentation */
for (i = 0 ; i < profile_func_level ; i++)
putchar(' ');
if (action == ENTER)
printf("[>> ");
else
printf("[<< ");
/* Function name */
if (func == NULL || *func == '\0')
printf("???");
else
printf("%s", func);
printf(" (%d)", profile_func_level);
/* Print the "from" part except for the main function) */
if (action == ENTER && func != NULL &&
strncmp(func, "main", sizeof("main"))) {
/* Calling function */
if ((bfd_vma)call_site < vma) {
printf("[ERROR address call_site]");
} else {
if (!bfd_find_nearest_line(abfd, text, symtab,
(bfd_vma)call_site - vma, &file,
&func, &line)) {
printf("[ERROR bfd_find_nearest_line call_site]");
} else {
printf(" from ");
/* Function name */
if (func == NULL || *func == '\0')
printf("???");
else
printf("%s", func);
/* File name */
if (file == NULL || *file == '\0')
printf(" ??:");
else {
char *slashp = strrchr(file, '/');
if (slashp != NULL)
file = slashp + 1;
printf(" %s:", file);
}
/* Line number */
if (line == 0)
printf("?");
else
printf("%u", line);
printf("]");
}
}
}
putchar('\n');
if (action == EXIT)
profile_func_level -= 1;
}
}
fflush(stdout);
}
/* vi: set tabstop=4 softtabstop=0 shiftwidth=4 smarttab autoindent : */

View file

@ -32,31 +32,6 @@
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#ifdef INET6
/*
* To quote the MSDN page for getaddrinfo() at
*
* https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx
*
* "Support for getaddrinfo on Windows 2000 and older versions
* The getaddrinfo function was added to the Ws2_32.dll on Windows XP and
* later. To execute an application that uses this function on earlier
* versions of Windows, then you need to include the Ws2tcpip.h and
* Wspiapi.h files. When the Wspiapi.h include file is added, the
* getaddrinfo function is defined to the WspiapiGetAddrInfo inline
* function in the Wspiapi.h file. At runtime, the WspiapiGetAddrInfo
* function is implemented in such a way that if the Ws2_32.dll or the
* Wship6.dll (the file containing getaddrinfo in the IPv6 Technology
* Preview for Windows 2000) does not include getaddrinfo, then a
* version of getaddrinfo is implemented inline based on code in the
* Wspiapi.h header file. This inline code will be used on older Windows
* platforms that do not natively support the getaddrinfo function."
*
* We use getaddrinfo(), so we include Wspiapi.h here.
*/
#include <wspiapi.h>
#endif /* INET6 */
#else /* _WIN32 */
#include <sys/param.h>
#include <sys/types.h>
@ -639,7 +614,7 @@ pcap_nametollc(const char *s)
/* Hex digit to 8-bit unsigned integer. */
static inline u_char
xdtoi(u_char c)
pcapint_xdtoi(u_char c)
{
if (c >= '0' && c <= '9')
return (u_char)(c - '0');
@ -697,38 +672,417 @@ __pcap_atodn(const char *s, bpf_u_int32 *addr)
}
/*
* Convert 's', which can have the one of the forms:
* libpcap ARCnet address format is "^\$[0-9a-fA-F]{1,2}$" in regexp syntax.
* Iff the given string is a well-formed ARCnet address, parse the string,
* store the 8-bit unsigned value into the provided integer and return 1.
* Otherwise return 0.
*
* "xx:xx:xx:xx:xx:xx"
* "xx.xx.xx.xx.xx.xx"
* "xx-xx-xx-xx-xx-xx"
* "xxxx.xxxx.xxxx"
* "xxxxxxxxxxxx"
* --> START -- $ --> DOLLAR -- [0-9a-fA-F] --> HEX1 -- \0 -->-+
* | | | |
* [.] [.] [0-9a-fA-F] |
* | | | |
* v v v v
* (invalid) <--------+-<---------------[.]-- HEX2 -- \0 -->-+--> (valid)
*/
int
pcapint_atoan(const char *s, uint8_t *addr)
{
enum {
START,
DOLLAR,
HEX1,
HEX2,
} fsm_state = START;
uint8_t tmp = 0;
while (*s) {
switch (fsm_state) {
case START:
if (*s != '$')
goto invalid;
fsm_state = DOLLAR;
break;
case DOLLAR:
if (! PCAP_ISXDIGIT(*s))
goto invalid;
tmp = pcapint_xdtoi(*s);
fsm_state = HEX1;
break;
case HEX1:
if (! PCAP_ISXDIGIT(*s))
goto invalid;
tmp <<= 4;
tmp |= pcapint_xdtoi(*s);
fsm_state = HEX2;
break;
case HEX2:
goto invalid;
} // switch
s++;
} // while
if (fsm_state == HEX1 || fsm_state == HEX2) {
*addr = tmp;
return 1;
}
invalid:
return 0;
}
// Man page: "xxxxxxxxxxxx", regexp: "^[0-9a-fA-F]{12}$".
static u_char
pcapint_atomac48_xxxxxxxxxxxx(const char *s, uint8_t *addr)
{
if (strlen(s) == 12 &&
PCAP_ISXDIGIT(s[0]) &&
PCAP_ISXDIGIT(s[1]) &&
PCAP_ISXDIGIT(s[2]) &&
PCAP_ISXDIGIT(s[3]) &&
PCAP_ISXDIGIT(s[4]) &&
PCAP_ISXDIGIT(s[5]) &&
PCAP_ISXDIGIT(s[6]) &&
PCAP_ISXDIGIT(s[7]) &&
PCAP_ISXDIGIT(s[8]) &&
PCAP_ISXDIGIT(s[9]) &&
PCAP_ISXDIGIT(s[10]) &&
PCAP_ISXDIGIT(s[11])) {
addr[0] = pcapint_xdtoi(s[0]) << 4 | pcapint_xdtoi(s[1]);
addr[1] = pcapint_xdtoi(s[2]) << 4 | pcapint_xdtoi(s[3]);
addr[2] = pcapint_xdtoi(s[4]) << 4 | pcapint_xdtoi(s[5]);
addr[3] = pcapint_xdtoi(s[6]) << 4 | pcapint_xdtoi(s[7]);
addr[4] = pcapint_xdtoi(s[8]) << 4 | pcapint_xdtoi(s[9]);
addr[5] = pcapint_xdtoi(s[10]) << 4 | pcapint_xdtoi(s[11]);
return 1;
}
return 0;
}
// Man page: "xxxx.xxxx.xxxx", regexp: "^[0-9a-fA-F]{4}(\.[0-9a-fA-F]{4}){2}$".
static u_char
pcapint_atomac48_xxxx_3_times(const char *s, uint8_t *addr)
{
const char sep = '.';
if (strlen(s) == 14 &&
PCAP_ISXDIGIT(s[0]) &&
PCAP_ISXDIGIT(s[1]) &&
PCAP_ISXDIGIT(s[2]) &&
PCAP_ISXDIGIT(s[3]) &&
s[4] == sep &&
PCAP_ISXDIGIT(s[5]) &&
PCAP_ISXDIGIT(s[6]) &&
PCAP_ISXDIGIT(s[7]) &&
PCAP_ISXDIGIT(s[8]) &&
s[9] == sep &&
PCAP_ISXDIGIT(s[10]) &&
PCAP_ISXDIGIT(s[11]) &&
PCAP_ISXDIGIT(s[12]) &&
PCAP_ISXDIGIT(s[13])) {
addr[0] = pcapint_xdtoi(s[0]) << 4 | pcapint_xdtoi(s[1]);
addr[1] = pcapint_xdtoi(s[2]) << 4 | pcapint_xdtoi(s[3]);
addr[2] = pcapint_xdtoi(s[5]) << 4 | pcapint_xdtoi(s[6]);
addr[3] = pcapint_xdtoi(s[7]) << 4 | pcapint_xdtoi(s[8]);
addr[4] = pcapint_xdtoi(s[10]) << 4 | pcapint_xdtoi(s[11]);
addr[5] = pcapint_xdtoi(s[12]) << 4 | pcapint_xdtoi(s[13]);
return 1;
}
return 0;
}
/*
* Man page: "xx:xx:xx:xx:xx:xx", regexp: "^[0-9a-fA-F]{1,2}(:[0-9a-fA-F]{1,2}){5}$".
* Man page: "xx-xx-xx-xx-xx-xx", regexp: "^[0-9a-fA-F]{1,2}(-[0-9a-fA-F]{1,2}){5}$".
* Man page: "xx.xx.xx.xx.xx.xx", regexp: "^[0-9a-fA-F]{1,2}(\.[0-9a-fA-F]{1,2}){5}$".
* (Any "xx" above can be "x", which is equivalent to "0x".)
*
* (or various mixes of ':', '.', and '-') into a new
* ethernet address. Assumes 's' is well formed.
* An equivalent (and parametrisable for EUI-64) FSM could be implemented using
* a smaller graph, but that graph would be neither acyclic nor planar nor
* trivial to verify.
*
* |
* [.] v
* +<---------- START
* | |
* | | [0-9a-fA-F]
* | [.] v
* +<--------- BYTE0_X ----------+
* | | |
* | | [0-9a-fA-F] |
* | [.] v |
* +<--------- BYTE0_XX | [:\.-]
* | | |
* | | [:\.-] |
* | [.] v |
* +<----- BYTE0_SEP_BYTE1 <-----+
* | |
* | | [0-9a-fA-F]
* | [.] v
* +<--------- BYTE1_X ----------+
* | | |
* | | [0-9a-fA-F] |
* | [.] v |
* +<--------- BYTE1_XX | <sep>
* | | |
* | | <sep> |
* | [.] v |
* +<----- BYTE1_SEP_BYTE2 <-----+
* | |
* | | [0-9a-fA-F]
* | [.] v
* +<--------- BYTE2_X ----------+
* | | |
* | | [0-9a-fA-F] |
* | [.] v |
* +<--------- BYTE2_XX | <sep>
* | | |
* | | <sep> |
* | [.] v |
* +<----- BYTE2_SEP_BYTE3 <-----+
* | |
* | | [0-9a-fA-F]
* | [.] v
* +<--------- BYTE3_X ----------+
* | | |
* | | [0-9a-fA-F] |
* | [.] v |
* +<--------- BYTE3_XX | <sep>
* | | |
* | | <sep> |
* | [.] v |
* +<----- BYTE3_SEP_BYTE4 <-----+
* | |
* | | [0-9a-fA-F]
* | [.] v
* +<--------- BYTE4_X ----------+
* | | |
* | | [0-9a-fA-F] |
* | [.] v |
* +<--------- BYTE4_XX | <sep>
* | | |
* | | <sep> |
* | [.] v |
* +<----- BYTE4_SEP_BYTE5 <-----+
* | |
* | | [0-9a-fA-F]
* | [.] v
* +<--------- BYTE5_X ----------+
* | | |
* | | [0-9a-fA-F] |
* | [.] v |
* +<--------- BYTE5_XX | \0
* | | |
* | | \0 |
* | | v
* +--> (reject) +---------> (accept)
*
*/
static u_char
pcapint_atomac48_x_xx_6_times(const char *s, uint8_t *addr)
{
enum {
START,
BYTE0_X,
BYTE0_XX,
BYTE0_SEP_BYTE1,
BYTE1_X,
BYTE1_XX,
BYTE1_SEP_BYTE2,
BYTE2_X,
BYTE2_XX,
BYTE2_SEP_BYTE3,
BYTE3_X,
BYTE3_XX,
BYTE3_SEP_BYTE4,
BYTE4_X,
BYTE4_XX,
BYTE4_SEP_BYTE5,
BYTE5_X,
BYTE5_XX,
} fsm_state = START;
uint8_t buf[6];
const char *seplist = ":.-";
char sep;
while (*s) {
switch (fsm_state) {
case START:
if (PCAP_ISXDIGIT(*s)) {
buf[0] = pcapint_xdtoi(*s);
fsm_state = BYTE0_X;
break;
}
goto reject;
case BYTE0_X:
if (strchr(seplist, *s)) {
sep = *s;
fsm_state = BYTE0_SEP_BYTE1;
break;
}
if (PCAP_ISXDIGIT(*s)) {
buf[0] = buf[0] << 4 | pcapint_xdtoi(*s);
fsm_state = BYTE0_XX;
break;
}
goto reject;
case BYTE0_XX:
if (strchr(seplist, *s)) {
sep = *s;
fsm_state = BYTE0_SEP_BYTE1;
break;
}
goto reject;
case BYTE0_SEP_BYTE1:
if (PCAP_ISXDIGIT(*s)) {
buf[1] = pcapint_xdtoi(*s);
fsm_state = BYTE1_X;
break;
}
goto reject;
case BYTE1_X:
if (*s == sep) {
fsm_state = BYTE1_SEP_BYTE2;
break;
}
if (PCAP_ISXDIGIT(*s)) {
buf[1] = buf[1] << 4 | pcapint_xdtoi(*s);
fsm_state = BYTE1_XX;
break;
}
goto reject;
case BYTE1_XX:
if (*s == sep) {
fsm_state = BYTE1_SEP_BYTE2;
break;
}
goto reject;
case BYTE1_SEP_BYTE2:
if (PCAP_ISXDIGIT(*s)) {
buf[2] = pcapint_xdtoi(*s);
fsm_state = BYTE2_X;
break;
}
goto reject;
case BYTE2_X:
if (*s == sep) {
fsm_state = BYTE2_SEP_BYTE3;
break;
}
if (PCAP_ISXDIGIT(*s)) {
buf[2] = buf[2] << 4 | pcapint_xdtoi(*s);
fsm_state = BYTE2_XX;
break;
}
goto reject;
case BYTE2_XX:
if (*s == sep) {
fsm_state = BYTE2_SEP_BYTE3;
break;
}
goto reject;
case BYTE2_SEP_BYTE3:
if (PCAP_ISXDIGIT(*s)) {
buf[3] = pcapint_xdtoi(*s);
fsm_state = BYTE3_X;
break;
}
goto reject;
case BYTE3_X:
if (*s == sep) {
fsm_state = BYTE3_SEP_BYTE4;
break;
}
if (PCAP_ISXDIGIT(*s)) {
buf[3] = buf[3] << 4 | pcapint_xdtoi(*s);
fsm_state = BYTE3_XX;
break;
}
goto reject;
case BYTE3_XX:
if (*s == sep) {
fsm_state = BYTE3_SEP_BYTE4;
break;
}
goto reject;
case BYTE3_SEP_BYTE4:
if (PCAP_ISXDIGIT(*s)) {
buf[4] = pcapint_xdtoi(*s);
fsm_state = BYTE4_X;
break;
}
goto reject;
case BYTE4_X:
if (*s == sep) {
fsm_state = BYTE4_SEP_BYTE5;
break;
}
if (PCAP_ISXDIGIT(*s)) {
buf[4] = buf[4] << 4 | pcapint_xdtoi(*s);
fsm_state = BYTE4_XX;
break;
}
goto reject;
case BYTE4_XX:
if (*s == sep) {
fsm_state = BYTE4_SEP_BYTE5;
break;
}
goto reject;
case BYTE4_SEP_BYTE5:
if (PCAP_ISXDIGIT(*s)) {
buf[5] = pcapint_xdtoi(*s);
fsm_state = BYTE5_X;
break;
}
goto reject;
case BYTE5_X:
if (PCAP_ISXDIGIT(*s)) {
buf[5] = buf[5] << 4 | pcapint_xdtoi(*s);
fsm_state = BYTE5_XX;
break;
}
goto reject;
case BYTE5_XX:
goto reject;
} // switch
s++;
} // while
if (fsm_state == BYTE5_X || fsm_state == BYTE5_XX) {
// accept
memcpy(addr, buf, sizeof(buf));
return 1;
}
reject:
return 0;
}
// The 'addr' argument must point to an array of at least 6 elements.
static int
pcapint_atomac48(const char *s, uint8_t *addr)
{
return s && (
pcapint_atomac48_xxxxxxxxxxxx(s, addr) ||
pcapint_atomac48_xxxx_3_times(s, addr) ||
pcapint_atomac48_x_xx_6_times(s, addr)
);
}
/*
* If 's' is a MAC-48 address in one of the forms documented in pcap-filter(7)
* for "ether host", return a pointer to an allocated buffer with the binary
* value of the address. Return NULL on any error.
*/
u_char *
pcap_ether_aton(const char *s)
{
register u_char *ep, *e;
register u_char d;
e = ep = (u_char *)malloc(6);
if (e == NULL)
uint8_t tmp[6];
if (! pcapint_atomac48(s, tmp))
return (NULL);
while (*s) {
if (*s == ':' || *s == '.' || *s == '-')
s += 1;
d = xdtoi(*s++);
if (PCAP_ISXDIGIT(*s)) {
d <<= 4;
d |= xdtoi(*s++);
}
*ep++ = d;
}
u_char *e = malloc(6);
if (e == NULL)
return (NULL);
memcpy(e, tmp, sizeof(tmp));
return (e);
}

View file

@ -42,6 +42,7 @@ extern "C" {
int __pcap_atodn(const char *, bpf_u_int32 *);
int __pcap_atoin(const char *, bpf_u_int32 *);
int __pcap_nametodnaddr(const char *, u_short *);
extern int pcapint_atoan(const char *, uint8_t *);
#ifdef __cplusplus
}

View file

@ -117,7 +117,7 @@ pcap_set_print_dot_graph(int value)
#define lowest_set_bit(mask) ((u_int)__builtin_ctz(mask))
#elif defined(_MSC_VER)
/*
* Visual Studio; we support only 2005 and later, so use
* Visual Studio; we support only 2015 and later, so use
* _BitScanForward().
*/
#include <intrin.h>

View file

@ -73,16 +73,6 @@ static const char usbus_prefix[] = "usbus";
#include <net/bpf.h>
#define _AIX
/*
* If both BIOCROTZBUF and BPF_BUFMODE_ZBUF are defined, we have
* zero-copy BPF.
*/
#if defined(BIOCROTZBUF) && defined(BPF_BUFMODE_ZBUF)
#define HAVE_ZEROCOPY_BPF
#include <sys/mman.h>
#include <machine/atomic.h>
#endif
#include <net/if_types.h> /* for IFT_ values */
#include <sys/sysconfig.h>
#include <sys/device.h>
@ -126,6 +116,16 @@ static int bpf_load(char *errbuf);
# include <net/if_media.h>
#endif
/*
* If both BIOCROTZBUF and BPF_BUFMODE_ZBUF are defined, we have
* zero-copy BPF.
*/
#if defined(BIOCROTZBUF) && defined(BPF_BUFMODE_ZBUF)
#define HAVE_ZEROCOPY_BPF
#include <sys/mman.h>
#include <machine/atomic.h>
#endif
#include "pcap-int.h"
#ifdef HAVE_OS_PROTO_H
@ -290,7 +290,7 @@ pcap_setnonblock_bpf(pcap_t *p, int nonblock)
* buffer filled for a fresh BPF session.
*/
static int
pcap_next_zbuf_shm(pcap_t *p, int *cc)
pcap_next_zbuf_shm(pcap_t *p, ssize_t *cc)
{
struct pcap_bpf *pb = p->priv;
struct bpf_zbuf_header *bzh;
@ -328,7 +328,7 @@ pcap_next_zbuf_shm(pcap_t *p, int *cc)
* work.
*/
static int
pcap_next_zbuf(pcap_t *p, int *cc)
pcap_next_zbuf(pcap_t *p, ssize_t *cc)
{
struct pcap_bpf *pb = p->priv;
struct bpf_zbuf bz;
@ -336,7 +336,7 @@ pcap_next_zbuf(pcap_t *p, int *cc)
struct timespec cur;
fd_set r_set;
int data, r;
int expire, tmout;
long expire, tmout;
#define TSTOMILLI(ts) (((ts)->tv_sec * 1000) + ((ts)->tv_nsec / 1000000))
/*
@ -2182,7 +2182,7 @@ pcap_activate_bpf(pcap_t *p)
status = PCAP_ERROR;
goto bad;
}
status = bpf_bind(fd, p->opt.device, ifnamsiz, p->errbuf);
status = bpf_bind(fd, p->opt.device, p->errbuf);
if (status != BPF_BIND_SUCCEEDED) {
if (status == BPF_BIND_BUFFER_TOO_BIG) {
/*
@ -3682,11 +3682,19 @@ pcap_set_datalink_bpf(pcap_t *p _U_, int dlt _U_)
/*
* Platform-specific information.
*/
#if defined(HAVE_ZEROCOPY_BPF) && defined(PCAP_SUPPORT_NETMAP)
#define ADDITIONAL_INFO_STRING "with zerocopy and netmap support"
#elif defined(HAVE_ZEROCOPY_BPF)
#define ADDITIONAL_INFO_STRING "with zerocopy support"
#elif defined(PCAP_SUPPORT_NETMAP)
#define ADDITIONAL_INFO_STRING "with netmap support"
#endif
const char *
pcap_lib_version(void)
{
#ifdef HAVE_ZEROCOPY_BPF
return (PCAP_VERSION_STRING " (with zerocopy support)");
#ifdef ADDITIONAL_INFO_STRING
return (PCAP_VERSION_STRING_WITH_ADDITIONAL_INFO(ADDITIONAL_INFO_STRING));
#else
return (PCAP_VERSION_STRING);
#endif

View file

@ -1199,6 +1199,8 @@
/*
* USB 2.0, 1.1, and 1.0 packets as transmitted over the cable.
* Deprecated in favor of speed specific LINKTYPEs: LINKTYPE_USB_2_0_LOW_SPEED,
* LINKTYPE_USB_2_0_FULL_SPEED and LINKTYPE_USB_2_0_HIGH_SPEED.
*/
#define LINKTYPE_USB_2_0 288
@ -1207,7 +1209,91 @@
*/
#define LINKTYPE_ATSC_ALP 289
#define LINKTYPE_HIGH_MATCHING_MAX 289 /* highest value in the "matching" range */
/*
* Event Tracing for Windows messages.
*/
#define LINKTYPE_ETW 290
/*
* Hilscher Gesellschaft fuer Systemautomation mbH
* netANALYZER NG hardware and software.
*
* The specification for this footer can be found at:
* https://kb.hilscher.com/x/brDJBw
*
* Requested by Jan Adam <jadam@hilscher.com>
*/
#define LINKTYPE_NETANALYZER_NG 291
/*
* Serial NCP (Network Co-Processor) protocol for Zigbee stack ZBOSS
* by DSR, https://dsr-iot.com/downloads
*/
#define LINKTYPE_ZBOSS_NCP 292
/*
* USB 2.0, 1.1, and 1.0 packets as transmitted over the cable.
*/
#define LINKTYPE_USB_2_0_LOW_SPEED 293
#define LINKTYPE_USB_2_0_FULL_SPEED 294
#define LINKTYPE_USB_2_0_HIGH_SPEED 295
/*
* Auerswald Logger Protocol
* description is provided on
* https://github.com/Auerswald-GmbH/auerlog/blob/master/auerlog.txt
* requested by Auerswald Developer Team <developer(at)auerswald.de>
*/
#define LINKTYPE_AUERSWALD_LOG 296
/*
* Z-Wave packets with a TAP meta-data header
* https://gitlab.com/exegin/zwave-g9959-tap
* requested on tcpdump-workers@
*/
#define LINKTYPE_ZWAVE_TAP 297
/*
* Silicon Labs debug channel protocol:
*/
#define LINKTYPE_SILABS_DEBUG_CHANNEL 298
/*
* Ultra-wideband (UWB) controller interface protocol (UCI).
*/
#define LINKTYPE_FIRA_UCI 299
/*
* MDB (Multi-Drop Bus) protocol between a vending machine controller and
* peripherals inside the vending machine. See
*
* https://www.kaiser.cx/pcap-mdb.html
*
* for the specification.
*
* Requested by Martin Kaiser <martin@kaiser.cx>.
*/
#define LINKTYPE_MDB 300
/*
* DECT-2020 New Radio (NR) - ETSI TS 103 636.
* Requested by Stig Bjorlykke <stig@bjorlykke.org>.
*/
#define LINKTYPE_DECT_NR 301
/*
* Request serialization protocol used by edk2 firmware to communicate between
* normal mode and management mode ('MM' for short).
*
* The qemu uefi variable store implementation reuses the request serialization
* protocol for firmware <-> qemu communication.
*/
#define LINKTYPE_EDK2_MM 302
// See DLT_DEBUG_ONLY
#define LINKTYPE_DEBUG_ONLY 303
#define LINKTYPE_HIGH_MATCHING_MAX 303 /* highest value in the "matching" range */
/*
* The DLT_ and LINKTYPE_ values in the "matching" range should be the
@ -1274,7 +1360,7 @@ dlt_to_linktype(int dlt)
/*
* These DLT_* codes have different values on different
* platforms, so we assigned them LINKTYPE_* codes just
* below the lower bound of the high matchig range;
* below the lower bound of the high matching range;
* those values should never be equal to any DLT_*
* code, so that should avoid collisions.
*
@ -1426,7 +1512,7 @@ linktype_to_dlt(int linktype)
/*
* These DLT_* codes have different values on different
* platforms, so we assigned them LINKTYPE_* codes just
* below the lower bound of the high matchig range;
* below the lower bound of the high matching range;
* those values should never be equal to any DLT_*
* code, so that should avoid collisions.
*

View file

@ -1425,8 +1425,7 @@ pcapint_platform_finddevs(pcap_if_list_t *devlistp _U_, char *errbuf)
pcap_t *
pcapint_create_interface(const char *device, char *errbuf)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"This version of libpcap only supports DAG cards");
snprintf(errbuf, PCAP_ERRBUF_SIZE, PCAP_ENODEV_MESSAGE, "DAG");
return NULL;
}
@ -1436,6 +1435,6 @@ pcapint_create_interface(const char *device, char *errbuf)
const char *
pcap_lib_version(void)
{
return (PCAP_VERSION_STRING " (DAG-only)");
return (PCAP_VERSION_STRING_WITH_ADDITIONAL_INFO("DAG-only"));
}
#endif

View file

@ -80,6 +80,7 @@ dbus_read(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_char *us
if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Disconnected");
dbus_message_unref(message);
return -1;
}
@ -97,6 +98,9 @@ dbus_read(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_char *us
dbus_free(raw_msg);
}
dbus_message_unref(message);
return count;
}

View file

@ -20,7 +20,7 @@
*
* This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk),
* University College London, and subsequently modified by
* Guy Harris (guy@alum.mit.edu), Mark Pizzolato
* Guy Harris, Mark Pizzolato
* <List-tcpdump-workers@subscriptions.pizzolato.net>,
* Mark C. Brown (mbrown@hp.com), and Sagun Shakya <Sagun.Shakya@Sun.COM>.
*/
@ -336,14 +336,156 @@ pcap_cleanup_dlpi(pcap_t *p)
pcapint_cleanup_live_common(p);
}
#ifdef HAVE_DEV_DLPI
static int
handle_dev_dlpi_open_error(const char *ifname, int error, char *errbuf)
{
/*
* An attempt to open /dev/dlpi failed.
* Report the appropriate error.
*/
if (error == ENOENT) {
/*
* Missing; I guess that means we don't support
* opening DLPI devices, and thus can't capture
* traffic at all.
*/
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Capturing network traffic not supported - /dev/dlpi doesn't exist");
return (PCAP_ERROR_CAPTURE_NOTSUP);
} else if (error == EPERM || error == EACCES) {
/*
* We lack permission to open it.
*
* If the interface exists, report the permission error,
* otherwise report "no such interface".
*/
int fd;
struct ifreq ifr;
if (strlen(ifname) >= sizeof(ifr.ifr_name)) {
/*
* The name is too long, so it can't possibly exist.
* Report that.
*
* There's nothing more to say, so clear
* the error message.
*/
errbuf[0] = '\0';
return (PCAP_ERROR_NO_SUCH_DEVICE);
}
/*
* Try to get a socket on which to do an ioctl to get the
* interface's flags.
*/
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
/* That failed; report that as the error. */
pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
errno, "Can't open socket to get interface flags");
return (PCAP_ERROR);
}
pcapint_strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
if (errno == ENXIO || errno == EINVAL) {
/*
* macOS, *BSD, and Solaris return one of
* those two errors if the device doesn't
* exist. Report that.
* XXX - what about HP-UX?
*
* There's nothing more to say, so clear
* the error message.
*/
errbuf[0] = '\0';
close(fd);
return (PCAP_ERROR_NO_SUCH_DEVICE);
}
/*
* Some other error.
*/
pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
errno, "Can't get interface flags");
close(fd);
return (PCAP_ERROR);
}
/*
* The device exists; report this as a permissions problem.
*/
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Attempt to open /dev/dlpi failed with %s - root privilege may be required",
(error == EPERM) ? "EPERM" : "EACCES");
close(fd);
return (PCAP_ERROR_PERM_DENIED);
} else {
/*
* Soe other error.
*/
pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
error, "Attempt to open /dev/dlpi failed");
return (PCAP_ERROR);
}
}
#else /* HAVE_DEV_DLPI */
static int
handle_dlpi_device_open_error(const char *ifname, const char *device,
int error, char *errbuf)
{
/*
* We couldn't open a DLPI device.
* Was that due to a permission error?
*/
if (error == EPERM || error == EACCES) {
/*
* We lack permission to open it.
*
* If the interface doesn't exist, there wouldn't be
* a DLPI device corresponding to it, so we wouldn't
* have gotten a permissions error.
*/
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Attempt to open %s failed with %s - root privilege may be required",
device, (error == EPERM) ? "EPERM" : "EACCES");
return (PCAP_ERROR_PERM_DENIED);
}
/*
* Was that due to the DLPI device not existing?
*/
if (error != ENOENT) {
/*
* No; report it as a generic error, giving the error
* message for the error code and the name of the
* device we tried to open.
*/
pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
error, "Attempt to open %s failed", device);
return (PCAP_ERROR);
}
/*
* Yes. That means we can't do DLPI capturing, at least not
* on that interface.
*
* Test whether it exists and, if it does, whether it's
* a loopback interface.
*/
return (handle_nonexistent_dlpi_device(ifname, errbuf));
}
#endif /* not HAVE_DEV_DLPI */
static int
open_dlpi_device(const char *name, u_int *ppa, char *errbuf)
{
int status;
char dname[100];
char *cp;
char *cp, *cq;
int fd;
#ifdef HAVE_DEV_DLPI
int status;
u_int unit;
#else
char dname2[100];
@ -359,6 +501,32 @@ open_dlpi_device(const char *name, u_int *ppa, char *errbuf)
else
pcapint_strlcpy(dname, cp + 1, sizeof(dname));
/*
* If this name has a colon followed by a number at
* the end, it's a logical interface. Those are just
* the way you assign multiple IP addresses to a real
* interface, so an entry for a logical interface should
* be treated like the entry for the real interface;
* we do that by stripping off the ":" and the number.
*/
cp = strchr(dname, ':');
if (cp != NULL) {
/*
* We have a ":"; is it followed by a number?
*/
cq = cp + 1;
while (PCAP_ISDIGIT(*cq))
cq++;
if (*cq == '\0') {
/*
* All digits after the ":" until the end.
* Strip off the ":" and everything after
* it.
*/
*cp = '\0';
}
}
/*
* Split the device name into a device type name and a unit number;
* chop off the unit number, so "dname" is just a device type name.
@ -383,20 +551,8 @@ open_dlpi_device(const char *name, u_int *ppa, char *errbuf)
* search "/dev" for the appropriate device with that major
* device number, rather than hardwiring "/dev/dlpi".
*/
cp = "/dev/dlpi";
if ((fd = open(cp, O_RDWR)) < 0) {
if (errno == EPERM || errno == EACCES) {
status = PCAP_ERROR_PERM_DENIED;
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Attempt to open %s failed with %s - root privilege may be required",
cp, (errno == EPERM) ? "EPERM" : "EACCES");
} else {
status = PCAP_ERROR;
pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
errno, "Attempt to open %s failed", cp);
}
return (status);
}
if ((fd = open("/dev/dlpi", O_RDWR)) < 0)
return (handle_dev_dlpi_open_error(name, errno, errbuf));
/*
* Get a table of all PPAs for that device, and search that
@ -420,6 +576,32 @@ open_dlpi_device(const char *name, u_int *ppa, char *errbuf)
snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX,
name);
/*
* If this name has a colon followed by a number at
* the end, it's a logical interface. Those are just
* the way you assign multiple IP addresses to a real
* interface, so an entry for a logical interface should
* be treated like the entry for the real interface;
* we do that by stripping off the ":" and the number.
*/
cp = strchr(dname, ':');
if (cp != NULL) {
/*
* We have a ":"; is it followed by a number?
*/
cq = cp + 1;
while (PCAP_ISDIGIT(*cq))
cq++;
if (*cq == '\0') {
/*
* All digits after the ":" until the end.
* Strip off the ":" and everything after
* it.
*/
*cp = '\0';
}
}
/*
* Get the unit number, and a pointer to the end of the device
* type name.
@ -441,69 +623,20 @@ open_dlpi_device(const char *name, u_int *ppa, char *errbuf)
/* Try device without unit number */
if ((fd = open(dname, O_RDWR)) < 0) {
if (errno != ENOENT) {
if (errno == EPERM || errno == EACCES) {
status = PCAP_ERROR_PERM_DENIED;
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Attempt to open %s failed with %s - root privilege may be required",
dname,
(errno == EPERM) ? "EPERM" : "EACCES");
} else {
status = PCAP_ERROR;
pcapint_fmt_errmsg_for_errno(errbuf,
PCAP_ERRBUF_SIZE, errno,
"Attempt to open %s failed", dname);
}
return (status);
}
if (errno != ENOENT)
return (handle_dlpi_device_open_error(name, dname,
errno, errbuf));
/* Try again with unit number */
if ((fd = open(dname2, O_RDWR)) < 0) {
if (errno == ENOENT) {
status = PCAP_ERROR_NO_SUCH_DEVICE;
/*
* We provide an error message even
* for this error, for diagnostic
* purposes (so that, for example,
* the app can show the message if the
* user requests it).
*
* In it, we just report "No DLPI device
* found" with the device name, so people
* don't get confused and think, for example,
* that if they can't capture on "lo0"
* on Solaris prior to Solaris 11 the fix
* is to change libpcap (or the application
* that uses it) to look for something other
* than "/dev/lo0", as the fix is to use
* Solaris 11 or some operating system
* other than Solaris - you just *can't*
* capture on a loopback interface
* on Solaris prior to Solaris 11, the lack
* of a DLPI device for the loopback
* interface is just a symptom of that
* inability.
*/
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"%s: No DLPI device found", name);
} else {
if (errno == EPERM || errno == EACCES) {
status = PCAP_ERROR_PERM_DENIED;
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Attempt to open %s failed with %s - root privilege may be required",
dname2,
(errno == EPERM) ? "EPERM" : "EACCES");
} else {
status = PCAP_ERROR;
pcapint_fmt_errmsg_for_errno(errbuf,
PCAP_ERRBUF_SIZE, errno,
"Attempt to open %s failed",
dname2);
}
}
return (status);
}
/*
* There's no DLPI device whose name is the interface
* name with the unit number removed.
*
* Try again with a device name that includes the
* unit number.
*/
if ((fd = open(dname2, O_RDWR)) < 0)
return (handle_dlpi_device_open_error(name, dname2,
errno, errbuf));
/* XXX Assume unit zero */
*ppa = 0;
}
@ -905,6 +1038,11 @@ split_dname(char *device, u_int *unitp, char *ebuf)
/* Digits at end of string are unit number */
while (cp-1 >= device && *(cp-1) >= '0' && *(cp-1) <= '9')
cp--;
if (cp == device || *(cp-1) == '/') {
snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s has only a unit number",
device);
return (NULL);
}
errno = 0;
unit = strtol(cp, &eos, 10);
@ -1025,52 +1163,16 @@ dlpromiscon(pcap_t *p, bpf_u_int32 level)
}
/*
* Not all interfaces are DLPI interfaces, and thus not all interfaces
* can be opened with DLPI (for example, the loopback interface is not
* a DLPI interface on Solaris prior to Solaris 11), so try to open
* the specified interface; return 0 if we fail with PCAP_ERROR_NO_SUCH_DEVICE
* and 1 otherwise.
* Show all interfaces, so users don't ask "why is this interface not
* showing up?" or "why are no interfaces showing up?" We report
* PCAP_ERROR_CAPTURE_NOTSUP if there's no DLPI device, with an
* error message that tries to explain the source of the problem,
* which is some flavor of "sorry, that's simply not supported by
* your OS".
*/
static int
is_dlpi_interface(const char *name)
show_them_all(const char *name _U_)
{
int fd;
u_int ppa;
char errbuf[PCAP_ERRBUF_SIZE];
fd = open_dlpi_device(name, &ppa, errbuf);
if (fd < 0) {
/*
* Error - was it PCAP_ERROR_NO_SUCH_DEVICE?
*/
if (fd == PCAP_ERROR_NO_SUCH_DEVICE) {
/*
* Yes, so we can't open this because it's
* not a DLPI interface.
*/
return (0);
}
/*
* No, so, in the case where there's a single DLPI
* device for all interfaces of this type ("style
* 2" providers?), we don't know whether it's a DLPI
* interface or not, as we didn't try an attach.
* Say it is a DLPI device, so that the user can at
* least try to open it and report the error (which
* is probably "you don't have permission to open that
* DLPI device"; reporting those interfaces means
* users will ask "why am I getting a permissions error
* when I try to capture" rather than "why am I not
* seeing any interfaces", making the underlying problem
* clearer).
*/
return (1);
}
/*
* Success.
*/
close(fd);
return (1);
}
@ -1114,7 +1216,7 @@ pcapint_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
/*
* Get the list of regular interfaces first.
*/
if (pcapint_findalldevs_interfaces(devlistp, errbuf, is_dlpi_interface,
if (pcapint_findalldevs_interfaces(devlistp, errbuf, show_them_all,
get_if_flags) == -1)
return (-1); /* failure */

View file

@ -1068,8 +1068,7 @@ pcapint_platform_finddevs(pcap_if_list_t *devlistp _U_, char *errbuf)
pcap_t *
pcapint_create_interface(const char *device, char *errbuf)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"This version of libpcap only supports DPDK");
snprintf(errbuf, PCAP_ERRBUF_SIZE, PCAP_ENODEV_MESSAGE, "DPDK");
return NULL;
}
@ -1079,6 +1078,6 @@ pcapint_create_interface(const char *device, char *errbuf)
const char *
pcap_lib_version(void)
{
return (PCAP_VERSION_STRING " (DPDK-only)");
return (PCAP_VERSION_STRING_WITH_ADDITIONAL_INFO("DPDK-only"));
}
#endif

View file

@ -212,7 +212,7 @@ pcap_inject_haiku(pcap_t *handle, const void *buffer _U_, int size _U_)
{
// Haiku currently (hrev57588) does not support sending raw packets.
// https://dev.haiku-os.org/ticket/18810
strlcpy(handle->errbuf, "Sending packets isn't supported yet",
pcapint_strlcpy(handle->errbuf, "Sending packets isn't supported yet",
PCAP_ERRBUF_SIZE);
return PCAP_ERROR;
}
@ -435,7 +435,8 @@ pcapint_create_interface(const char *device, char *errorBuffer)
struct pcap_haiku *handlep = (struct pcap_haiku *)handle->priv;
handlep->aux_socket = -1;
strcpy(handlep->ifreq.ifr_name, device);
// validate_ifname() has already checked "device" length.
(void)pcapint_strlcpy(handlep->ifreq.ifr_name, device, IF_NAMESIZE);
return handle;
}
@ -468,7 +469,8 @@ get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
if (fd < 0)
return PCAP_ERROR;
struct ifreq ifreq;
strcpy(ifreq.ifr_name, name);
// validate_ifname() has already checked "name" length.
(void)pcapint_strlcpy(ifreq.ifr_name, name, IF_NAMESIZE);
if (ioctl_ifreq(fd, SIOCGIFFLAGS, "SIOCGIFFLAGS", &ifreq, errbuf) < 0) {
close(fd);
return PCAP_ERROR;

View file

@ -73,10 +73,28 @@
#endif
/*
* Version string.
* Uses PACKAGE_VERSION from config.h.
* Version string trailer.
* Uses SIZEOF_TIME_T from config.h.
* (There's no need to announce the pointer size; if it doesn't
* match the pointer size in code linked with libpcap, either
* build-time linking or run-time linking will fail.)
*/
#define PCAP_VERSION_STRING "libpcap version " PACKAGE_VERSION
#if SIZEOF_TIME_T == 8
#define PCAP_SIZEOF_TIME_T_BITS_STRING "64"
#elif SIZEOF_TIME_T == 4
#define PCAP_SIZEOF_TIME_T_BITS_STRING "32"
#else
#error Unknown time_t size
#endif
/*
* Version string.
* Uses PACKAGE_VERSION from config.h and PCAP_SIZEOF_TIME_T_BITS_STRING.
*/
#define PCAP_VERSION_STRING \
"libpcap version " PACKAGE_VERSION " (" PCAP_SIZEOF_TIME_T_BITS_STRING "-bit time_t)"
#define PCAP_VERSION_STRING_WITH_ADDITIONAL_INFO(additional_info) \
"libpcap version " PACKAGE_VERSION " (" PCAP_SIZEOF_TIME_T_BITS_STRING "-bit time_t, " additional_info ")"
#ifdef __cplusplus
extern "C" {
@ -413,6 +431,14 @@ int pcapint_setnonblock_fd(pcap_t *p, int);
* by pcap_create routines.
*/
pcap_t *pcapint_create_interface(const char *, char *);
/*
* A format string for something-only libpcap builds, which use a stub
* implementation of pcapint_create_interface(). It contains the substring
* "No such device" (one of the standard descriptions of ENODEV) -- this way
* tcpdump can detect a particular error condition even though pcap_create()
* returns NULL for all errors.
*/
#define PCAP_ENODEV_MESSAGE "No such device (this build of libpcap supports %s devices only)."
/*
* This wrapper takes an error buffer pointer and a type to use for the
@ -530,10 +556,9 @@ FILE *pcapint_charset_fopen(const char *path, const char *mode);
*/
#ifdef _WIN32
#define pcap_code_handle_t HMODULE
#define pcap_funcptr_t FARPROC
pcap_code_handle_t pcapint_load_code(const char *);
pcap_funcptr_t pcapint_find_function(pcap_code_handle_t, const char *);
void *pcapint_find_function(pcap_code_handle_t, const char *);
#endif
/*

View file

@ -106,20 +106,47 @@ pcap_activate_libdlpi(pcap_t *p)
*/
retv = dlpi_open(p->opt.device, &dh, DLPI_RAW|DLPI_PASSIVE);
if (retv != DLPI_SUCCESS) {
if (retv == DLPI_ELINKNAMEINVAL || retv == DLPI_ENOLINK) {
if (retv == DLPI_ELINKNAMEINVAL) {
/*
* The interface name is not syntactiacally
* valid, and thus doesn't correspond to
* an interface.
*
* There's nothing more to say, so clear the
* error message.
*/
status = PCAP_ERROR_NO_SUCH_DEVICE;
p->errbuf[0] = '\0';
} else if (retv == DLPI_ENOLINK) {
/*
* The interface name is syntactically valid,
* but we don't have a DLPI device that
* would be used for that interface.
*/
status = handle_nonexistent_dlpi_device(p->opt.device,
p->errbuf);
} else if (retv == DL_SYSERR &&
(errno == EPERM || errno == EACCES)) {
/*
* We got EPERM or EACCES trying to open the
* DLPI device, so we know it exists.
*/
status = PCAP_ERROR_PERM_DENIED;
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Attempt to open DLPI device failed with %s - root privilege may be required",
(errno == EPERM) ? "EPERM" : "EACCES");
} else {
/*
* pcap_libdlpi_err() calls dlpi_strerror(),
* which handles DL_SYSERR.
*
* XXX - does DLPI_ERAWNOTSUP mean that the
* interface exists and supports DLPI but,
* as it doesn't support raw mode, it
* doesn't support packet capture?
*
* XXX - what does DLPI_EBADLINK mean?
*/
status = PCAP_ERROR;
pcap_libdlpi_err(p->opt.device, "dlpi_open", retv,
p->errbuf);
@ -131,7 +158,7 @@ pcap_activate_libdlpi(pcap_t *p)
if (p->opt.rfmon) {
/*
* This device exists, but we don't support monitor mode
* any platforms that support DLPI.
* on any platforms that support DLPI.
*/
status = PCAP_ERROR_RFMON_NOTSUP;
goto bad;
@ -488,7 +515,7 @@ pcap_cleanup_libdlpi(pcap_t *p)
static void
pcap_libdlpi_err(const char *linkname, const char *func, int err, char *errbuf)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "libpcap: %s failed on %s: %s",
snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s failed on %s: %s",
func, linkname, dlpi_strerror(err));
}

View file

@ -91,6 +91,7 @@
#include <linux/ethtool.h>
#include <netinet/in.h>
#include <linux/if_ether.h>
#include <linux/netlink.h>
#include <linux/if_arp.h>
#include <poll.h>
#include <dirent.h>
@ -213,8 +214,7 @@ struct pcap_linux {
/*
* Stuff to do when we close.
*/
#define MUST_CLEAR_RFMON 0x00000001 /* clear rfmon (monitor) mode */
#define MUST_DELETE_MONIF 0x00000002 /* delete monitor-mode interface */
#define MUST_DELETE_MONIF 0x00000001 /* delete monitor-mode interface */
/*
* Prototypes for internal functions and methods.
@ -457,9 +457,57 @@ get_mac80211_phydev(pcap_t *handle, const char *device, char *phydev_path,
}
bytes_read = readlink(pathstr, phydev_path, phydev_max_pathlen);
if (bytes_read == -1) {
if (errno == ENOENT || errno == EINVAL) {
if (errno == ENOENT) {
/*
* Doesn't exist, or not a symlink; assume that
* This either means that the directory
* /sys/class/net/{device} exists but doesn't
* have anything named "phy80211" in it,
* in which case it's not a mac80211 device,
* or that the directory doesn't exist,
* in which case the device doesn't exist.
*
* Directly check whether the directory
* exists.
*/
struct stat statb;
free(pathstr);
if (asprintf(&pathstr, "/sys/class/net/%s", device) == -1) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: Can't generate path name string for /sys/class/net device",
device);
return PCAP_ERROR;
}
if (stat(pathstr, &statb) == -1) {
if (errno == ENOENT) {
/*
* No such device.
*/
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: %s doesn't exist",
device, pathstr);
free(pathstr);
return PCAP_ERROR_NO_SUCH_DEVICE;
}
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: Can't stat %s: %s",
device, pathstr, strerror(errno));
free(pathstr);
return PCAP_ERROR;
}
/*
* Path to the directory that would contain
* "phy80211" exists, but "phy80211" doesn't
* exist; that means it's not a mac80211
* device.
*/
free(pathstr);
return 0;
}
if (errno == EINVAL) {
/*
* Exists, but it's not a symlink; assume that
* means it's not a mac80211 device.
*/
free(pathstr);
@ -535,6 +583,119 @@ static int
del_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
const char *device, const char *mondevice);
static int
if_type_cb(struct nl_msg *msg, void* arg)
{
struct nlmsghdr* ret_hdr = nlmsg_hdr(msg);
struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
int *type = (int*)arg;
struct genlmsghdr *gnlh = (struct genlmsghdr*) nlmsg_data(ret_hdr);
nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), NULL);
/*
* We sent a message asking for info about a single index.
* To be really paranoid, we could check if the index matched
* by examining nla_get_u32(tb_msg[NL80211_ATTR_IFINDEX]).
*/
if (tb_msg[NL80211_ATTR_IFTYPE]) {
*type = nla_get_u32(tb_msg[NL80211_ATTR_IFTYPE]);
}
return NL_SKIP;
}
static int
get_if_type(pcap_t *handle, int sock_fd, struct nl80211_state *state,
const char *device, int *type)
{
int ifindex;
struct nl_msg *msg;
int err;
ifindex = iface_get_id(sock_fd, device, handle->errbuf);
if (ifindex == -1)
return PCAP_ERROR;
msg = nlmsg_alloc();
if (!msg) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: failed to allocate netlink msg", device);
return PCAP_ERROR;
}
genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ,
genl_family_get_id(state->nl80211), 0,
0, NL80211_CMD_GET_INTERFACE, 0);
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
err = nl_send_auto(state->nl_sock, msg);
nlmsg_free(msg);
if (err < 0) {
if (err == -NLE_FAILURE) {
/*
* Device not available; our caller should just
* keep trying. (libnl 2.x maps ENFILE to
* NLE_FAILURE; it can also map other errors
* to that, but there's not much we can do
* about that.)
*/
return 0;
} else {
/*
* Real failure, not just "that device is not
* available.
*/
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: nl_send_auto failed getting interface type: %s",
device, nl_geterror(-err));
return PCAP_ERROR;
}
}
struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, if_type_cb, (void*)type);
err = nl_recvmsgs(state->nl_sock, cb);
nl_cb_put(cb);
if (err < 0) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: nl_recvmsgs failed getting interface type: %s",
device, nl_geterror(-err));
return PCAP_ERROR;
}
/*
* If this is a mac80211 device not in monitor mode, nl_sock will be
* reused for add_mon_if. So we must wait for the ACK here so that
* add_mon_if does not receive it instead and incorrectly interpret
* the ACK as its NEW_INTERFACE command succeeding, even when it fails.
*/
err = nl_wait_for_ack(state->nl_sock);
if (err < 0) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: nl_wait_for_ack failed getting interface type: %s",
device, nl_geterror(-err));
return PCAP_ERROR;
}
/*
* Success.
*/
return 1;
nla_put_failure:
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: nl_put failed getting interface type",
device);
nlmsg_free(msg);
// Do not call nl_cb_put(): nl_cb_alloc() has not been called.
return PCAP_ERROR;
}
static int
add_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
const char *device, const char *mondevice)
@ -555,7 +716,8 @@ add_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
return PCAP_ERROR;
}
genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ,
genl_family_get_id(state->nl80211), 0,
0, NL80211_CMD_NEW_INTERFACE, 0);
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
DIAG_OFF_NARROWING
@ -563,9 +725,12 @@ DIAG_OFF_NARROWING
DIAG_ON_NARROWING
NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR);
err = nl_send_auto_complete(state->nl_sock, msg);
err = nl_send_sync(state->nl_sock, msg); // calls nlmsg_free()
if (err < 0) {
if (err == -NLE_FAILURE) {
switch (err) {
case -NLE_FAILURE:
case -NLE_AGAIN:
/*
* Device not available; our caller should just
* keep trying. (libnl 2.x maps ENFILE to
@ -573,41 +738,25 @@ DIAG_ON_NARROWING
* to that, but there's not much we can do
* about that.)
*/
nlmsg_free(msg);
return 0;
} else {
case -NLE_OPNOTSUPP:
/*
* Device is a mac80211 device but adding it as a
* monitor mode device isn't supported. Report our
* error.
*/
return PCAP_ERROR_RFMON_NOTSUP;
default:
/*
* Real failure, not just "that device is not
* available.
* available." Report a generic error, using the
* error message from libnl.
*/
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: nl_send_auto_complete failed adding %s interface: %s",
"%s: nl_send_sync failed adding %s interface: %s",
device, mondevice, nl_geterror(-err));
nlmsg_free(msg);
return PCAP_ERROR;
}
}
err = nl_wait_for_ack(state->nl_sock);
if (err < 0) {
if (err == -NLE_FAILURE) {
/*
* Device not available; our caller should just
* keep trying. (libnl 2.x maps ENFILE to
* NLE_FAILURE; it can also map other errors
* to that, but there's not much we can do
* about that.)
*/
nlmsg_free(msg);
return 0;
} else {
/*
* Real failure, not just "that device is not
* available.
*/
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: nl_wait_for_ack failed adding %s interface: %s",
device, mondevice, nl_geterror(-err));
nlmsg_free(msg);
return PCAP_ERROR;
}
}
@ -615,7 +764,6 @@ DIAG_ON_NARROWING
/*
* Success.
*/
nlmsg_free(msg);
/*
* Try to remember the monitor device.
@ -659,31 +807,22 @@ del_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
return PCAP_ERROR;
}
genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ,
genl_family_get_id(state->nl80211), 0,
0, NL80211_CMD_DEL_INTERFACE, 0);
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
err = nl_send_auto_complete(state->nl_sock, msg);
err = nl_send_sync(state->nl_sock, msg); // calls nlmsg_free()
if (err < 0) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: nl_send_auto_complete failed deleting %s interface: %s",
"%s: nl_send_sync failed deleting %s interface: %s",
device, mondevice, nl_geterror(-err));
nlmsg_free(msg);
return PCAP_ERROR;
}
err = nl_wait_for_ack(state->nl_sock);
if (err < 0) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: nl_wait_for_ack failed adding %s interface: %s",
device, mondevice, nl_geterror(-err));
nlmsg_free(msg);
return PCAP_ERROR;
}
/*
* Success.
*/
nlmsg_free(msg);
return 1;
nla_put_failure:
@ -1231,19 +1370,17 @@ linux_check_direction(const pcap_t *handle, const struct sockaddr_ll *sll)
return 0;
/*
* If this is an outgoing CAN or CAN FD frame, and
* the user doesn't only want outgoing packets,
* reject it; CAN devices and drivers, and the CAN
* stack, always arrange to loop back transmitted
* packets, so they also appear as incoming packets.
* We don't want duplicate packets, and we can't
* easily distinguish packets looped back by the CAN
* layer than those received by the CAN layer, so we
* eliminate this packet instead.
* If this is an outgoing CAN frame, and the user doesn't
* want only outgoing packets, reject it; CAN devices
* and drivers, and the CAN stack, always arrange to
* loop back transmitted packets, so they also appear
* as incoming packets. We don't want duplicate packets,
* and we can't easily distinguish packets looped back
* by the CAN layer than those received by the CAN layer,
* so we eliminate this packet instead.
*
* We check whether this is a CAN or CAN FD frame
* by checking whether the device's hardware type
* is ARPHRD_CAN.
* We check whether this is a CAN frame by checking whether
* the device's hardware type is ARPHRD_CAN.
*/
if (sll->sll_hatype == ARPHRD_CAN &&
handle->direction != PCAP_D_OUT)
@ -1925,8 +2062,8 @@ static int map_arphrd_to_dlt(pcap_t *handle, int arptype,
if (ret == 1) {
/*
* This is a DSA master/management network
* device linktype is already set by
* iface_dsa_get_proto_info() set an
* device, linktype is already set by
* iface_dsa_get_proto_info(), set an
* appropriate offset here.
*/
handle->offset = 2;
@ -2218,7 +2355,7 @@ static int map_arphrd_to_dlt(pcap_t *handle, int arptype,
*
* https://github.com/mcr/libpcap/pull/29
*
* There doesn't seem to be any network drivers that uses
* There don't seem to be any network drivers that uses
* any of the ARPHRD_FC* values for IP-over-FC, and
* it's not exactly clear what the "Dummy types for non
* ARP hardware" are supposed to mean (link-layer
@ -2374,9 +2511,9 @@ setup_socket(pcap_t *handle, int is_any_device)
* Other error.
*/
status = PCAP_ERROR;
pcapint_fmt_errmsg_for_errno(handle->errbuf,
PCAP_ERRBUF_SIZE, errno, "socket");
}
pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
errno, "socket");
return status;
}
@ -2564,6 +2701,7 @@ setup_socket(pcap_t *handle, int is_any_device)
if (handle->dlt_list == NULL) {
pcapint_fmt_errmsg_for_errno(handle->errbuf,
PCAP_ERRBUF_SIZE, errno, "malloc");
close(sock_fd);
return (PCAP_ERROR);
}
handle->dlt_list[0] = DLT_LINUX_SLL;
@ -4810,18 +4948,40 @@ enter_rfmon_mode(pcap_t *handle, int sock_fd, const char *device)
if (ret == 0)
return 0; /* no error, but not mac80211 device */
/*
* XXX - is this already a monN device?
* If so, we're done.
*/
/*
* OK, it's apparently a mac80211 device.
* Try to find an unused monN device for it.
*/
ret = nl80211_init(handle, &nlstate, device);
if (ret != 0)
return ret;
/*
* Is this already a monN device?
* If so, we're done.
*/
int type;
ret = get_if_type(handle, sock_fd, &nlstate, device, &type);
if (ret <= 0) {
/*
* < 0 is a Hard failure. Just return ret; handle->errbuf
* has already been set.
*
* 0 is "device not available"; the caller should retry later.
*/
nl80211_cleanup(&nlstate);
return ret;
}
if (type == NL80211_IFTYPE_MONITOR) {
/*
* OK, it's already a monitor mode device; just use it.
* There's no point in creating another monitor device
* that will have to be cleaned up.
*/
nl80211_cleanup(&nlstate);
return ret;
}
/*
* OK, it's apparently a mac80211 device but not a monitor device.
* Try to find an unused monN device for it.
*/
for (n = 0; n < UINT_MAX; n++) {
/*
* Try mon{n}.
@ -5267,22 +5427,294 @@ iface_get_offload(pcap_t *handle _U_)
}
#endif /* SIOCETHTOOL */
/*
* As per
*
* https://www.kernel.org/doc/html/latest/networking/dsa/dsa.html#switch-tagging-protocols
*
* Type 1 means that the tag is prepended to the Ethernet packet.
*
* Type 2 means that the tag is inserted into the Ethernet header
* after the source address and before the type/length field.
*
* Type 3 means that tag is a packet trailer.
*
* Every element in the array below uses a DLT. Because a DSA-tagged frame is
* not a standard IEEE 802.3 Ethernet frame, the array elements must not use
* DLT_EN10MB. It is safe, albeit only barely useful, to use DLT_DEBUG_ONLY,
* which is also the implicit default for any DSA tag that is not present in
* the array. To implement proper support for a particular DSA tag of
* interest, please do as much of the following as is reasonably practicable:
*
* 1. Using recent versions of tcpdump and libpcap on a Linux host with a
* network interface that implements the required DSA tag, capture packets
* on the interface and study the hex dumps.
* 2. Using the hex dumps and any other available supporting materials, produce
* a sufficiently detailed description of the DSA tag structure, complete
* with a full comment indicating whether it's type 1, 2, or 3, and, for
* type 2, indicating whether it has an Ethertype and, if so, what that type
* is, and whether it's registered with the IEEE or not. Refer to the
* specification(s), existing implementation(s), or any other relevant
* resources.
* 3. Using the description, request and obtain a new DLT for the DSA tag.
* 4. Associate the new DLT with the DSA tag in the array below.
* 5. Using the updated libpcap, capture packets again, produce a .pcap file
* and confirm it uses the new DLT.
* 6. Using the .pcap file as a test, prepare additional changes to tcpdump to
* enable decoding of packets for the new DLT.
* 7. Using the .pcap file as a test, prepare additional changes to libpcap to
* enable filtering of packets for the new DLT.
*
* For working examples of such support, see the existing DLTs other than
* DLT_DEBUG_ONLY in the array below.
*/
static struct dsa_proto {
const char *name;
bpf_u_int32 linktype;
} dsa_protos[] = {
/*
* None is special and indicates that the interface does not have
* any tagging protocol configured, and is therefore a standard
* Ethernet interface.
* Type 1. See
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_ar9331.c
*/
{ "ar9331", DLT_DEBUG_ONLY },
/*
* Type 2, without an EtherType at the beginning.
*/
{ "none", DLT_EN10MB },
{ "brcm", DLT_DSA_TAG_BRCM },
/*
* Type 2, with EtherType 0x8874, assigned to Broadcom.
*/
{ "brcm-legacy", DLT_DEBUG_ONLY },
/*
* Type 1.
*/
{ "brcm-prepend", DLT_DSA_TAG_BRCM_PREPEND },
/*
* Type 2, without an EtherType at the beginning.
*/
{ "dsa", DLT_DSA_TAG_DSA },
/*
* Type 2, with an Ethertype field, but without
* an assigned EtherType value that can be relied
* on.
*/
{ "edsa", DLT_DSA_TAG_EDSA },
/*
* Type 1, with different transmit and receive headers,
* so can't really be handled well with the current
* libpcap API and with pcap files.
*
* See
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_gswip.c
*/
{ "gswip", DLT_DEBUG_ONLY },
/*
* Type 3. See
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_hellcreek.c
*/
{ "hellcreek", DLT_DEBUG_ONLY },
/*
* Type 3, with different transmit and receive headers,
* so can't really be handled well with the current
* libpcap API and with pcap files.
*
* See
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_ksz.c#L102
*/
{ "ksz8795", DLT_DEBUG_ONLY },
/*
* Type 3, with different transmit and receive headers,
* so can't really be handled well with the current
* libpcap API and with pcap files.
*
* See
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_ksz.c#L160
*/
{ "ksz9477", DLT_DEBUG_ONLY },
/*
* Type 3, with different transmit and receive headers,
* so can't really be handled well with the current
* libpcap API and with pcap files.
*
* See
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_ksz.c#L341
*/
{ "ksz9893", DLT_DEBUG_ONLY },
/*
* Type 3, with different transmit and receive headers,
* so can't really be handled well with the current
* libpcap API and with pcap files.
*
* See
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_ksz.c#L386
*/
{ "lan937x", DLT_DEBUG_ONLY },
/*
* Type 2, with EtherType 0x8100; the VID can be interpreted
* as per
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_lan9303.c#L24
*/
{ "lan9303", DLT_DEBUG_ONLY },
/*
* Type 2, without an EtherType at the beginning.
*
* See
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_mtk.c#L15
*
* Linux kernel implements this tag so that it does not indicate the frame
* encoding reliably. The matter is, some drivers use METADATA_HW_PORT_MUX,
* which (for the switch->CPU direction only, at the time of this writing)
* means that the frame does not have a DSA tag, the frame metadata is stored
* elsewhere and libpcap receives the frame only. Specifically, this is the
* case for drivers/net/ethernet/mediatek/mtk_eth_soc.c, but the tag visible
* in sysfs is still "mtk" even though the wire encoding is different.
*/
{ "mtk", DLT_DEBUG_ONLY },
/*
* Type 1.
*
* See
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_ocelot.c
*/
{ "ocelot", DLT_DEBUG_ONLY },
/*
* Type 1.
*
* See
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_ocelot.c
*/
{ "seville", DLT_DEBUG_ONLY },
/*
* Type 2, with EtherType 0x8100; the VID can be interpreted
* as per
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_8021q.c#L15
*/
{ "ocelot-8021q", DLT_DEBUG_ONLY },
/*
* Type 2, without an EtherType at the beginning.
*
* See
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_qca.c
*/
{ "qca", DLT_DEBUG_ONLY },
/*
* Type 2, with EtherType 0x8899, assigned to Realtek;
* they use it for several on-the-Ethernet protocols
* as well, but there are fields that allow the two
* tag formats, and all the protocols in question,
* to be distinguiished from one another.
*
* See
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_rtl4_a.c
*
* http://realtek.info/pdf/rtl8306sd%28m%29_datasheet_1.1.pdf
*
* and various pages in tcpdump's print-realtek.c and Wireshark's
* epan/dissectors/packet-realtek.c for the other protocols.
*/
{ "rtl4a", DLT_DEBUG_ONLY },
/*
* Type 2, with EtherType 0x8899, assigned to Realtek;
* see above.
*/
{ "rtl8_4", DLT_DEBUG_ONLY },
/*
* Type 3, with the same tag format as rtl8_4.
*/
{ "rtl8_4t", DLT_DEBUG_ONLY },
/*
* Type 2, with EtherType 0xe001; that's probably
* self-assigned.
*
* See
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_rzn1_a5psw.c
*/
{ "a5psw", DLT_DEBUG_ONLY },
/*
* Type 2, with EtherType 0x8100 or the self-assigned
* 0xdadb, so this really should have its own
* LINKTYPE_/DLT_ value; that would also allow the
* VID of the tag to be dissected as per
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_8021q.c#L15
*/
{ "sja1105", DLT_DEBUG_ONLY },
/*
* Type "none of the above", with both a header and trailer,
* with different transmit and receive tags. Has
* EtherType 0xdadc, which is probably self-assigned.
*/
{ "sja1110", DLT_DEBUG_ONLY },
/*
* Type 3, as the name suggests.
*
* See
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_trailer.c
*/
{ "trailer", DLT_DEBUG_ONLY },
/*
* Type 2, with EtherType 0x8100; the VID can be interpreted
* as per
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_8021q.c#L15
*/
{ "vsc73xx-8021q", DLT_DEBUG_ONLY },
/*
* Type 3.
*
* See
*
* https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_xrs700x.c
*/
{ "xrs700x", DLT_DEBUG_ONLY },
};
/*
* Return 1 if the interface uses DSA tagging, 0 if the interface does not use
* DSA tagging, or PCAP_ERROR on error.
*/
static int
iface_dsa_get_proto_info(const char *device, pcap_t *handle)
{
@ -5309,10 +5741,18 @@ iface_dsa_get_proto_info(const char *device, pcap_t *handle)
fd = open(pathstr, O_RDONLY);
free(pathstr);
/*
* This is not fatal, kernel >= 4.20 *might* expose this attribute
* This could be not fatal: kernel >= 4.20 *might* expose this
* attribute. However, if it exposes the attribute, but the read has
* failed due to another reason (ENFILE, EMFILE, ENOMEM...), propagate
* the failure.
*/
if (fd < 0)
return 0;
if (fd < 0) {
if (errno == ENOENT)
return 0;
pcapint_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
errno, "open");
return PCAP_ERROR;
}
r = read(fd, buf, sizeof(buf) - 1);
if (r <= 0) {
@ -5330,23 +5770,41 @@ iface_dsa_get_proto_info(const char *device, pcap_t *handle)
r--;
buf[r] = '\0';
/*
* The string "none" indicates that the interface does not have
* any tagging protocol configured, and is therefore a standard
* Ethernet interface.
*/
if (strcmp(buf, "none") == 0)
return 0;
/*
* Every element in the array stands for a DSA-tagged interface. Using
* DLT_EN10MB (the standard IEEE 802.3 Ethernet) for such an interface
* may seem a good idea at first, but doing so would certainly cause
* major problems in areas that are already complicated and depend on
* DLT_EN10MB meaning the standard IEEE 802.3 Ethernet only, namely:
*
* - live capturing of packets on Linux, and
* - live kernel filtering of packets on Linux, and
* - live userspace filtering of packets on Linux, and
* - offline filtering of packets on all supported OSes, and
* - identification of savefiles on all OSes.
*
* Therefore use a default DLT value that does not block capturing and
* hexdumping of unsupported DSA encodings (in case the tag is not in
* the array) and enforce the non-use of DLT_EN10MB (in case the tag is
* in the array, but is incorrectly declared).
*/
handle->linktype = DLT_DEBUG_ONLY;
for (i = 0; i < sizeof(dsa_protos) / sizeof(dsa_protos[0]); i++) {
if (strlen(dsa_protos[i].name) == (size_t)r &&
strcmp(buf, dsa_protos[i].name) == 0) {
handle->linktype = dsa_protos[i].linktype;
switch (dsa_protos[i].linktype) {
case DLT_EN10MB:
return 0;
default:
return 1;
}
if (strcmp(buf, dsa_protos[i].name) == 0) {
if (dsa_protos[i].linktype != DLT_EN10MB)
handle->linktype = dsa_protos[i].linktype;
break;
}
}
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"unsupported DSA tag: %s", buf);
return PCAP_ERROR;
return 1;
}
/*
@ -5724,12 +6182,18 @@ pcap_set_protocol_linux(pcap_t *p, int protocol)
/*
* Libpcap version string.
*/
#if defined(HAVE_TPACKET3) && defined(PCAP_SUPPORT_NETMAP)
#define ADDITIONAL_INFO_STRING "with TPACKET_V3 and netmap"
#elif defined(HAVE_TPACKET3)
#define ADDITIONAL_INFO_STRING "with TPACKET_V3"
#elif defined(PCAP_SUPPORT_NETMAP)
#define ADDITIONAL_INFO_STRING "with TPACKET_V2 and netmap"
#else
#define ADDITIONAL_INFO_STRING "with TPACKET_V2"
#endif
const char *
pcap_lib_version(void)
{
#if defined(HAVE_TPACKET3)
return (PCAP_VERSION_STRING " (with TPACKET_V3)");
#else
return (PCAP_VERSION_STRING " (with TPACKET_V2)");
#endif
return (PCAP_VERSION_STRING_WITH_ADDITIONAL_INFO(ADDITIONAL_INFO_STRING));
}

View file

@ -85,6 +85,12 @@ int pcap_findalldevs_ex(const char *source, struct pcap_rmtauth *auth, pcap_if_t
(*alldevs) = NULL;
lastdev = NULL;
if (source == NULL)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"The source string must not be NULL.");
return -1;
}
if (strlen(source) > PCAP_BUF_SIZE)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly.");
@ -93,21 +99,23 @@ int pcap_findalldevs_ex(const char *source, struct pcap_rmtauth *auth, pcap_if_t
/*
* Determine the type of the source (file, local, remote)
* There are some differences if pcap_findalldevs_ex() is called to list files and remote adapters.
* In the first case, the name of the directory we have to look into must be present (therefore
* the 'name' parameter of the pcap_parsesrcstr() is present).
* In the second case, the name of the adapter is not required (we need just the host). So, we have
* to use a first time this function to get the source type, and a second time to get the appropriate
* info, which depends on the source type.
*
* To list files in a local directory, the source string must specify
* the directory name. To list local or remote capture devices, the
* source string must not specify a device name. Retrieve the name
* component now and validate it for each source type next.
*/
if (pcap_parsesrcstr(source, &type, NULL, NULL, NULL, errbuf) == -1)
if (pcap_parsesrcstr(source, &type, NULL, NULL, name, errbuf) == -1)
return -1;
switch (type)
{
case PCAP_SRC_IFLOCAL:
if (pcap_parsesrcstr(source, &type, NULL, NULL, NULL, errbuf) == -1)
if (strlen(name)) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"To list local capture devices, the source string must not include a device name.");
return -1;
}
/* Initialize temporary string */
tmpstring[PCAP_BUF_SIZE] = 0;
@ -186,12 +194,15 @@ int pcap_findalldevs_ex(const char *source, struct pcap_rmtauth *auth, pcap_if_t
DIR *unixdir;
#endif
if (pcap_parsesrcstr(source, &type, NULL, NULL, name, errbuf) == -1)
return -1;
/* Check that the filename is correct */
stringlen = strlen(name);
if (! stringlen) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"To list local files, the source string must include a directory.");
return -1;
}
/* The directory must end with '\' in Win32 and '/' in UNIX */
#ifdef _WIN32
#define ENDING_CHAR '\\'
@ -378,6 +389,12 @@ int pcap_findalldevs_ex(const char *source, struct pcap_rmtauth *auth, pcap_if_t
}
case PCAP_SRC_IFREMOTE:
if (strlen(name)) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"To list remote capture devices, the source string must not include a device name.");
return -1;
}
return pcap_findalldevs_ex_remote(source, auth, alldevs, errbuf);
default:
@ -419,13 +436,28 @@ pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout,
switch (type)
{
case PCAP_SRC_FILE:
if (! strlen(name)) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"To open a local file, the source string must include the file path.");
return NULL;
}
return pcap_open_offline(name, errbuf);
case PCAP_SRC_IFLOCAL:
if (! strlen(name)) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"To open a local capture device, the source string must include the device name.");
return NULL;
}
fp = pcap_create(name, errbuf);
break;
case PCAP_SRC_IFREMOTE:
if (! strlen(name)) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"To open a remote capture device, the source string must include the device name.");
return NULL;
}
/*
* Although we already have host, port and iface, we prefer
* to pass only 'source' to pcap_open_rpcap(), so that it

View file

@ -196,6 +196,10 @@ PacketGetMonitorMode(PCHAR AdapterName _U_)
#define NDIS_STATUS_NOT_SUPPORTED 0xc00000bb /* STATUS_NOT_SUPPORTED */
#define NDIS_STATUS_NOT_RECOGNIZED 0x00010001
#ifndef PACKET_OID_DATA_LENGTH
#define PACKET_OID_DATA_LENGTH(_DataLength) \
(offsetof(PACKET_OID_DATA, Data) + _DataLength)
#endif
static int
oid_get_request(ADAPTER *adapter, bpf_u_int32 oid, void *data, size_t *lenp,
char *errbuf)
@ -204,12 +208,9 @@ oid_get_request(ADAPTER *adapter, bpf_u_int32 oid, void *data, size_t *lenp,
/*
* Allocate a PACKET_OID_DATA structure to hand to PacketRequest().
* It should be big enough to hold "*lenp" bytes of data; it
* will actually be slightly larger, as PACKET_OID_DATA has a
* 1-byte data array at the end, standing in for the variable-length
* data that's actually there.
* It should be big enough to hold "*lenp" bytes of data;
*/
oid_data_arg = malloc(sizeof (PACKET_OID_DATA) + *lenp);
oid_data_arg = malloc(PACKET_OID_DATA_LENGTH(*lenp));
if (oid_data_arg == NULL) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"Couldn't allocate argument buffer for PacketRequest");
@ -404,12 +405,9 @@ pcap_oid_set_request_npf(pcap_t *p, bpf_u_int32 oid, const void *data,
/*
* Allocate a PACKET_OID_DATA structure to hand to PacketRequest().
* It should be big enough to hold "*lenp" bytes of data; it
* will actually be slightly larger, as PACKET_OID_DATA has a
* 1-byte data array at the end, standing in for the variable-length
* data that's actually there.
* It should be big enough to hold "*lenp" bytes of data;
*/
oid_data_arg = malloc(sizeof (PACKET_OID_DATA) + *lenp);
oid_data_arg = malloc(PACKET_OID_DATA_LENGTH(*lenp));
if (oid_data_arg == NULL) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Couldn't allocate argument buffer for PacketRequest");
@ -1033,6 +1031,10 @@ pcap_activate_npf(pcap_t *p)
int status = 0;
struct bpf_insn total_insn;
struct bpf_program total_prog;
#ifdef HAVE_PACKET_GET_INFO
char oid_data_buf[PACKET_OID_DATA_LENGTH(sizeof(ULONG))] = {0};
PACKET_OID_DATA *oid_data_arg = (PACKET_OID_DATA *)oid_data_buf;
#endif
if (p->opt.rfmon) {
/*
@ -1292,6 +1294,42 @@ pcap_activate_npf(pcap_t *p)
}
#endif /* HAVE_PACKET_GET_TIMESTAMP_MODES */
#ifdef PACKET_MODE_NANO
/*
* If nanosecond timestamp resolution is requested, set
* the packet mode to enable it.
*
* XXX - it's not nanosecond resolution, as the internal
* NT clock has 100 ns resolution, but we can't indicate
* that. An updated-for-pcapng API should support that.
*/
if (p->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) {
res = PacketSetMode(pw->adapter, PACKET_MODE_NANO);
if(res == FALSE){
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Error setting nanosecond capture mode");
goto bad;
}
}
#endif /* PACKET_MODE_NANO */
#if defined(HAVE_PACKET_GET_INFO) && defined(NPF_GETINFO_BPFEXT) && defined(SKF_AD_VLAN_TAG_PRESENT)
/* Can we generate special code for VLAN checks? */
oid_data_arg->Oid = NPF_GETINFO_BPFEXT;
oid_data_arg->Length = sizeof(ULONG);
if (PacketGetInfo(pw->adapter, oid_data_arg)) {
if (*((ULONG *)oid_data_arg->Data) >= SKF_AD_VLAN_TAG_PRESENT) {
/* Yes, we can. Request that we do so. */
p->bpf_codegen_flags |= BPF_SPECIAL_VLAN_HANDLING;
}
}
else {
pcapint_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
GetLastError(), "Error calling PacketGetInfo");
}
#endif /* HAVE_PACKET_GET_INFO */
/*
* Turn a negative snapshot value (invalid), a snapshot value of
* 0 (unspecified), or a value bigger than the normal maximum
@ -1613,11 +1651,11 @@ pcap_can_set_rfmon_npf(pcap_t *p)
}
/*
* Get a list of time stamp types.
* Get lists of time stamp types and precisions.
*/
#ifdef HAVE_PACKET_GET_TIMESTAMP_MODES
static int
get_ts_types(const char *device, pcap_t *p, char *ebuf)
get_ts_support(const char *device, pcap_t *p, char *ebuf)
{
char *device_copy = NULL;
ADAPTER *adapter = NULL;
@ -1632,6 +1670,12 @@ get_ts_types(const char *device, pcap_t *p, char *ebuf)
ULONG *modes = NULL;
int status = 0;
/*
* This is called in pcapint_create_interface(), after the
* pcap_t is allocated and initialized, so the time stamp
* type list and the time stamp precision lists are both
* empty.
*/
do {
/*
* First, find out how many time stamp modes we have.
@ -1683,8 +1727,6 @@ get_ts_types(const char *device, pcap_t *p, char *ebuf)
*/
if (error == ERROR_BAD_UNIT ||
error == ERROR_ACCESS_DENIED) {
p->tstamp_type_count = 0;
p->tstamp_type_list = NULL;
status = 0;
} else {
pcapint_fmt_errmsg_for_win32_err(ebuf,
@ -1692,6 +1734,10 @@ get_ts_types(const char *device, pcap_t *p, char *ebuf)
"Error opening adapter");
status = -1;
}
/*
* We're done; clean up and return the status.
*/
break;
}
@ -1865,6 +1911,25 @@ get_ts_types(const char *device, pcap_t *p, char *ebuf)
}
}
p->tstamp_type_count = num_ts_types;
#ifdef PACKET_MODE_NANO
/*
* Check if we support nanosecond time stamps.
*/
if (PacketSetMode(adapter, PACKET_MODE_NANO)) {
p->tstamp_precision_list = malloc(2 * sizeof(u_int));
if (p->tstamp_precision_list == NULL) {
pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
errno, "malloc");
pcap_close(p);
return (NULL);
}
p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
p->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO;
p->tstamp_precision_count = 2;
}
#endif /* PACKET_MODE_NANO */
} while (0);
/* Clean up temporary allocations */
@ -1882,7 +1947,7 @@ get_ts_types(const char *device, pcap_t *p, char *ebuf)
}
#else /* HAVE_PACKET_GET_TIMESTAMP_MODES */
static int
get_ts_types(const char *device _U_, pcap_t *p _U_, char *ebuf _U_)
get_ts_support(const char *device _U_, pcap_t *p _U_, char *ebuf _U_)
{
/*
* Nothing to fetch, so it always "succeeds".
@ -1903,10 +1968,11 @@ pcapint_create_interface(const char *device _U_, char *ebuf)
p->activate_op = pcap_activate_npf;
p->can_set_rfmon_op = pcap_can_set_rfmon_npf;
if (get_ts_types(device, p, ebuf) == -1) {
if (get_ts_support(device, p, ebuf) == -1) {
pcap_close(p);
return (NULL);
}
return (p);
}
@ -2766,7 +2832,7 @@ pcap_lib_version(void)
char *full_pcap_version_string;
if (pcapint_asprintf(&full_pcap_version_string,
PCAP_VERSION_STRING " (packet.dll version %s)",
PCAP_VERSION_STRING_WITH_ADDITIONAL_INFO("packet.dll version %s"),
PacketGetVersion()) != -1) {
/* Success */
pcap_lib_version_string = full_pcap_version_string;

View file

@ -267,7 +267,7 @@ static int rpcap_read_packet_msg(struct pcap_rpcap const *, pcap_t *p, size_t si
/*
* Possible IPv4 family values other than the designated over-the-wire value,
* which is 2 (because everybody, except for Haiku uses 2 for AF_INET,
* which is 2 (because everybody, except for Haiku, uses 2 for AF_INET,
* and Haiku has probably never run the old rpcapd code that put address
* structures directly on the wire, rather than the new rpcapd code
* that serializes addresses, using 2 for AF_INET).

View file

@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
.TH PCAP-SAVEFILE @MAN_FILE_FORMATS@ "16 Aug 2023"
.TH PCAP-SAVEFILE @MAN_FILE_FORMATS@ "6 Jan 2025"
.SH NAME
pcap-savefile \- libpcap savefile format
.SH DESCRIPTION
@ -55,19 +55,30 @@ The per-file header length is 24 octets.
.PP
All fields in the per-file header are in the byte order of the host
writing the file. Normally, the first field in the per-file header is a
4-byte magic number, with the value 0xa1b2c3d4. The magic number, when
4-byte magic number, with the value
.BR 0xa1b2c3d4 .
The magic number, when
read by a host with the same byte order as the host that wrote the file,
will have the value 0xa1b2c3d4, and, when read by a host with the
will have the value
.BR 0xa1b2c3d4 ,
and, when read by a host with the
opposite byte order as the host that wrote the file, will have the value
0xd4c3b2a1. That allows software reading the file to determine whether
.BR 0xd4c3b2a1 .
That allows software reading the file to determine whether
the byte order of the host that wrote the file is the same as the byte
order of the host on which the file is being read, and thus whether the
values in the per-file and per-packet headers need to be byte-swapped.
.PP
If the magic number has the value 0xa1b23c4d (with the two nibbles of
If the magic number has the value
.B 0xa1b23c4d
(with the two nibbles of
the two lower-order bytes of the magic number swapped), which would be
read as 0xa1b23c4d by a host with the same byte order as the host that
wrote the file and as 0x4d3cb2a1 by a host with the opposite byte order
read as
.B 0xa1b23c4d
by a host with the same byte order as the host that
wrote the file and as
.B 0x4d3cb2a1
by a host with the opposite byte order
as the host that wrote the file, the file format is the same as for
regular files, except that the time stamps for packets are given in
seconds and nanoseconds rather than seconds and microseconds.
@ -75,10 +86,10 @@ seconds and nanoseconds rather than seconds and microseconds.
Following this are:
.IP
A 2-byte file format major version number; the current version number is
2.
2 (big-endian 0x00 0x02 or little-endian 0x02 0x00).
.IP
A 2-byte file format minor version number; the current version number is
4.
4 (big-endian 0x00 0x04 or little-endian 0x04 0x00).
.IP
A 4-byte not used - SHOULD be filled with 0 by pcap file writers, and MUST
be ignored by pcap file readers. This value was documented by some older

View file

@ -312,8 +312,7 @@ pcapint_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
pcap_t *
pcapint_create_interface(const char *device, char *errbuf)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"This version of libpcap only supports Septel cards");
snprintf(errbuf, PCAP_ERRBUF_SIZE, PCAP_ENODEV_MESSAGE, "Septel");
return (NULL);
}

View file

@ -599,8 +599,7 @@ pcapint_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
pcap_t *
pcapint_create_interface(const char *device, char *errbuf)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"This version of libpcap only supports SNF cards");
snprintf(errbuf, PCAP_ERRBUF_SIZE, PCAP_ENODEV_MESSAGE, "SNF");
return NULL;
}
@ -610,6 +609,6 @@ pcapint_create_interface(const char *device, char *errbuf)
const char *
pcap_lib_version(void)
{
return (PCAP_VERSION_STRING " (SNF-only)");
return (PCAP_VERSION_STRING_WITH_ADDITIONAL_INFO("SNF-only"));
}
#endif

73
pcap.c
View file

@ -1781,6 +1781,17 @@ pcap_parse_source(const char *source, char **schemep, char **userinfop,
char *parsep, *atsignp, *bracketp;
char *userinfo, *host, *port, *path;
if (source == NULL) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"The source string must not be NULL.");
return (-1);
}
if (! strcmp(source, "")) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"The source string must not be empty.");
return (-1);
}
/*
* Start out returning nothing.
*/
@ -2271,19 +2282,16 @@ pcapint_parsesrcstr_ex(const char *source, int *type, char *host, char *port,
}
/*
* Neither rpcap: nor file:; just treat the entire string
* as a local device.
* The code above has already completely handled the case of no scheme,
* as well as each case of a valid scheme.
*/
if (name)
pcapint_strlcpy(name, source, PCAP_BUF_SIZE);
if (type)
*type = PCAP_SRC_IFLOCAL;
snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string URL scheme is not supported.");
free(tmppath);
free(tmpport);
free(tmphost);
free(tmpuserinfo);
free(scheme);
return (0);
return (-1);
}
int
@ -3341,7 +3349,7 @@ static struct dlt_choice dlt_choices[] = {
DLT_CHOICE(BLUETOOTH_BREDR_BB, "Bluetooth Basic Rate/Enhanced Data Rate baseband packets"),
DLT_CHOICE(BLUETOOTH_LE_LL_WITH_PHDR, "Bluetooth Low Energy air interface with pseudo-header"),
DLT_CHOICE(PROFIBUS_DL, "PROFIBUS data link layer"),
DLT_CHOICE(PKTAP, "Apple DLT_PKTAP"),
DLT_CHOICE(PKTAP, "Apple PKTAP"),
DLT_CHOICE(EPON, "Ethernet with 802.3 Clause 65 EPON preamble"),
DLT_CHOICE(IPMI_HPM_2, "IPMI trace packets"),
DLT_CHOICE(ZWAVE_R1_R2, "Z-Wave RF profile R1 and R2 packets"),
@ -3350,7 +3358,7 @@ static struct dlt_choice dlt_choices[] = {
DLT_CHOICE(ISO_14443, "ISO 14443 messages"),
DLT_CHOICE(RDS, "IEC 62106 Radio Data System groups"),
DLT_CHOICE(USB_DARWIN, "USB with Darwin header"),
DLT_CHOICE(OPENFLOW, "OpenBSD DLT_OPENFLOW"),
DLT_CHOICE(OPENFLOW, "OpenBSD OpenFlow"),
DLT_CHOICE(SDLC, "IBM SDLC frames"),
DLT_CHOICE(TI_LLN_SNIFFER, "TI LLN sniffer frames"),
DLT_CHOICE(VSOCK, "Linux vsock"),
@ -3371,6 +3379,36 @@ static struct dlt_choice dlt_choices[] = {
DLT_CHOICE(Z_WAVE_SERIAL, "Z-Wave serial frames between host and chip"),
DLT_CHOICE(USB_2_0, "USB 2.0/1.1/1.0 as transmitted over the cable"),
DLT_CHOICE(ATSC_ALP, "ATSC Link-Layer Protocol packets"),
DLT_CHOICE(ETW, "Event Tracing for Windows messages"),
DLT_CHOICE(NETANALYZER_NG, "Hilscher netANALYZER NG pseudo-footer"),
DLT_CHOICE(ZBOSS_NCP, "ZBOSS NCP protocol with pseudo-header"),
DLT_CHOICE(USB_2_0_LOW_SPEED, "Low-Speed USB 2.0/1.1/1.0 as transmitted over the cable"),
DLT_CHOICE(USB_2_0_FULL_SPEED, "Full-Speed USB 2.0/1.1/1.0 as transmitted over the cable"),
DLT_CHOICE(USB_2_0_HIGH_SPEED, "High-Speed USB 2.0 as transmitted over the cable"),
DLT_CHOICE(AUERSWALD_LOG, "Auerswald Logger Protocol"),
DLT_CHOICE(ZWAVE_TAP, "Z-Wave packets with a TAP meta-data header"),
DLT_CHOICE(SILABS_DEBUG_CHANNEL, "Silicon Labs debug channel protocol"),
DLT_CHOICE(FIRA_UCI, "Ultra-wideband controller interface protocol"),
DLT_CHOICE(MDB, "Multi-Drop Bus"),
DLT_CHOICE(DECT_NR, "DECT New Radio"),
DLT_CHOICE(USER0, "Private use 0"),
DLT_CHOICE(USER1, "Private use 1"),
DLT_CHOICE(USER2, "Private use 2"),
DLT_CHOICE(USER3, "Private use 3"),
DLT_CHOICE(USER4, "Private use 4"),
DLT_CHOICE(USER5, "Private use 5"),
DLT_CHOICE(USER6, "Private use 6"),
DLT_CHOICE(USER7, "Private use 7"),
DLT_CHOICE(USER8, "Private use 8"),
DLT_CHOICE(USER9, "Private use 9"),
DLT_CHOICE(USER10, "Private use 10"),
DLT_CHOICE(USER11, "Private use 11"),
DLT_CHOICE(USER12, "Private use 12"),
DLT_CHOICE(USER13, "Private use 13"),
DLT_CHOICE(USER14, "Private use 14"),
DLT_CHOICE(USER15, "Private use 15"),
DLT_CHOICE(EDK2_MM, "edk2 mm request serialization protocol"),
DLT_CHOICE(DEBUG_ONLY, "unstructured data for manual debugging only"),
DLT_CHOICE_SENTINEL
};
@ -4278,10 +4316,23 @@ pcapint_load_code(const char *name)
return hModule;
}
pcap_funcptr_t
/*
* Casting from FARPROC, which is the type of the return value of
* GetProcAddress(), to a function pointer gets a C4191 warning
* from Visual Studio 2022.
*
* Casting FARPROC to void * and returning the result, and then
* casting the void * to a function pointer, doesn't get the
* same warning.
*
* Given that, and given that the equivalent UN*X API, dlsym(),
* returns a void *, we have pcapint_find_function() return
* a void *.
*/
void *
pcapint_find_function(pcap_code_handle_t code, const char *func)
{
return (GetProcAddress(code, func));
return ((void *)GetProcAddress(code, func));
}
#endif

View file

@ -390,7 +390,7 @@
* 121 was reserved for Siemens HiPath HDLC on 2002-01-25, as
* requested by Tomas Kukosa.
*
* On 2004-02-25, a FreeBSD checkin to sys/net/bpf.h was made that
* On 2004-02-25, a FreeBSD check in to sys/net/bpf.h was made that
* assigned 121 as DLT_PFSYNC. In current versions, its libpcap
* does DLT_ <-> LINKTYPE_ mapping, mapping DLT_PFSYNC to a
* LINKTYPE_PFSYNC value of 246, so it should write out DLT_PFSYNC
@ -1570,6 +1570,8 @@
/*
* USB 2.0, 1.1, and 1.0 packets as transmitted over the cable.
* Deprecated in favor of speed specific DLTs: DLT_USB_2_0_LOW_SPEED,
* DLT_USB_2_0_FULL_SPEED and DLT_USB_2_0_HIGH_SPEED.
*/
#define DLT_USB_2_0 288
@ -1578,6 +1580,102 @@
*/
#define DLT_ATSC_ALP 289
/*
* Event Tracing for Windows messages.
*/
#define DLT_ETW 290
/*
* Hilscher Gesellschaft fuer Systemautomation mbH
* netANALYZER NG hardware and software.
*
* The specification for this footer can be found at:
* https://kb.hilscher.com/x/brDJBw
*
* Requested by Jan Adam <jadam@hilscher.com>
*/
#define DLT_NETANALYZER_NG 291
/*
* Serial NCP (Network Co-Processor) protocol for Zigbee stack ZBOSS
* by DSR, https://dsr-iot.com/downloads
*/
#define DLT_ZBOSS_NCP 292
/*
* USB 2.0, 1.1, and 1.0 packets as transmitted over the cable.
*/
#define DLT_USB_2_0_LOW_SPEED 293
#define DLT_USB_2_0_FULL_SPEED 294
#define DLT_USB_2_0_HIGH_SPEED 295
/*
* Auerswald Logger Protocol
* description is provided on
* https://github.com/Auerswald-GmbH/auerlog/blob/master/auerlog.txt
*/
#define DLT_AUERSWALD_LOG 296
/*
* Z-Wave packets with a TAP meta-data header
* https://gitlab.com/exegin/zwave-g9959-tap
* requested on tcpdump-workers@
*/
#define DLT_ZWAVE_TAP 297
/*
* Silicon Labs debug channel protocol:
*/
#define DLT_SILABS_DEBUG_CHANNEL 298
/*
* Ultra-wideband (UWB) controller interface protocol (UCI).
* requested by Henri Chataing <henrichataing@google.com>
*/
#define DLT_FIRA_UCI 299
/*
* MDB (Multi-Drop Bus) protocol between a vending machine controller and
* peripherals inside the vending machine. See
*
* https://www.kaiser.cx/pcap-mdb.html
*
* for the specification.
*
* Requested by Martin Kaiser <martin@kaiser.cx>.
*/
#define DLT_MDB 300
/*
* DECT-2020 New Radio (NR) - ETSI TS 103 636.
* Requested by Stig Bjorlykke <stig@bjorlykke.org>.
*/
#define DLT_DECT_NR 301
/*
* Request serialization protocol used by edk2 firmware to communicate between
* normal mode and management mode ('MM' for short).
*
* The qemu uefi variable store implementation reuses the request serialization
* protocol for firmware <-> qemu communication.
*/
#define DLT_EDK2_MM 302
/*
* Unstructured data for manual debugging only. In other words, this DLT is
* suitable for expert interpretation of hex dumps, and that's it. Do not use
* this DLT for any other purpose. For any automated (identification, saving,
* loading, filtering, decoding) processing please either use another existing
* DLT that fits the use case or document, assign and implement a new, properly
* structured DLT.
*
* In this DLT do not assume any specification, any structure, any format, any
* version, any header, any payload, any byte order, any implementation, any
* software/firmware/hardware particulars, any source, any destination, any
* direction, any protocol or any data integrity/consistency whatsoever.
*/
#define DLT_DEBUG_ONLY 303
/*
* In case the code that includes this file (directly or indirectly)
* has also included OS files that happen to define DLT_HIGH_MATCHING_MAX,
@ -1588,6 +1686,6 @@
#ifdef DLT_HIGH_MATCHING_MAX
#undef DLT_HIGH_MATCHING_MAX
#endif
#define DLT_HIGH_MATCHING_MAX 289 /* highest value in the "matching" range */
#define DLT_HIGH_MATCHING_MAX 303 /* highest value in the "matching" range */
#endif /* !defined(lib_pcap_dlt_h) */

View file

@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
.TH PCAP_CLOSE 3PCAP "3 January 2014"
.TH PCAP_CLOSE 3PCAP "12 October 2024"
.SH NAME
pcap_close \- close a capture device or savefile
.SH SYNOPSIS
@ -34,6 +34,14 @@ void pcap_close(pcap_t *p);
.BR pcap_close ()
closes the files associated with
.I p
and deallocates resources.
and deallocates resources. This means that, for example, if
.I p
refers to a savefile that was opened with
.BR pcap_fopen_offline ()
or
.BR pcap_fopen_offline_with_tstamp_precision (),
the stream provided to the routine will be closed unless it is
.BR stdin .
.SH SEE ALSO
.BR pcap (3PCAP)
.BR pcap (3PCAP),
.BR pcap_open_offline (3PCAP)

View file

@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
.TH PCAP_DUMP_CLOSE 3PCAP "3 January 2014"
.TH PCAP_DUMP_CLOSE 3PCAP "12 October 2024"
.SH NAME
pcap_dump_close \- close a savefile being written to
.SH SYNOPSIS
@ -32,7 +32,14 @@ void pcap_dump_close(pcap_dumper_t *p);
.fi
.SH DESCRIPTION
.BR pcap_dump_close ()
closes the ``savefile.''
closes the ``savefile'' associated with
.I p
and deallocates resources. This means that, for example, if
.I p
refers to a savefile that was opened with
.BR pcap_dump_fopen (),
the stream provided to that routine will be closed unless it is
.BR stdout .
.SH SEE ALSO
.BR pcap (3PCAP),
.BR pcap_dump_open (3PCAP),

View file

@ -32,7 +32,7 @@ int pcap_dump_flush(pcap_dumper_t *p);
.fi
.SH DESCRIPTION
.BR pcap_dump_flush ()
flushes the output buffer to the ``savefile,'' so that any packets
flushes the output buffer to the ``savefile'', so that any packets
written with
.BR pcap_dump (3PCAP)
but not yet written to the ``savefile'' will be written.

View file

@ -32,7 +32,7 @@ FILE *pcap_file(pcap_t *p);
.fi
.SH DESCRIPTION
.BR pcap_file ()
returns the standard I/O stream of the ``savefile,'' if a ``savefile''
returns the standard I/O stream of the ``savefile'', if a ``savefile''
was opened with
.BR pcap_open_offline (3PCAP),
or

View file

@ -180,7 +180,7 @@ platforms that support a packet buffer timeout that starts before any
packets arrive, the timeout expires before any packets arrive, or if the
file descriptor for the capture device is in non-blocking mode and no
packets were available to be read) or if no more packets are available
in a ``savefile.'' It returns
in a ``savefile''. It returns
.B PCAP_ERROR_BREAK
if the loop terminated due to a call to
.BR pcap_breakloop ()

View file

@ -146,7 +146,7 @@ packet filter, or if, on platforms that support a packet buffer timeout
that starts before any packets arrive, the timeout expires before any
packets arrive, or if the file descriptor for the capture device is in
non-blocking mode and no packets were available to be read), or if no
more packets are available in a ``savefile.'' Unfortunately, there is no
more packets are available in a ``savefile''. Unfortunately, there is no
way to determine whether an error occurred or not.
.SH SEE ALSO
.BR pcap (3PCAP)

View file

@ -17,7 +17,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
.TH PCAP_OPEN_OFFLINE 3PCAP "30 November 2023"
.TH PCAP_OPEN_OFFLINE 3PCAP "12 October 2024"
.SH NAME
pcap_open_offline, pcap_open_offline_with_tstamp_precision,
pcap_fopen_offline, pcap_fopen_offline_with_tstamp_precision \- open a saved capture file for reading
@ -80,7 +80,11 @@ Alternatively, you may call
or
.BR pcap_fopen_offline_with_tstamp_precision ()
to read dumped data from an existing open stream
.IR fp .
.IR fp ;
this stream will be closed by a subsequent call to
.BR pcap_close (3PCAP)
unless it is
.BR stdin .
.BR pcap_fopen_offline_with_tstamp_precision ()
takes an additional
.I precision

View file

@ -31,6 +31,10 @@
* SUCH DAMAGE.
*/
#ifndef _WIN32
#include <netinet/in.h>
#endif
/*
* pflog headers, at least as they exist now.
*/

View file

@ -48,26 +48,30 @@ if(WIN32 OR ((CMAKE_USE_PTHREADS_INIT OR PTHREADS_FOUND) AND HAVE_CRYPT))
endif(NOT STDLIBS_HAVE_GETADDRINFO)
endif(UNIX)
if(WIN32)
set(RPCAPD_EXTRA_SOURCES
win32-svc.c
${pcap_SOURCE_DIR}/charconv.c
${pcap_SOURCE_DIR}/missing/getopt.c
rpcapd.rc)
include_directories(${pcap_SOURCE_DIR}/rpcapd ${pcap_SOURCE_DIR}/missing)
endif(WIN32)
add_executable(rpcapd
set(RPCAPD_SOURCES
daemon.c
fileconf.c
log.c
rpcapd.c
${pcap_SOURCE_DIR}/rpcap-protocol.c
${pcap_SOURCE_DIR}/sockutils.c
${pcap_SOURCE_DIR}/sslutils.c
${pcap_SOURCE_DIR}/fmtutils.c
${RPCAPD_EXTRA_SOURCES}
)
if(OPENSSL_FOUND)
set(RPCAPD_SOURCES ${RPCAPD_SOURCES}
${pcap_SOURCE_DIR}/sslutils.c)
endif(OPENSSL_FOUND)
if(WIN32)
set(RPCAPD_SOURCES ${RPCAPD_SOURCES}
win32-svc.c
${pcap_SOURCE_DIR}/charconv.c
${pcap_SOURCE_DIR}/missing/getopt.c
rpcapd.rc
)
include_directories(${pcap_SOURCE_DIR}/rpcapd ${pcap_SOURCE_DIR}/missing)
endif(WIN32)
add_executable(rpcapd ${RPCAPD_SOURCES})
if(NOT C_ADDITIONAL_FLAGS STREQUAL "")
set_target_properties(rpcapd PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS})

View file

@ -87,9 +87,12 @@ static char address[MAX_LINE + 1]; //!< keeps the network address (either numer
static char port[MAX_LINE + 1]; //!< keeps the network port to bind to
#ifdef _WIN32
static HANDLE state_change_event; //!< event to signal that a state change should take place
#endif
static volatile long shutdown_server; //!< '1' if the server is to shut down
static volatile long reread_config; //!< '1' if the server is to re-read its configuration
#else
static volatile sig_atomic_t shutdown_server; //!< '1' if the server is to shut down
static volatile sig_atomic_t reread_config; //!< '1' if the server is to re-read its configuration
#endif
static int uses_ssl; //!< '1' to use TLS over TCP
extern char *optarg; // for getopt()
@ -754,7 +757,7 @@ send_shutdown_notification(void)
//
// Indicate that the server should shut down.
//
shutdown_server = 1;
_InterlockedExchange(&shutdown_server, 1);
//
// Send a state change event, to wake up WSAWaitForMultipleEvents().
@ -768,7 +771,7 @@ send_reread_configuration_notification(void)
//
// Indicate that the server should re-read its configuration file.
//
reread_config = 1;
_InterlockedExchange(&reread_config, 1);
//
// Send a state change event, to wake up WSAWaitForMultipleEvents().
@ -947,20 +950,19 @@ accept_connections(void)
//
// The state change event was set.
//
if (shutdown_server)
if (_InterlockedExchange(&shutdown_server, 0))
{
//
// Time to quit. Exit the loop.
//
break;
}
if (reread_config)
if (_InterlockedExchange(&reread_config, 0))
{
//
// We should re-read the configuration
// file.
//
reread_config = 0; // clear the indicator
fileconf_read();
}
}

View file

@ -126,28 +126,6 @@ void pcap_set_column(int, yyscan_t);
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
/*
* To quote the MSDN page for getaddrinfo() at
*
* https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx
*
* "Support for getaddrinfo on Windows 2000 and older versions
* The getaddrinfo function was added to the Ws2_32.dll on Windows XP and
* later. To execute an application that uses this function on earlier
* versions of Windows, then you need to include the Ws2tcpip.h and
* Wspiapi.h files. When the Wspiapi.h include file is added, the
* getaddrinfo function is defined to the WspiapiGetAddrInfo inline
* function in the Wspiapi.h file. At runtime, the WspiapiGetAddrInfo
* function is implemented in such a way that if the Ws2_32.dll or the
* Wship6.dll (the file containing getaddrinfo in the IPv6 Technology
* Preview for Windows 2000) does not include getaddrinfo, then a
* version of getaddrinfo is implemented inline based on code in the
* Wspiapi.h header file. This inline code will be used on older Windows
* platforms that do not natively support the getaddrinfo function."
*
* We use getaddrinfo(), so we include Wspiapi.h here.
*/
#include <wspiapi.h>
#else /* _WIN32 */
#include <sys/socket.h> /* for "struct sockaddr" in "struct addrinfo" */
#include <netdb.h> /* for "struct addrinfo" */

View file

@ -108,7 +108,7 @@
* read on systems with the same tv_sec size as the system on which
* the file was written.
*
* THe fields are unsigned, as that's what the pcap draft specification
* The fields are unsigned, as that's what the pcap draft specification
* says they are. (That gives pcap a 68-year Y2.038K reprieve, although
* in 2106 it runs out for good. pcapng doesn't have that problem,
* unless you pick a *really* high time stamp precision.)
@ -1224,7 +1224,7 @@ pcap_dump_ftell64(pcap_dumper_t *p)
}
#elif defined(_MSC_VER)
/*
* We have Visual Studio; we support only 2005 and later, so we have
* We have Visual Studio; we support only 2015 and later, so we have
* _ftelli64().
*/
int64_t
@ -1262,11 +1262,16 @@ pcap_dump_flush(pcap_dumper_t *p)
void
pcap_dump_close(pcap_dumper_t *p)
{
FILE *fp = (FILE *)p;
#ifdef notyet
if (ferror((FILE *)p))
if (ferror(fp))
return-an-error;
/* XXX should check return from fclose() too */
/* XXX should check return from fflush()/fclose() too */
#endif
(void)fclose((FILE *)p);
/* Don't close the standard output, but *do* flush it */
if (fp == stdout)
(void)fflush(fp);
else
(void)fclose(fp);
}

View file

@ -33,6 +33,7 @@ add_test_executable(findalldevstest)
add_test_executable(findalldevstest-perf)
add_test_executable(opentest)
add_test_executable(reactivatetest)
add_test_executable(versiontest)
add_test_executable(writecaptest)
if(NOT WIN32)
@ -48,4 +49,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
add_test_executable(valgrindtest)
endif()
add_subdirectory(fuzz)
if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR
CMAKE_SYSTEM_NAME STREQUAL "Linux")
if(IS_DIRECTORY ${CMAKE_HOME_DIRECTORY}/.git)
add_subdirectory(fuzz)
endif(IS_DIRECTORY ${CMAKE_HOME_DIRECTORY}/.git)
endif()

View file

@ -89,6 +89,7 @@ SRC = @VALGRINDTEST_SRC@ \
reactivatetest.c \
selpolltest.c \
threadsignaltest.c \
versiontest.c \
writecaptest.c
TESTS = $(SRC:.c=)
@ -148,6 +149,10 @@ valgrindtest: $(srcdir)/valgrindtest.c ../libpcap.a
$(CC) $(FULL_CFLAGS) -I. -L. -o valgrindtest $(srcdir)/valgrindtest.c \
../libpcap.a $(LIBS)
versiontest: $(srcdir)/versiontest.c ../libpcap.a
$(CC) $(FULL_CFLAGS) -I. -L. -o $@ $(srcdir)/versiontest.c \
../libpcap.a $(LIBS)
writecaptest: $(srcdir)/writecaptest.c ../libpcap.a
$(CC) $(FULL_CFLAGS) -I. -L. -o writecaptest $(srcdir)/writecaptest.c \
../libpcap.a $(LIBS)

View file

@ -356,6 +356,9 @@ main(int argc, char **argv)
free(cmdbuf);
pcap_freecode (&fcode);
pcap_close(pd);
#ifdef _WIN32
WSACleanup();
#endif
exit(0);
}

View file

@ -1,43 +0,0 @@
add_executable(fuzz_pcap onefile.c fuzz_pcap.c)
target_link_libraries(fuzz_pcap ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
if(NOT "${SANITIZER_FLAGS}" STREQUAL "")
set_target_properties(fuzz_pcap PROPERTIES
LINK_FLAGS "${SANITIZER_FLAGS}")
endif()
add_executable(fuzz_filter onefile.c fuzz_filter.c)
target_link_libraries(fuzz_filter ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
if(NOT "${SANITIZER_FLAGS}" STREQUAL "")
set_target_properties(fuzz_filter PROPERTIES
LINK_FLAGS "${SANITIZER_FLAGS}")
endif()
add_executable(fuzz_both onefile.c fuzz_both.c)
target_link_libraries(fuzz_both ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
if(NOT "${SANITIZER_FLAGS}" STREQUAL "")
set_target_properties(fuzz_both PROPERTIES
LINK_FLAGS "${SANITIZER_FLAGS}")
endif()
if(ENABLE_REMOTE AND "$ENV{CFLAGS}" MATCHES "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION")
add_executable(fuzz_rclient onefile.c fuzz_rclient.c)
target_link_libraries(fuzz_rclient ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
if(NOT "${SANITIZER_FLAGS}" STREQUAL "")
set_target_properties(fuzz_rclient PROPERTIES
LINK_FLAGS "${SANITIZER_FLAGS}")
endif()
add_executable(fuzz_rserver onefile.c fuzz_rserver.c ../../rpcapd/daemon.c)
check_function_exists(crypt HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
if(HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
set(HAVE_CRYPT TRUE)
else(HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} crypt)
endif(HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
target_link_libraries(fuzz_rserver ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
if(NOT "${SANITIZER_FLAGS}" STREQUAL "")
set_target_properties(fuzz_rserver PROPERTIES
LINK_FLAGS "${SANITIZER_FLAGS}")
endif()
endif(ENABLE_REMOTE AND "$ENV{CFLAGS}" MATCHES "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION")

View file

@ -1,101 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <pcap/pcap.h>
FILE * outfile = NULL;
static int bufferToFile(const char * name, const uint8_t *Data, size_t Size) {
FILE * fd;
if (remove(name) != 0) {
if (errno != ENOENT) {
printf("failed remove, errno=%d\n", errno);
return -1;
}
}
fd = fopen(name, "wb");
if (fd == NULL) {
printf("failed open, errno=%d\n", errno);
return -2;
}
if (fwrite (Data, 1, Size, fd) != Size) {
fclose(fd);
return -3;
}
fclose(fd);
return 0;
}
void fuzz_openFile(const char * name) {
if (outfile != NULL) {
fclose(outfile);
}
outfile = fopen(name, "w");
}
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
pcap_t * pkts;
char errbuf[PCAP_ERRBUF_SIZE];
const u_char *pkt;
struct pcap_pkthdr *header;
int r;
size_t filterSize;
char * filter;
struct bpf_program bpf;
//initialize output file
if (outfile == NULL) {
outfile = fopen("/dev/null", "w");
if (outfile == NULL) {
return 0;
}
}
if (Size < 1) {
return 0;
}
filterSize = Data[0];
if (Size < 1+filterSize || filterSize == 0) {
return 0;
}
//rewrite buffer to a file as libpcap does not have buffer inputs
if (bufferToFile("/tmp/fuzz.pcap", Data+1+filterSize, Size-(1+filterSize)) < 0) {
return 0;
}
//initialize structure
pkts = pcap_open_offline("/tmp/fuzz.pcap", errbuf);
if (pkts == NULL) {
fprintf(outfile, "Couldn't open pcap file %s\n", errbuf);
return 0;
}
filter = malloc(filterSize);
memcpy(filter, Data+1, filterSize);
//null terminate string
filter[filterSize-1] = 0;
if (pcap_compile(pkts, &bpf, filter, 1, PCAP_NETMASK_UNKNOWN) == 0) {
//loop over packets
r = pcap_next_ex(pkts, &header, &pkt);
while (r > 0) {
//checks filter
fprintf(outfile, "packet length=%d/%d filter=%d\n",header->caplen, header->len, pcap_offline_filter(&bpf, header, pkt));
r = pcap_next_ex(pkts, &header, &pkt);
}
//close structure
pcap_close(pkts);
pcap_freecode(&bpf);
}
else {
pcap_close(pkts);
}
free(filter);
return 0;
}

View file

@ -1,2 +0,0 @@
[libfuzzer]
max_len = 65535

View file

@ -1,43 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pcap/pcap.h>
void fuzz_openFile(const char * name){
//do nothing
}
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
pcap_t * pkts;
struct bpf_program bpf;
char * filter;
//we need at least 1 byte for linktype
if (Size < 1) {
return 0;
}
//initialize structure snaplen = 65535
pkts = pcap_open_dead(Data[Size-1], 0xFFFF);
if (pkts == NULL) {
printf("pcap_open_dead failed\n");
return 0;
}
filter = malloc(Size);
memcpy(filter, Data, Size);
//null terminate string
filter[Size-1] = 0;
if (pcap_compile(pkts, &bpf, filter, 1, PCAP_NETMASK_UNKNOWN) == 0) {
pcap_setfilter(pkts, &bpf);
pcap_close(pkts);
pcap_freecode(&bpf);
}
else {
pcap_close(pkts);
}
free(filter);
return 0;
}

View file

@ -1,2 +0,0 @@
[libfuzzer]
max_len = 4096

View file

@ -1,80 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <pcap/pcap.h>
FILE * outfile = NULL;
static int bufferToFile(const char * name, const uint8_t *Data, size_t Size) {
FILE * fd;
if (remove(name) != 0) {
if (errno != ENOENT) {
printf("failed remove, errno=%d\n", errno);
return -1;
}
}
fd = fopen(name, "wb");
if (fd == NULL) {
printf("failed open, errno=%d\n", errno);
return -2;
}
if (fwrite (Data, 1, Size, fd) != Size) {
fclose(fd);
return -3;
}
fclose(fd);
return 0;
}
void fuzz_openFile(const char * name) {
if (outfile != NULL) {
fclose(outfile);
}
outfile = fopen(name, "w");
}
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
pcap_t * pkts;
char errbuf[PCAP_ERRBUF_SIZE];
const u_char *pkt;
struct pcap_pkthdr *header;
struct pcap_stat stats;
int r;
//initialize output file
if (outfile == NULL) {
outfile = fopen("/dev/null", "w");
if (outfile == NULL) {
return 0;
}
}
//rewrite buffer to a file as libpcap does not have buffer inputs
if (bufferToFile("/tmp/fuzz.pcap", Data, Size) < 0) {
return 0;
}
//initialize structure
pkts = pcap_open_offline("/tmp/fuzz.pcap", errbuf);
if (pkts == NULL) {
fprintf(outfile, "Couldn't open pcap file %s\n", errbuf);
return 0;
}
//loop over packets
r = pcap_next_ex(pkts, &header, &pkt);
while (r > 0) {
//TODO pcap_offline_filter
fprintf(outfile, "packet length=%d/%d\n",header->caplen, header->len);
r = pcap_next_ex(pkts, &header, &pkt);
}
if (pcap_stats(pkts, &stats) == 0) {
fprintf(outfile, "number of packets=%d\n", stats.ps_recv);
}
//close structure
pcap_close(pkts);
return 0;
}

View file

@ -1,2 +0,0 @@
[libfuzzer]
max_len = 65535

View file

@ -1,54 +0,0 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
void fuzz_openFile(const char * name);
int main(int argc, char** argv)
{
FILE * fp;
uint8_t *Data;
size_t Size;
if (argc == 3) {
fuzz_openFile(argv[2]);
} else if (argc != 2) {
return 1;
}
//opens the file, get its size, and reads it into a buffer
fp = fopen(argv[1], "rb");
if (fp == NULL) {
return 2;
}
if (fseek(fp, 0L, SEEK_END) != 0) {
fclose(fp);
return 2;
}
Size = ftell(fp);
if (Size == (size_t) -1) {
fclose(fp);
return 2;
}
if (fseek(fp, 0L, SEEK_SET) != 0) {
fclose(fp);
return 2;
}
Data = malloc(Size);
if (Data == NULL) {
fclose(fp);
return 2;
}
if (fread(Data, Size, 1, fp) != 1) {
fclose(fp);
free(Data);
return 2;
}
//launch fuzzer
LLVMFuzzerTestOneInput(Data, Size);
free(Data);
fclose(fp);
return 0;
}

29
testprogs/versiontest.c Normal file
View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <pcap.h>
#include <stdio.h>
int
main(void)
{
printf("%s\n", pcap_lib_version());
}