summaryrefslogtreecommitdiffstats
path: root/cmake/modules/FindPCAP.cmake
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
commite4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch)
tree68cb5ef9081156392f1dd62a00c6ccc1451b93df /cmake/modules/FindPCAP.cmake
parentInitial commit. (diff)
downloadwireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz
wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'cmake/modules/FindPCAP.cmake')
-rw-r--r--cmake/modules/FindPCAP.cmake329
1 files changed, 329 insertions, 0 deletions
diff --git a/cmake/modules/FindPCAP.cmake b/cmake/modules/FindPCAP.cmake
new file mode 100644
index 0000000..eb9565b
--- /dev/null
+++ b/cmake/modules/FindPCAP.cmake
@@ -0,0 +1,329 @@
+#
+# - Find libpcap
+# Find the native PCAP includes and library
+#
+# PCAP_INCLUDE_DIRS - where to find pcap.h, etc.
+# PCAP_LIBRARIES - List of libraries when using pcap.
+# PCAP_FOUND - True if pcap found.
+
+include(FindWSWinLibs)
+FindWSWinLibs("libpcap-*" "PCAP_HINTS")
+
+#
+# First, try pkg-config on platforms other than Windows.
+#
+if(NOT USE_REPOSITORY)
+ find_package(PkgConfig)
+ pkg_search_module(PC_PCAP libpcap)
+endif()
+
+if(NOT PC_PCAP_FOUND AND NOT WIN32)
+ #
+ # That didn't work. Try to retrieve hints from pcap-config.
+ # Do not use it on Windows as pcap-config is a shell script.
+ #
+ find_program(PCAP_CONFIG pcap-config)
+ if(PCAP_CONFIG)
+ #
+ # We have pcap-config; use it.
+ #
+ # First, get the include directory.
+ #
+ execute_process(COMMAND "${PCAP_CONFIG}" "--cflags"
+ RESULT_VARIABLE PCAP_CONFIG_RESULT
+ OUTPUT_VARIABLE PCAP_CONFIG_OUTPUT
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ if(NOT PCAP_CONFIG_RESULT EQUAL 0)
+ message(FATAL_ERROR "pcap-config --cflags failed")
+ endif()
+ #
+ # Assumes there's exactly one -I flag in the output
+ # of pcap-config --cflags. That *should* be the case.
+ # Note that the hint might be bogus, on macOS it could be
+ # -I/usr/local/include even though the header isn't
+ # there (it may be under /usr/include or it may be
+ # buried in the Xcode app bundle).
+ #
+ string(REGEX REPLACE "^-I" "" PCAP_CONFIG_INCLUDE_DIRS "${PCAP_CONFIG_OUTPUT}")
+
+ # Now, get the library search path.
+ execute_process(COMMAND "${PCAP_CONFIG}" "--libs"
+ RESULT_VARIABLE PCAP_CONFIG_RESULT
+ OUTPUT_VARIABLE PCAP_CONFIG_OUTPUT
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ if(NOT PCAP_CONFIG_RESULT EQUAL 0)
+ message(FATAL_ERROR "pcap-config --libs failed")
+ endif()
+ separate_arguments(LIBS_LIST UNIX_COMMAND ${PCAP_CONFIG_OUTPUT})
+ set(PCAP_CONFIG_LIBRARY_DIRS "")
+ foreach(_arg IN LISTS LIBS_LIST)
+ # At most one -L path is expected for -lpcap.
+ if(_arg MATCHES "^-L")
+ string(REGEX REPLACE "^-L" "" _dir ${_arg})
+ list(APPEND PCAP_CONFIG_LIBRARY_DIRS ${_dir})
+ endif()
+ endforeach()
+
+ if(UNIX AND CMAKE_FIND_LIBRARY_SUFFIXES STREQUAL ".a")
+ # Now, get the library directories and libraries for static linking.
+ # (XXX - what about AIX?)
+ execute_process(COMMAND "${PCAP_CONFIG}" "--libs" "--static"
+ RESULT_VARIABLE PCAP_CONFIG_RESULT
+ OUTPUT_VARIABLE PCAP_CONFIG_OUTPUT
+ )
+ if(NOT PCAP_CONFIG_RESULT EQUAL 0)
+ message(FATAL_ERROR "pcap-config --libs --static failed")
+ endif()
+ separate_arguments(LIBS_LIST UNIX_COMMAND ${PCAP_CONFIG_OUTPUT})
+ set(PCAP_CONFIG_STATIC_LIBRARY_DIRS "")
+ set(PCAP_CONFIG_STATIC_LIBRARIES "")
+ foreach(_arg IN LISTS LIBS_LIST)
+ if(_arg MATCHES "^-L")
+ # Add this directory to the library directory hints.
+ string(REGEX REPLACE "^-L" "" _dir ${_arg})
+ list(APPEND PCAP_CONFIG_STATIC_LIBRARY_DIRS ${_dir})
+ elseif(_arg MATCHES "^-l")
+ # Add this library to the requirements for static linking.
+ string(REGEX REPLACE "^-l" "" _lib ${_arg})
+ list(APPEND PCAP_CONFIG_STATIC_LIBRARIES ${_lib})
+ endif()
+ endforeach()
+ endif()
+ endif()
+endif()
+
+#
+# Locate the actual include directory. For pkg-config the
+# PC_PCAP_INCLUDE_DIRS variable could be empty if the default
+# header search path is sufficient to locate the header file.
+# For macOS, the directory returned by pcap-config is wrong, so
+# this will make sure to find a valid path.
+#
+find_path(PCAP_INCLUDE_DIR
+ NAMES
+ pcap/pcap.h
+ pcap.h
+ PATH_SUFFIXES
+ wpcap
+ HINTS
+ ${PC_PCAP_INCLUDE_DIRS}
+ ${PCAP_CONFIG_INCLUDE_DIRS}
+ "${PCAP_HINTS}/Include"
+)
+
+# On Windows we load wpcap.dll explicitly and probe its functions in
+# capture\capture-wpcap.c. We don't want to link with pcap.lib since
+# that would bring in the non-capturing (null) pcap.dll from the vcpkg
+# library.
+if(WIN32 AND NOT CMAKE_CROSSCOMPILING)
+ set(_pkg_required_vars PCAP_INCLUDE_DIR)
+else()
+ find_library(PCAP_LIBRARY
+ NAMES
+ pcap
+ wpcap
+ HINTS
+ ${PC_PCAP_LIBRARY_DIRS}
+ ${PCAP_CONFIG_LIBRARY_DIRS}
+ )
+ set(_pkg_required_vars PCAP_LIBRARY PCAP_INCLUDE_DIR)
+endif()
+
+if(UNIX AND CMAKE_FIND_LIBRARY_SUFFIXES STREQUAL ".a")
+ # Try to find the static library (XXX - what about AIX?)
+ if(PC_PCAP_FOUND)
+ set(_pcap_static_libraries ${PC_PCAP_STATIC_LIBRARIES})
+ elseif(PCAP_CONFIG)
+ set(_pcap_static_libraries ${PCAP_CONFIG_STATIC_LIBRARIES})
+ else()
+ #
+ # No pkg-config nor pcap-config found, hope that this single library is
+ # sufficient for static linking.
+ #
+ set(_pcap_static_libraries pcap)
+ endif()
+
+ set(PCAP_STATIC_LIBRARIES "")
+ foreach(_lib IN LISTS _pcap_static_libraries)
+ #
+ # Try to find that library, so we get its full path, as
+ # we do with dynamic libraries.
+ #
+ string(MAKE_C_IDENTIFIER "PCAP_STATIC_${_lib}_LIBRARY" _libvar)
+ find_library(${_libvar} ${_lib}
+ HINTS
+ ${PC_PCAP_STATIC_LIBRARY_DIRS}
+ ${PCAP_CONFIG_STATIC_LIBRARY_DIRS}
+ )
+ set(_libpath ${${_libvar}})
+ if(_libpath)
+ list(APPEND PCAP_STATIC_LIBRARIES ${_libpath})
+ endif()
+ endforeach()
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(PCAP DEFAULT_MSG ${_pkg_required_vars})
+mark_as_advanced(${_pkg_required_vars})
+
+if(PCAP_FOUND)
+ set(PCAP_INCLUDE_DIRS ${PCAP_INCLUDE_DIR})
+ if(UNIX AND CMAKE_FIND_LIBRARY_SUFFIXES STREQUAL ".a")
+ # Link with static libpcap and its transitive dependencies.
+ set(PCAP_LIBRARIES ${PCAP_STATIC_LIBRARIES})
+ else()
+ set(PCAP_LIBRARIES ${PCAP_LIBRARY})
+ endif()
+
+ #Functions
+ include( CMakePushCheckState )
+ include( CheckFunctionExists )
+ include( CheckVariableExists )
+
+ cmake_push_check_state()
+ set( CMAKE_REQUIRED_INCLUDES ${PCAP_INCLUDE_DIRS} )
+ set( CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARIES} )
+
+ include(CheckSymbolExists)
+
+ if(WIN32 AND NOT CMAKE_CROSSCOMPILING)
+ #
+ # Prepopulate some values. WinPcap 3.1 and later, and Npcap, have these
+ # in their SDK, and compilation checks on Windows can be slow. We check
+ # whether they're present at run time, when we load wpcap.dll, and work
+ # around their absence or report an error.
+ #
+ set(HAVE_PCAP_FREECODE TRUE)
+ set(HAVE_PCAP_CREATE TRUE)
+ set(HAVE_PCAP_FREE_DATALINKS TRUE)
+ set(HAVE_PCAP_OPEN TRUE)
+ set(HAVE_PCAP_SETSAMPLING TRUE)
+ set(HAVE_PCAP_SET_TSTAMP_PRECISION TRUE)
+ set(HAVE_PCAP_SET_TSTAMP_TYPE TRUE)
+ else(WIN32)
+ #
+ # Make sure we have at least libpcap 0.8, because we require at
+ # least libpcap 0.8's APIs.
+ #
+ # We check whether pcap_lib_version is defined in the pcap header,
+ # using it as a proxy for all the 0.8 API's. if not, we fail.
+ #
+ check_symbol_exists( pcap_lib_version ${PCAP_INCLUDE_DIR}/pcap.h HAVE_PCAP_LIB_VERSION )
+ if( NOT HAVE_PCAP_LIB_VERSION )
+ message(FATAL_ERROR "You need libpcap 0.8 or later")
+ endif( NOT HAVE_PCAP_LIB_VERSION )
+
+ check_function_exists( "pcap_freecode" HAVE_PCAP_FREECODE )
+ check_function_exists( "pcap_create" HAVE_PCAP_CREATE )
+ check_function_exists( "pcap_free_datalinks" HAVE_PCAP_FREE_DATALINKS )
+ #
+ # macOS Sonoma's libpcap includes stub versions of the remote-
+ # capture APIs. They are exported as "weakly linked symbols".
+ #
+ # Xcode 15 offers only a macOS Sonoma SDK, which has a .tbd
+ # file for libpcap that claims it includes those APIs. (Newer
+ # versions of macOS don't provide the system shared libraries,
+ # they only provide the dyld shared cache containing those
+ # libraries, so the OS provides SDKs that include a .tbd file
+ # to use when linking.)
+ #
+ # This means that check_function_exists() will think that
+ # the remote-capture APIs are present, including pcap_open().
+ #
+ # However, they are *not* present in macOS Ventura and earlier,
+ # which means that building on Ventura with Xcode 15 produces
+ # executables that fail to start because one of those APIs
+ # isn't found in the system libpcap.
+ #
+ # Protecting calls to those APIs with __builtin_available()
+ # does not prevent this, because the libpcap header files
+ # in the Sonoma SDK mark them as being first available
+ # in macOS 10.13, just like all the other routines introduced
+ # in libpcap 1.9, even though they're only available if libpcap
+ # is built with remote capture enabled or stub routines are
+ # provided. (A fix to enable this has been checked into the
+ # libpcap repository, and may end up in a later version of
+ # the SDK.)
+ #
+ # Given all that, and given that the versions of the
+ # remote-capture APIs in Sonoma are stubs that always fail,
+ # there doesn't seem to be any point in checking for pcap_open()
+ # if we're linking against the Apple libpcap.
+ #
+ # However, if we're *not* linking against the Apple libpcap,
+ # we should check for it, so that we can use it if it's present.
+ #
+ # So we check for pcap_open if 1) this isn't macOS or 2) the
+ # the libpcap we found is not a system library, meaning that
+ # its path begins neither with /usr/lib (meaning it's a system
+ # dylib) nor /Application/Xcode.app (meaning it's a file in
+ # the Xcode SDK).
+ #
+ if( NOT APPLE OR NOT
+ (PCAP_LIBRARY MATCHES "/usr/lib/.*" OR
+ PCAP_LIBRARY MATCHES "/Application/Xcode.app/.*"))
+ check_function_exists( "pcap_open" HAVE_PCAP_OPEN )
+ endif()
+ if( HAVE_PCAP_OPEN )
+ #
+ # XXX - this *should* be checked for independently of checking
+ # for pcap_open(), as you might have pcap_setsampling() without
+ # remote capture support.
+ #
+ # However, 1) the sampling options are treated as remote options
+ # in the GUI and 2) having pcap_setsampling() doesn't mean
+ # you have sampling support. libpcap needs a way to indicate
+ # whether a given device supports sampling, and the GUI should
+ # be changed to decouple them.
+ #
+ # (Actually, libpcap needs a general mechanism to offer options
+ # for particular devices, and Wireshark needs to use that
+ # mechanism. The former is a work in progress.)
+ #
+ # (Note: another work in progress is support for remote
+ # capturing using pcap_create()/pcap_activate(), which we
+ # also need to support once it's available.)
+ #
+ check_function_exists( "pcap_setsampling" HAVE_PCAP_SETSAMPLING )
+ endif( HAVE_PCAP_OPEN )
+ endif()
+
+ if( HAVE_PCAP_CREATE )
+ #
+ # If we have pcap_create(), we have pcap_set_buffer_size(), and
+ # can set the capture buffer size.
+ #
+ # Otherwise, if this is Windows, we have pcap_setbuff(), and can
+ # set the capture buffer size.
+ #
+ set( CAN_SET_CAPTURE_BUFFER_SIZE TRUE )
+ endif()
+ check_function_exists( "pcap_set_tstamp_precision" HAVE_PCAP_SET_TSTAMP_PRECISION )
+ check_function_exists( "pcap_set_tstamp_type" HAVE_PCAP_SET_TSTAMP_TYPE )
+ # Remote pcap checks
+ if( HAVE_PCAP_OPEN )
+ set( HAVE_PCAP_REMOTE 1 )
+ endif()
+
+ check_symbol_exists(PCAP_ERROR_PROMISC_PERM_DENIED ${PCAP_INCLUDE_DIR}/pcap.h HAVE_PCAP_ERROR_PROMISC_PERM_DENIED)
+ check_symbol_exists(PCAP_WARNING_TSTAMP_TYPE_NOTSUP ${PCAP_INCLUDE_DIR}/pcap.h HAVE_PCAP_WARNING_TSTAMP_TYPE_NOTSUP)
+
+ cmake_pop_check_state()
+endif()
+
+if(PCAP_FOUND AND NOT TARGET pcap::pcap)
+ if(WIN32)
+ add_library(pcap::pcap INTERFACE IMPORTED)
+ set_target_properties(pcap::pcap PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${PCAP_INCLUDE_DIRS}"
+ )
+ else()
+ add_library(pcap::pcap UNKNOWN IMPORTED)
+ set_target_properties(pcap::pcap PROPERTIES
+ IMPORTED_LOCATION "${PCAP_LIBRARIES}"
+ INTERFACE_INCLUDE_DIRECTORIES "${PCAP_INCLUDE_DIRS}"
+ )
+ endif()
+endif()