3 # Find the native PCAP includes and library
5 # PCAP_INCLUDE_DIRS - where to find pcap.h, etc.
6 # PCAP_LIBRARIES - List of libraries when using pcap.
7 # PCAP_FOUND - True if pcap found.
10 FindWSWinLibs("libpcap-*" "PCAP_HINTS")
13 # First, try pkg-config on platforms other than Windows.
15 if(NOT USE_REPOSITORY)
16 find_package(PkgConfig)
17 pkg_search_module(PC_PCAP libpcap)
20 if(NOT PC_PCAP_FOUND AND NOT WIN32)
22 # That didn't work. Try to retrieve hints from pcap-config.
23 # Do not use it on Windows as pcap-config is a shell script.
25 find_program(PCAP_CONFIG pcap-config)
28 # We have pcap-config; use it.
30 # First, get the include directory.
32 execute_process(COMMAND "${PCAP_CONFIG}" "--cflags"
33 RESULT_VARIABLE PCAP_CONFIG_RESULT
34 OUTPUT_VARIABLE PCAP_CONFIG_OUTPUT
35 OUTPUT_STRIP_TRAILING_WHITESPACE
37 if(NOT PCAP_CONFIG_RESULT EQUAL 0)
38 message(FATAL_ERROR "pcap-config --cflags failed")
41 # Assumes there's exactly one -I flag in the output
42 # of pcap-config --cflags. That *should* be the case.
43 # Note that the hint might be bogus, on macOS it could be
44 # -I/usr/local/include even though the header isn't
45 # there (it may be under /usr/include or it may be
46 # buried in the Xcode app bundle).
48 string(REGEX REPLACE "^-I" "" PCAP_CONFIG_INCLUDE_DIRS "${PCAP_CONFIG_OUTPUT}")
50 # Now, get the library search path.
51 execute_process(COMMAND "${PCAP_CONFIG}" "--libs"
52 RESULT_VARIABLE PCAP_CONFIG_RESULT
53 OUTPUT_VARIABLE PCAP_CONFIG_OUTPUT
54 OUTPUT_STRIP_TRAILING_WHITESPACE
56 if(NOT PCAP_CONFIG_RESULT EQUAL 0)
57 message(FATAL_ERROR "pcap-config --libs failed")
59 separate_arguments(LIBS_LIST UNIX_COMMAND ${PCAP_CONFIG_OUTPUT})
60 set(PCAP_CONFIG_LIBRARY_DIRS "")
61 foreach(_arg IN LISTS LIBS_LIST)
62 # At most one -L path is expected for -lpcap.
63 if(_arg MATCHES "^-L")
64 string(REGEX REPLACE "^-L" "" _dir ${_arg})
65 list(APPEND PCAP_CONFIG_LIBRARY_DIRS ${_dir})
69 if(UNIX AND CMAKE_FIND_LIBRARY_SUFFIXES STREQUAL ".a")
70 # Now, get the library directories and libraries for static linking.
71 # (XXX - what about AIX?)
72 execute_process(COMMAND "${PCAP_CONFIG}" "--libs" "--static"
73 RESULT_VARIABLE PCAP_CONFIG_RESULT
74 OUTPUT_VARIABLE PCAP_CONFIG_OUTPUT
76 if(NOT PCAP_CONFIG_RESULT EQUAL 0)
77 message(FATAL_ERROR "pcap-config --libs --static failed")
79 separate_arguments(LIBS_LIST UNIX_COMMAND ${PCAP_CONFIG_OUTPUT})
80 set(PCAP_CONFIG_STATIC_LIBRARY_DIRS "")
81 set(PCAP_CONFIG_STATIC_LIBRARIES "")
82 foreach(_arg IN LISTS LIBS_LIST)
83 if(_arg MATCHES "^-L")
84 # Add this directory to the library directory hints.
85 string(REGEX REPLACE "^-L" "" _dir ${_arg})
86 list(APPEND PCAP_CONFIG_STATIC_LIBRARY_DIRS ${_dir})
87 elseif(_arg MATCHES "^-l")
88 # Add this library to the requirements for static linking.
89 string(REGEX REPLACE "^-l" "" _lib ${_arg})
90 list(APPEND PCAP_CONFIG_STATIC_LIBRARIES ${_lib})
98 # Locate the actual include directory. For pkg-config the
99 # PC_PCAP_INCLUDE_DIRS variable could be empty if the default
100 # header search path is sufficient to locate the header file.
101 # For macOS, the directory returned by pcap-config is wrong, so
102 # this will make sure to find a valid path.
104 find_path(PCAP_INCLUDE_DIR
111 ${PC_PCAP_INCLUDE_DIRS}
112 ${PCAP_CONFIG_INCLUDE_DIRS}
113 "${PCAP_HINTS}/Include"
116 # On Windows we load wpcap.dll explicitly and probe its functions in
117 # capture\capture-wpcap.c. We don't want to link with pcap.lib since
118 # that would bring in the non-capturing (null) pcap.dll from the vcpkg
120 if(WIN32 AND NOT CMAKE_CROSSCOMPILING)
121 set(_pkg_required_vars PCAP_INCLUDE_DIR)
123 find_library(PCAP_LIBRARY
128 ${PC_PCAP_LIBRARY_DIRS}
129 ${PCAP_CONFIG_LIBRARY_DIRS}
131 set(_pkg_required_vars PCAP_LIBRARY PCAP_INCLUDE_DIR)
134 if(UNIX AND CMAKE_FIND_LIBRARY_SUFFIXES STREQUAL ".a")
135 # Try to find the static library (XXX - what about AIX?)
137 set(_pcap_static_libraries ${PC_PCAP_STATIC_LIBRARIES})
139 set(_pcap_static_libraries ${PCAP_CONFIG_STATIC_LIBRARIES})
142 # No pkg-config nor pcap-config found, hope that this single library is
143 # sufficient for static linking.
145 set(_pcap_static_libraries pcap)
148 set(PCAP_STATIC_LIBRARIES "")
149 foreach(_lib IN LISTS _pcap_static_libraries)
151 # Try to find that library, so we get its full path, as
152 # we do with dynamic libraries.
154 string(MAKE_C_IDENTIFIER "PCAP_STATIC_${_lib}_LIBRARY" _libvar)
155 find_library(${_libvar} ${_lib}
157 ${PC_PCAP_STATIC_LIBRARY_DIRS}
158 ${PCAP_CONFIG_STATIC_LIBRARY_DIRS}
160 set(_libpath ${${_libvar}})
162 list(APPEND PCAP_STATIC_LIBRARIES ${_libpath})
167 include(FindPackageHandleStandardArgs)
168 find_package_handle_standard_args(PCAP DEFAULT_MSG ${_pkg_required_vars})
169 mark_as_advanced(${_pkg_required_vars})
172 set(PCAP_INCLUDE_DIRS ${PCAP_INCLUDE_DIR})
173 if(UNIX AND CMAKE_FIND_LIBRARY_SUFFIXES STREQUAL ".a")
174 # Link with static libpcap and its transitive dependencies.
175 set(PCAP_LIBRARIES ${PCAP_STATIC_LIBRARIES})
177 set(PCAP_LIBRARIES ${PCAP_LIBRARY})
181 include( CMakePushCheckState )
182 include( CheckFunctionExists )
183 include( CheckVariableExists )
185 cmake_push_check_state()
186 set( CMAKE_REQUIRED_INCLUDES ${PCAP_INCLUDE_DIRS} )
187 set( CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARIES} )
189 include(CheckSymbolExists)
191 if(WIN32 AND NOT CMAKE_CROSSCOMPILING)
193 # Prepopulate some values. WinPcap 3.1 and later, and Npcap, have these
194 # in their SDK, and compilation checks on Windows can be slow. We check
195 # whether they're present at run time, when we load wpcap.dll, and work
196 # around their absence or report an error.
198 set(HAVE_PCAP_FREECODE TRUE)
199 set(HAVE_PCAP_CREATE TRUE)
200 set(HAVE_PCAP_FREE_DATALINKS TRUE)
201 set(HAVE_PCAP_OPEN TRUE)
202 set(HAVE_PCAP_SETSAMPLING TRUE)
203 set(HAVE_PCAP_SET_TSTAMP_PRECISION TRUE)
204 set(HAVE_PCAP_SET_TSTAMP_TYPE TRUE)
207 # Make sure we have at least libpcap 0.8, because we require at
208 # least libpcap 0.8's APIs.
210 # We check whether pcap_lib_version is defined in the pcap header,
211 # using it as a proxy for all the 0.8 API's. if not, we fail.
213 check_symbol_exists( pcap_lib_version ${PCAP_INCLUDE_DIR}/pcap.h HAVE_PCAP_LIB_VERSION )
214 if( NOT HAVE_PCAP_LIB_VERSION )
215 message(FATAL_ERROR "You need libpcap 0.8 or later")
216 endif( NOT HAVE_PCAP_LIB_VERSION )
218 check_function_exists( "pcap_freecode" HAVE_PCAP_FREECODE )
219 check_function_exists( "pcap_create" HAVE_PCAP_CREATE )
220 check_function_exists( "pcap_free_datalinks" HAVE_PCAP_FREE_DATALINKS )
222 # macOS Sonoma's libpcap includes stub versions of the remote-
223 # capture APIs. They are exported as "weakly linked symbols".
225 # Xcode 15 offers only a macOS Sonoma SDK, which has a .tbd
226 # file for libpcap that claims it includes those APIs. (Newer
227 # versions of macOS don't provide the system shared libraries,
228 # they only provide the dyld shared cache containing those
229 # libraries, so the OS provides SDKs that include a .tbd file
230 # to use when linking.)
232 # This means that check_function_exists() will think that
233 # the remote-capture APIs are present, including pcap_open().
235 # However, they are *not* present in macOS Ventura and earlier,
236 # which means that building on Ventura with Xcode 15 produces
237 # executables that fail to start because one of those APIs
238 # isn't found in the system libpcap.
240 # Protecting calls to those APIs with __builtin_available()
241 # does not prevent this, because the libpcap header files
242 # in the Sonoma SDK mark them as being first available
243 # in macOS 10.13, just like all the other routines introduced
244 # in libpcap 1.9, even though they're only available if libpcap
245 # is built with remote capture enabled or stub routines are
246 # provided. (A fix to enable this has been checked into the
247 # libpcap repository, and may end up in a later version of
250 # Given all that, and given that the versions of the
251 # remote-capture APIs in Sonoma are stubs that always fail,
252 # there doesn't seem to be any point in checking for pcap_open()
253 # if we're linking against the Apple libpcap.
255 # However, if we're *not* linking against the Apple libpcap,
256 # we should check for it, so that we can use it if it's present.
258 # So we check for pcap_open if 1) this isn't macOS or 2) the
259 # the libpcap we found is not a system library, meaning that
260 # its path begins neither with /usr/lib (meaning it's a system
261 # dylib) nor /Application/Xcode.app (meaning it's a file in
265 (PCAP_LIBRARY MATCHES "/usr/lib/.*" OR
266 PCAP_LIBRARY MATCHES "/Application/Xcode.app/.*"))
267 check_function_exists( "pcap_open" HAVE_PCAP_OPEN )
271 # XXX - this *should* be checked for independently of checking
272 # for pcap_open(), as you might have pcap_setsampling() without
273 # remote capture support.
275 # However, 1) the sampling options are treated as remote options
276 # in the GUI and 2) having pcap_setsampling() doesn't mean
277 # you have sampling support. libpcap needs a way to indicate
278 # whether a given device supports sampling, and the GUI should
279 # be changed to decouple them.
281 # (Actually, libpcap needs a general mechanism to offer options
282 # for particular devices, and Wireshark needs to use that
283 # mechanism. The former is a work in progress.)
285 # (Note: another work in progress is support for remote
286 # capturing using pcap_create()/pcap_activate(), which we
287 # also need to support once it's available.)
289 check_function_exists( "pcap_setsampling" HAVE_PCAP_SETSAMPLING )
290 endif( HAVE_PCAP_OPEN )
293 if( HAVE_PCAP_CREATE )
295 # If we have pcap_create(), we have pcap_set_buffer_size(), and
296 # can set the capture buffer size.
298 # Otherwise, if this is Windows, we have pcap_setbuff(), and can
299 # set the capture buffer size.
301 set( CAN_SET_CAPTURE_BUFFER_SIZE TRUE )
303 check_function_exists( "pcap_set_tstamp_precision" HAVE_PCAP_SET_TSTAMP_PRECISION )
304 check_function_exists( "pcap_set_tstamp_type" HAVE_PCAP_SET_TSTAMP_TYPE )
307 set( HAVE_PCAP_REMOTE 1 )
310 check_symbol_exists(PCAP_ERROR_PROMISC_PERM_DENIED ${PCAP_INCLUDE_DIR}/pcap.h HAVE_PCAP_ERROR_PROMISC_PERM_DENIED)
311 check_symbol_exists(PCAP_WARNING_TSTAMP_TYPE_NOTSUP ${PCAP_INCLUDE_DIR}/pcap.h HAVE_PCAP_WARNING_TSTAMP_TYPE_NOTSUP)
313 cmake_pop_check_state()
316 if(PCAP_FOUND AND NOT TARGET pcap::pcap)
318 add_library(pcap::pcap INTERFACE IMPORTED)
319 set_target_properties(pcap::pcap PROPERTIES
320 INTERFACE_INCLUDE_DIRECTORIES "${PCAP_INCLUDE_DIRS}"
323 add_library(pcap::pcap UNKNOWN IMPORTED)
324 set_target_properties(pcap::pcap PROPERTIES
325 IMPORTED_LOCATION "${PCAP_LIBRARIES}"
326 INTERFACE_INCLUDE_DIRECTORIES "${PCAP_INCLUDE_DIRS}"