xref: /freebsd/contrib/libpcap/CMakeLists.txt (revision 7937bfbc0ca53fe7cdd0d54414f9296e273a518e)
1if(WIN32)
2    #
3    # We need 3.12 or later, so that we can set policy CMP0074; see
4    # below.
5    #
6    cmake_minimum_required(VERSION 3.12)
7else(WIN32)
8    #
9    # For now:
10    #
11    #  if this is a version of CMake less than 3.5, require only
12    #  2.8.12, just in case somebody is configuring with CMake
13    #  on a "long-term support" version # of some OS and that
14    #  version supplies an older version of CMake;
15    #
16    #  otherwise, require 3.5, so we don't get messages warning
17    #  that support for versions of CMake lower than 3.5 is
18    #  deprecated.
19    #
20    if(CMAKE_VERSION VERSION_LESS "3.5")
21        cmake_minimum_required(VERSION 2.8.12)
22    else()
23        cmake_minimum_required(VERSION 3.5)
24    endif()
25endif(WIN32)
26
27#
28# Apple doesn't build with an install_name starting with @rpath, and
29# neither do we with autotools; don't do so with CMake, either, and
30# suppress warnings about that.
31#
32# Setting CMAKE_MACOSX_RPATH to FALSE uses the old behavior,
33# but removes the POLICY CMP0042 OLD deprecated warning.
34# See https://cmake.org/cmake/help/latest/policy/CMP0042.html
35#
36if (NOT DEFINED CMAKE_MACOSX_RPATH)
37    set(CMAKE_MACOSX_RPATH FALSE)
38endif()
39if(POLICY CMP0042)
40    cmake_policy(SET CMP0042 NEW)
41endif()
42
43#
44# Squelch noise about quoted strings in if() statements.
45# WE KNOW WHAT WE'RE DOING, WE'RE DOING EVERYTHING THE WAY THAT NEWER
46# VERSIONS OF CMAKE EXPECT BY DEFAULT, DON'T WASTE OUR TIME WITH NOISE.
47#
48if(POLICY CMP0054)
49    cmake_policy(SET CMP0054 NEW)
50endif()
51
52#
53# We want find_file() and find_library() to honor {packagename}_ROOT,
54# as that appears to be the only way, with the Visual Studio 2019 IDE
55# and its CMake support, to tell CMake where to look for the Npcap
56# or WinPcap SDK.
57#
58if(POLICY CMP0074)
59    cmake_policy(SET CMP0074 NEW)
60endif()
61
62#
63# We want check_include_file() to honor CMAKE_REQUIRED_LIBRARIES; see
64# the big comment before the check_include_file() test for
65# infiniband/verbs.h for the reason.
66#
67if(POLICY CMP0075)
68    cmake_policy(SET CMP0075 NEW)
69endif()
70
71set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules)
72
73#
74# We explicitly indicate what languages are used in libpcap to avoid
75# checking for a C++ compiler.
76#
77# One reason to avoid that check is that there's no need to waste
78# configuration time performing it.
79#
80# Another reason is that:
81#
82# CMake will try to determine the sizes of some data types, including
83# void *, early in the process of configuration; apparently, it's done
84# as part of processing the project() command.
85#
86# At least as of CMake 2.8.6, it does so by checking the size of
87# "void *" in C, setting CMAKE_C_SIZEOF_DATA_PTR based on that,
88# setting CMAKE_SIZEOF_VOID_P to that, and then checking the size
89# of "void *" in C++, setting CMAKE_CXX_SIZEOF_DATA_PTR based on
90# that, and then setting CMAKE_SIZEOF_VOID_P to *that*.
91#
92# The compile tests include whatever C flags may have been provided
93# to CMake in the CFLAGS and CXXFLAGS environment variables.
94#
95# If you set an architecture flag such as -m32 or -m64 in CFLAGS
96# but *not* in CXXFLAGS, the size for C++ will win, and hilarity
97# will ensue.
98#
99# Or if, at least on Solaris, you have a newer version of GCC
100# installed, but *not* a newer version of G++, and you have Oracle
101# Studio installed, it will find GCC, which will default to building
102# 64-bit, and Oracle Studio's C++ compiler, which will default to
103# building 32-bit, the size for C++ will win, and, again, hilarity
104# will ensue.
105#
106project(pcap C)
107
108#
109# Setting CMAKE_MACOSX_RPATH to FALSE causes the installed
110# libpcap.A.dylib to have just libpcap.A.dylib as the install
111# name;  Apple built libpcap with an install_name of /usr/lib/libpcap.A.dylib
112# (back when they still shipped individual system dylibs rather than
113# shipping a pre-built shared library cache, at least), and we do the
114# same with autotools; do the same with CMake.
115#
116if (NOT DEFINED CMAKE_INSTALL_NAME_DIR)
117    set(CMAKE_INSTALL_NAME_DIR ${CMAKE_INSTALL_PREFIX}/lib)
118endif()
119
120#
121# For getting raw lists of --libs and --libs --static information from a
122# pkg-config module.
123#
124# In CMake up to 2.8.12, pkg_check_modules() sets:
125#
126#    <XPREFIX>_LIBRARIES, which is a list of library names to which, on
127#      a UN*X, -l can be prefixed - i.e., names, without extensions,
128#      rather than full paths to the file.
129#    <XPREFIX>_LIBRARY_DIRS, which is a list of paths to directories
130#      containing the libraries, to which, on a UN*X, -L can be
131#      prefixed.
132#    <XPREFIX>_LDFLAGS, which is a list of *all* required linker flags
133#    <XPREFIX>_LDFLAGS_OTHER, which is a list of all linker flags other
134#      than -l and -L flags
135#
136# In 3.0 (at least as of 3.0.2), it also sets:
137#
138#    <XPREFIX>_LINK_LIBRARIES, which is a list of full paths to the
139#      library files.
140#
141# but if <XPREFIX> is <PREFIX>_STATIC, <XPREFIX>_LINK_LIBRARIES is
142# currently not set by CMake.
143#
144# Unfortunately, pkg_check_modules() sets the
145# PKG_CONFIG_ALLOW_SYSTEM_LIBS environment variable when running
146# pkg-config, so the output of --libs, etc. may include a -L for the
147# system library, which we do *NOT* want to put in our libpcap.pc and
148# pcap-config files.
149#
150# So we just run pkg-config ourselves, so that we get its output
151# directly without any processing by CMake.
152#
153macro(pkg_get_link_info _prefix _package)
154  if (PKG_CONFIG_EXECUTABLE)
155    #
156    # Get the --libs information.
157    #
158    # We force PKG_CONFIG_ALLOW_SYSTEM_LIBS to be undefined, as
159    # at least some versions of CMake appear to define it in
160    # pkg_check_modules() before running pkg-config and *not* undefine
161    # it after running it.
162    #
163    unset(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS})
164    set(_pkg_config_result "")
165    execute_process(
166      COMMAND ${PKG_CONFIG_EXECUTABLE} "--libs" ${_package}
167      OUTPUT_VARIABLE _pkg_config_result
168      RESULT_VARIABLE _pkg_config_failed
169      OUTPUT_STRIP_TRAILING_WHITESPACE)
170
171    if (_pkg_config_failed)
172      #
173      # pkg-config failed; assume that means that there is no such
174      # package for it to find.  XXX - what do we do here?
175      #
176      set(${_prefix}_FOUND_WITH_PKG_CONFIG FALSE)
177    else()
178      #
179      # pkg-config succeeded; replace CR and LF with spaces.
180      #
181      string(REGEX REPLACE "[\r\n]" " " ${_prefix}_LIBS "${_pkg_config_result}")
182
183      #
184      # Now get the --libs --static information.
185      #
186      set(_pkg_config_result "")
187      execute_process(
188        COMMAND ${PKG_CONFIG_EXECUTABLE} "--libs" "--static" ${_package}
189        OUTPUT_VARIABLE _pkg_config_result
190        RESULT_VARIABLE _pkg_config_failed
191        OUTPUT_STRIP_TRAILING_WHITESPACE)
192
193      if (_pkg_config_failed)
194        #
195        # pkg-config failed; assume that means that there is no such
196        # package for it to find.  XXX - what do we do here?
197        #
198        set(${_prefix}_FOUND_WITH_PKG_CONFIG FALSE)
199      else()
200        #
201        # pkg-config succeeded; replace CR and LF with spaces.
202        #
203        string(REGEX REPLACE "[\r\n]" " " ${_prefix}_LIBS_STATIC "${_pkg_config_result}")
204
205        #
206        # List this package in its PACKAGE_NAME variable.
207        #
208        set(${_prefix}_PACKAGE_NAME "${_package}")
209
210        #
211        # It worked.
212        #
213        set(${_prefix}_FOUND_WITH_PKG_CONFIG TRUE)
214      endif()
215    endif()
216  endif()
217endmacro()
218
219macro(get_link_info_from_library_path  _library_prefix _library_name)
220  if(NOT ${_library_prefix}_LIBRARY STREQUAL "${_library_prefix}_LIBRARY-NOTFOUND")
221    get_filename_component(_lib_directory "${${_library_prefix}_LIBRARY}}" DIRECTORY)
222
223    #
224    # The closest thing to a list of "system library directories" in
225    # which the linker will, by default, search for libraries appears to
226    # be CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES, so that's what we use
227    # when we're trying to construct a -L argument, for insertion into
228    # pcap-config and libpcap.pc, for a library upon which we depend.
229    #
230    # In some versions of CMake it appears to have duplicate entries,
231    # but that shouldn't affect a search for a directory in that list.
232    #
233    list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${_lib_directory}" _lib_index)
234    if(_lib_index EQUAL -1)
235      #
236      # No, so add a -L flag to get the linker to search in that
237      # directory.
238      #
239      set(${_library_prefix}_LIBS "-L${_lib_directory}")
240      set(${_library_prefix}_LIBS_STATIC "-L${_lib_directory}")
241      set(${_libraryprefix}_LIBS_PRIVATE "-L${_lib_directory}")
242    endif()
243    set(${_library_prefix}_LIBS "${${_library_prefix}_LIBS} -l${_library_name}")
244    set(${_library_prefix}_LIBS_STATIC "${${_library_prefix}_LIBS} -l${_library_name}")
245    set(${_library_prefix}_LIBS_PRIVATE "${${_library_prefix}_LIBS} -l${_library_name}")
246  endif()
247endmacro()
248
249#
250# Show the bit width for which we're compiling.
251# This can help debug problems if you're dealing with a compiler that
252# defaults to generating 32-bit code even when running on a 64-bit
253# platform, and where that platform may provide only 64-bit versions of
254# libraries that we might use (looking at *you*, Oracle Studio!).
255#
256if(CMAKE_SIZEOF_VOID_P EQUAL 4)
257  message(STATUS "Building 32-bit")
258elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
259  message(STATUS "Building 64-bit")
260endif()
261
262#
263# Solaris pkg-config is annoying.  For at least one package (D-Bus, I'm
264# looking at *you*!), there are separate include files for 32-bit and
265# 64-bit builds (I guess using "unsigned long long" as a 64-bit integer
266# type on a 64-bit build is like crossing the beams or something), and
267# there are two separate .pc files, so if we're doing a 32-bit build we
268# should make sure we look in /usr/lib/pkgconfig for .pc files and if
269# we're doing a 64-bit build we should make sure we look in
270# /usr/lib/amd64/pkgconfig for .pc files.
271#
272if(CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND CMAKE_SYSTEM_VERSION MATCHES "5[.][0-9.]*")
273    #
274    # Note: string(REPLACE) does not appear to support using ENV{...}
275    # as an argument, so we set a variable and then use set() to set
276    # the environment variable.
277    #
278    if(CMAKE_SIZEOF_VOID_P EQUAL 8)
279        #
280        # 64-bit build.  If /usr/lib/pkgconfig appears in the path,
281        # prepend /usr/lib/amd64/pkgconfig to it; otherwise,
282        # put /usr/lib/amd64 at the end.
283        #
284        if((NOT DEFINED ENV{PKG_CONFIG_PATH}) OR "$ENV{PKG_CONFIG_PATH}" EQUAL "")
285            #
286            # Not set, or empty.  Set it to /usr/lib/amd64/pkgconfig.
287            #
288            set(fixed_path "/usr/lib/amd64/pkgconfig")
289        elseif("$ENV{PKG_CONFIG_PATH}" MATCHES "/usr/lib/pkgconfig")
290            #
291            # It contains /usr/lib/pkgconfig.  Prepend
292            # /usr/lib/amd64/pkgconfig to /usr/lib/pkgconfig.
293            #
294            string(REPLACE "/usr/lib/pkgconfig"
295                "/usr/lib/amd64/pkgconfig:/usr/lib/pkgconfig"
296                fixed_path "$ENV{PKG_CONFIG_PATH}")
297        else()
298            #
299            # Not empty, but doesn't contain /usr/lib/pkgconfig.
300            # Append /usr/lib/amd64/pkgconfig to it.
301            #
302            set(fixed_path "$ENV{PKG_CONFIG_PATH}:/usr/lib/amd64/pkgconfig")
303        endif()
304        set(ENV{PKG_CONFIG_PATH} "${fixed_path}")
305    elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
306        #
307        # 32-bit build.  If /usr/amd64/lib/pkgconfig appears in the path,
308        # prepend /usr/lib/pkgconfig to it.
309        #
310        if("$ENV{PKG_CONFIG_PATH}" MATCHES "/usr/lib/amd64/pkgconfig")
311            #
312            # It contains /usr/lib/amd64/pkgconfig.  Prepend
313            # /usr/lib/pkgconfig to /usr/lib/amd64/pkgconfig.
314            #
315            string(REPLACE "/usr/lib/amd64/pkgconfig"
316                "/usr/lib/pkgconfig:/usr/lib/amd64/pkgconfig"
317                fixed_path "$ENV{PKG_CONFIG_PATH}")
318            set(ENV{PKG_CONFIG_PATH} "${fixed_path}")
319        endif()
320    endif()
321endif()
322
323include(CheckCCompilerFlag)
324
325#
326# For checking if a compiler flag works and adding it if it does.
327#
328macro(check_and_add_compiler_option _option)
329    message(STATUS "Checking C compiler flag ${_option}")
330    string(REPLACE "=" "-" _temp_option_variable ${_option})
331    string(REGEX REPLACE "^-" "" _option_variable ${_temp_option_variable})
332    check_c_compiler_flag("${_option}" ${_option_variable})
333    if(${${_option_variable}})
334        set(C_ADDITIONAL_FLAGS "${C_ADDITIONAL_FLAGS} ${_option}")
335    endif()
336endmacro()
337
338#
339# If we're building with Visual Studio, we require Visual Studio 2015,
340# in order to get sufficient C99 compatibility.  Check for that.
341#
342# If not, try the appropriate flag for the compiler to enable C99
343# features.
344#
345set(C_ADDITIONAL_FLAGS "")
346if(MSVC)
347    if(MSVC_VERSION LESS 1900)
348        message(FATAL_ERROR "Visual Studio 2015 or later is required")
349    endif()
350
351    #
352    # Treat source files as being in UTF-8 with MSVC if it's not using
353    # the Clang front end.
354    # We assume that UTF-8 source is OK with other compilers and with
355    # MSVC if it's using the Clang front end.
356    #
357    if(NOT ${CMAKE_C_COMPILER} MATCHES "clang*")
358        set(C_ADDITIONAL_FLAGS "${C_ADDITIONAL_FLAGS} /utf-8")
359    endif(NOT ${CMAKE_C_COMPILER} MATCHES "clang*")
360else(MSVC)
361    #
362    # For checking if a compiler flag works, failing if it doesn't,
363    # and adding it otherwise.
364    #
365    macro(require_and_add_compiler_option _option)
366        message(STATUS "Checking C compiler flag ${_option}")
367        string(REPLACE "=" "-" _temp_option_variable ${_option})
368        string(REGEX REPLACE "^-" "" _option_variable ${_temp_option_variable})
369        check_c_compiler_flag("${_option}" ${_option_variable})
370        if(${${_option_variable}})
371            set(C_ADDITIONAL_FLAGS "${C_ADDITIONAL_FLAGS} ${_option}")
372        else()
373            message(FATAL_ERROR "C99 support is required, but the compiler doesn't support a compiler flag to enable it")
374        endif()
375    endmacro()
376
377    #
378    # Try to enable as many C99 features as we can.
379    # At minimum, we want C++/C99-style // comments.
380    #
381    # Newer versions of compilers might default to supporting C99, but
382    # older versions may require a special flag.
383    #
384    # Prior to CMake 3.1, setting CMAKE_C_STANDARD will not have any effect,
385    # so, unless and until we require CMake 3.1 or later, we have to do it
386    # ourselves on pre-3.1 CMake, so we just do it ourselves on all versions
387    # of CMake.
388    #
389    # Note: with CMake 3.1 through 3.5, the only compilers for which CMake
390    # handles CMAKE_C_STANDARD are GCC and Clang.  3.6 adds support only
391    # for Intel C; 3.9 adds support for PGI C, Sun C, and IBM XL C, and
392    # 3.10 adds support for Cray C and IAR C, but no version of CMake has
393    # support for HP C.  Therefore, even if we use CMAKE_C_STANDARD with
394    # compilers for which CMake supports it, we may still have to do it
395    # ourselves on other compilers.
396    #
397    # See the CMake documentation for the CMAKE_<LANG>_COMPILER_ID variables
398    # for a list of compiler IDs.
399    #
400    # XXX - this just tests whether the option works, fails if it doesn't,
401    # and adds it if it does.  We don't test whether it's necessary in order
402    # to get the C99 features that we use, or whether, if it's used, it
403    # enables all the features that we require.
404    #
405    if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR
406       CMAKE_C_COMPILER_ID MATCHES "Clang")
407        require_and_add_compiler_option("-std=gnu99")
408    elseif(CMAKE_C_COMPILER_ID MATCHES "XL")
409        #
410        # We want support for extensions picked up for GNU C compatibility,
411        # so we use -qlanglvl=extc99.
412        #
413        require_and_add_compiler_option("-qlanglvl=extc99")
414    elseif(CMAKE_C_COMPILER_ID MATCHES "HP")
415        require_and_add_compiler_option("-AC99")
416    elseif(CMAKE_C_COMPILER_ID MATCHES "Sun")
417        require_and_add_compiler_option("-xc99")
418    elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
419        require_and_add_compiler_option("-c99")
420    endif()
421endif(MSVC)
422
423#
424# If we're building with MinGW, we need to specify _WIN32_WINNT as
425# 0x0600 ("NT 6.0", a/k/a Vista/Windows Server 2008) or higher
426# in order to get the full IPv6 API, including inet_ntop(), and we
427# need to specify it as 0x0601 ("NT 6.1", a/k/a Windows 7) or higher
428# in order to get NdisMediumIP.
429#
430# NOTE: pcap does *NOT* work with msvcrt.dll; it must link with
431# a newer version of the C library, i.e. Visual Studio 2015 or
432# later, as it depends on C99 features introduced in VS 2015.
433#
434if(MINGW)
435    add_definitions(-D_WIN32_WINNT=0x0601)
436endif(MINGW)
437
438#
439# Build all runtimes in the top-level binary directory; that way,
440# on Windows, the executables will be in the same directory as
441# the DLLs, so the system will find pcap.dll when any of the
442# executables are run.
443#
444set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/run)
445
446###################################################################
447#   Parameters
448###################################################################
449
450if(WIN32)
451    #
452    # On Windows, allow the library name to be overridden, for the
453    # benefit of projects that combine libpcap with their own
454    # kernel-mode code to support capturing.
455    #
456    set(LIBRARY_NAME pcap CACHE STRING "Library name")
457else()
458    #
459    # On UN*X, it's always been libpcap.
460    #
461    set(LIBRARY_NAME pcap)
462endif()
463
464option(INET6 "Enable IPv6" ON)
465if(WIN32)
466    option(USE_STATIC_RT "Use static Runtime" ON)
467endif(WIN32)
468option(BUILD_SHARED_LIBS "Build shared libraries" ON)
469set(dpdk_ROOT "" CACHE PATH "Path to directory with include and lib subdirectories for DPDK")
470if(WIN32)
471    set(Packet_ROOT "" CACHE PATH "Path to directory with include and lib subdirectories for packet.dll")
472    set(AirPcap_ROOT "" CACHE PATH "Path to directory with include and lib subdirectories for airpcap.dll")
473endif(WIN32)
474
475option(ENABLE_PROFILING "Enable code profiling" OFF)
476
477# To pacify those who hate the protochain instruction
478option(NO_PROTOCHAIN "Disable protochain instruction" OFF)
479
480#
481# Start out with the capture mechanism type unspecified; the user
482# can explicitly specify it and, if they don't, we'll pick an
483# appropriate one.
484#
485set(PCAP_TYPE "" CACHE STRING "Packet capture type")
486
487#
488# Default to having remote capture support on Windows and, for now, to
489# not having it on UN*X.
490#
491if(WIN32)
492    option(ENABLE_REMOTE "Enable remote capture" ON)
493else()
494    option(ENABLE_REMOTE "Enable remote capture" OFF)
495endif(WIN32)
496
497if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
498    option(BUILD_WITH_LIBNL "Build with libnl" ON)
499endif()
500
501#
502# Additional capture modules.
503#
504if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
505    option(DISABLE_LINUX_USBMON "Disable Linux usbmon USB sniffing support" OFF)
506endif()
507option(DISABLE_BLUETOOTH "Disable Bluetooth sniffing support" OFF)
508option(DISABLE_NETMAP "Disable netmap support" OFF)
509option(DISABLE_DPDK "Disable DPDK support" OFF)
510
511#
512# We don't support D-Bus sniffing on macOS; see
513#
514# https://bugs.freedesktop.org/show_bug.cgi?id=74029
515#
516if(APPLE)
517    option(DISABLE_DBUS "Disable D-Bus sniffing support" ON)
518else(APPLE)
519    option(DISABLE_DBUS "Disable D-Bus sniffing support" OFF)
520endif(APPLE)
521option(DISABLE_RDMA "Disable RDMA sniffing support" OFF)
522
523option(DISABLE_DAG "Disable Endace DAG card support" OFF)
524
525option(DISABLE_SEPTEL "Disable Septel card support" OFF)
526set(SEPTEL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../septel" CACHE PATH "Path to directory with include and lib subdirectories for Septel API")
527
528option(DISABLE_SNF "Disable Myricom SNF support" OFF)
529
530option(DISABLE_TC "Disable Riverbed TurboCap support" OFF)
531
532#
533# Debugging options.
534#
535option(BDEBUG "Build optimizer debugging code" OFF)
536option(YYDEBUG "Build parser debugging code" OFF)
537
538###################################################################
539#   Versioning
540###################################################################
541
542# Get, parse, format and set pcap's version string from [pcap_root]/VERSION
543# for later use.
544
545# Get MAJOR, MINOR, PATCH & SUFFIX
546file(STRINGS ${pcap_SOURCE_DIR}/VERSION
547    PACKAGE_VERSION
548    LIMIT_COUNT 1 # Read only the first line
549)
550
551# Get "just" MAJOR
552string(REGEX MATCH "^([0-9]+)" PACKAGE_VERSION_MAJOR "${PACKAGE_VERSION}")
553
554# Get MAJOR, MINOR & PATCH
555string(REGEX MATCH "^([0-9]+.)?([0-9]+.)?([0-9]+)" PACKAGE_VERSION_NOSUFFIX "${PACKAGE_VERSION}")
556
557if(WIN32)
558    # Convert PCAP_VERSION_NOSUFFIX to Windows preferred version format
559    string(REPLACE "." "," PACKAGE_VERSION_PREDLL ${PACKAGE_VERSION_NOSUFFIX})
560
561    # Append NANO (used for Windows internal versioning) to PCAP_VERSION_PREDLL
562    # 0 means unused.
563    set(PACKAGE_VERSION_DLL ${PACKAGE_VERSION_PREDLL},0)
564endif(WIN32)
565
566set(PACKAGE_NAME "${LIBRARY_NAME}")
567set(PACKAGE_STRING "${LIBRARY_NAME} ${PACKAGE_VERSION}")
568
569######################################
570# Project settings
571######################################
572
573include_directories(
574    ${CMAKE_CURRENT_BINARY_DIR}
575    ${pcap_SOURCE_DIR}
576)
577
578include(CheckFunctionExists)
579include(CMakePushCheckState)
580include(CheckSymbolExists)
581
582if(WIN32)
583
584    if(IS_DIRECTORY ${CMAKE_HOME_DIRECTORY}/../../Common)
585        include_directories(${CMAKE_HOME_DIRECTORY}/../../Common)
586    endif(IS_DIRECTORY ${CMAKE_HOME_DIRECTORY}/../../Common)
587
588    find_package(Packet)
589    if(Packet_FOUND)
590        set(HAVE_PACKET32 TRUE)
591        include_directories(${Packet_INCLUDE_DIRS})
592        #
593        # Check whether we have the NPcap PacketIsLoopbackAdapter()
594        # function.
595        #
596        cmake_push_check_state()
597        set(CMAKE_REQUIRED_LIBRARIES ${Packet_LIBRARIES})
598        check_function_exists(PacketIsLoopbackAdapter HAVE_PACKET_IS_LOOPBACK_ADAPTER)
599        check_function_exists(PacketGetTimestampModes HAVE_PACKET_GET_TIMESTAMP_MODES)
600        cmake_pop_check_state()
601    endif(Packet_FOUND)
602
603    message(STATUS "checking for Npcap's version.h")
604    check_symbol_exists(WINPCAP_PRODUCT_NAME "${CMAKE_SOURCE_DIR}/../../version.h" HAVE_VERSION_H)
605    if(HAVE_VERSION_H)
606        message(STATUS "HAVE version.h")
607    else(HAVE_VERSION_H)
608        message(STATUS "MISSING version.h")
609    endif(HAVE_VERSION_H)
610
611endif(WIN32)
612
613if(MSVC)
614    add_definitions(-D__STDC__)
615    add_definitions(-D_CRT_SECURE_NO_WARNINGS)
616endif(MSVC)
617
618if(USE_STATIC_RT)
619    message(STATUS "Use STATIC runtime")
620        if(MSVC)
621            foreach(RT_FLAG
622                CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
623                CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
624                string(REGEX REPLACE "/MD" "/MT" ${RT_FLAG} "${${RT_FLAG}}")
625            endforeach(RT_FLAG)
626        elseif(MINGW)
627            set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libgcc")
628        endif()
629else (USE_STATIC_RT)
630    message(STATUS "Use DYNAMIC runtime")
631endif(USE_STATIC_RT)
632
633###################################################################
634#   Detect available platform features
635###################################################################
636
637include(CheckIncludeFile)
638include(CheckIncludeFiles)
639include(CheckStructHasMember)
640include(CheckTypeSize)
641
642#
643# Tests are a bit expensive with Visual Studio on Windows, so, on
644# Windows, we skip tests for UN*X-only headers and functions.
645#
646
647#
648# Header files.
649#
650check_include_file(inttypes.h HAVE_INTTYPES_H)
651check_include_file(stdint.h HAVE_STDINT_H)
652check_include_file(unistd.h HAVE_UNISTD_H)
653if(NOT HAVE_UNISTD_H)
654    add_definitions(-DYY_NO_UNISTD_H)
655endif(NOT HAVE_UNISTD_H)
656check_include_file(bitypes.h HAVE_SYS_BITYPES_H)
657if(NOT WIN32)
658    check_include_file(sys/ioccom.h HAVE_SYS_IOCCOM_H)
659    check_include_file(sys/sockio.h HAVE_SYS_SOCKIO_H)
660    check_include_file(sys/select.h HAVE_SYS_SELECT_H)
661
662    check_include_file(netpacket/packet.h HAVE_NETPACKET_PACKET_H)
663    check_include_file(netinet/if_ether.h HAVE_NETINET_IF_ETHER_H)
664endif(NOT WIN32)
665
666#
667# Functions.
668#
669# First, check for the __atomic_load_n() and __atomic_store_n()
670# builtins.
671#
672# We can't use check_function_exists(), as it tries to declare
673# the function, and attempting to declare a compiler builtin
674# can produce an error.
675#
676# We don't use check_symbol_exists(), as it expects a header
677# file to be specified to declare the function, but there isn't
678# such a header file.
679#
680# So we use check_c_source_compiles().
681#
682check_c_source_compiles(
683"int
684main(void)
685{
686	int i = 17;
687	return __atomic_load_n(&i, __ATOMIC_RELAXED);
688}
689"
690            HAVE___ATOMIC_LOAD_N)
691check_c_source_compiles(
692"int
693main(void)
694{
695	int i;
696	__atomic_store_n(&i, 17, __ATOMIC_RELAXED);
697	return 0;
698}
699"
700            HAVE___ATOMIC_STORE_N)
701
702#
703# Now check for various system functions.
704#
705check_function_exists(strerror_r HAVE_STRERROR_R)
706if(HAVE_STRERROR_R)
707    #
708    # We have strerror_r; if we define _GNU_SOURCE, is it a
709    # POSIX-compliant strerror_r() or a GNU strerror_r()?
710    #
711    check_c_source_compiles(
712"#define _GNU_SOURCE
713#include <string.h>
714
715/* Define it GNU-style; that will cause an error if it's not GNU-style */
716extern char *strerror_r(int, char *, size_t);
717
718int
719main(void)
720{
721	return 0;
722}
723"
724            HAVE_GNU_STRERROR_R)
725    if(NOT HAVE_GNU_STRERROR_R)
726        set(HAVE_POSIX_STRERROR_R YES)
727    endif(NOT HAVE_GNU_STRERROR_R)
728else(HAVE_STRERROR_R)
729    #
730    # We don't have strerror_r; do we have _wcserror_s?
731    #
732    check_function_exists(_wcserror_s HAVE__WCSERROR_S)
733endif(HAVE_STRERROR_R)
734
735#
736# Make sure we have vsnprintf() and snprintf(); we require them.
737# We use check_symbol_exists(), as they aren't necessarily external
738# functions - in Visual Studio, for example, they're inline functions
739# calling a common external function.
740#
741check_symbol_exists(vsnprintf "stdio.h" HAVE_VSNPRINTF)
742if(NOT HAVE_VSNPRINTF)
743    message(FATAL_ERROR "vsnprintf() is required but wasn't found")
744endif(NOT HAVE_VSNPRINTF)
745check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
746if(NOT HAVE_SNPRINTF)
747    message(FATAL_ERROR "snprintf() is required but wasn't found")
748endif()
749
750check_function_exists(strlcpy HAVE_STRLCPY)
751check_function_exists(strlcat HAVE_STRLCAT)
752check_function_exists(asprintf HAVE_ASPRINTF)
753check_function_exists(vasprintf HAVE_VASPRINTF)
754check_function_exists(strtok_r HAVE_STRTOK_R)
755if(NOT WIN32)
756    check_function_exists(vsyslog HAVE_VSYSLOG)
757endif()
758
759#
760# Look for various networking-related libraries that we may need.
761#
762# We need getaddrinfo() to translate host names in filters to IP
763# addresses. We use getaddrinfo() because we want a portable
764# thread-safe way of getting information for a host name or port;
765# there exist _r versions of gethostbyname() and getservbyname() on
766# some platforms, but not on all platforms.
767#
768# We may also need socket() and other socket functions to support:
769#
770#   Local packet capture with capture mechanisms that use sockets.
771#
772#   Local capture device enumeration if a socket call is needed to
773#   enumerate devices or get device attributes.
774#
775#   Packet capture from services that put captured packets on the
776#   network, such as rpcap servers.
777#
778# We may also need getnameinfo() for packet capture from services
779# that put packets on the network.
780#
781set(PCAP_LINK_LIBRARIES "")
782set(LIBS "")
783set(LIBS_STATIC "")
784set(REQUIRES_PRIVATE "")
785set(LIBS_PRIVATE "")
786include(CheckLibraryExists)
787if(WIN32)
788    #
789    # Windows.
790    #
791    # We need winsock2.h and ws2tcpip.h.
792    #
793    # On Windows, getaddrinfo() is in the ws2_32 library.
794    #
795    cmake_push_check_state()
796    set(CMAKE_REQUIRED_LIBRARIES ws2_32)
797    check_symbol_exists(getaddrinfo "winsock2.h;ws2tcpip.h" LIBWS2_32_HAS_GETADDRINFO)
798    cmake_pop_check_state()
799    if(LIBWS2_32_HAS_GETADDRINFO)
800        set(PCAP_LINK_LIBRARIES ws2_32 ${PCAP_LINK_LIBRARIES})
801    else(LIBWS2_32_HAS_GETADDRINFO)
802        message(FATAL_ERROR "getaddrinfo is required, but wasn't found")
803    endif(LIBWS2_32_HAS_GETADDRINFO)
804else(WIN32)
805    #
806    # UN*X.
807    #
808    # Most UN*Xes have getaddrinfo(), and the other routines we may
809    # need, in the default searched libraries (e.g., libc).
810    # Check there first.
811    #
812    # NOTE: if you hand check_library_exists as its last argument a
813    # variable that's been set, it skips the test, so we need different
814    # variables for different libraries.
815    #
816    check_function_exists(getaddrinfo STDLIBS_HAVE_GETADDRINFO)
817    if(NOT STDLIBS_HAVE_GETADDRINFO)
818	#
819	# Not found in the standard system libraries.
820	#
821	# In some versions of Solaris, we need to link with libsocket
822	# and libnsl, so check in libsocket and also link with liblnsl
823	# when doing this test.
824	#
825	# Linking with libsocket and libnsl will find all the routines
826	# we need.
827	#
828        cmake_push_check_state()
829        set(CMAKE_REQUIRED_LIBRARIES nsl)
830        check_library_exists(socket getaddrinfo "" LIBSOCKET_HAS_GETADDRINFO)
831        cmake_pop_check_state()
832        if(LIBSOCKET_HAS_GETADDRINFO)
833            #
834            # OK, we found it in libsocket.
835            #
836            set(PCAP_LINK_LIBRARIES socket nsl ${PCAP_LINK_LIBRARIES})
837            set(LIBS "-lsocket -lnsl ${LIBS}")
838            set(LIBS_STATIC "-lsocket -lnsl ${LIBS_STATIC}")
839            set(LIBS_PRIVATE "-lsocket -lnsl ${LIBS_PRIVATE}")
840        else(LIBSOCKET_HAS_GETADDRINFO)
841	    #
842	    # Not found in libsocket; test for it in libnetwork, which
843	    # is where it is in Haiku.
844	    #
845	    # Linking with libnetwork will find all the routines we
846	    # need.
847	    #
848            check_library_exists(network getaddrinfo "" LIBNETWORK_HAS_GETADDRINFO)
849            if(LIBNETWORK_HAS_GETADDRINFO)
850                #
851		# OK, we found it in libnetwork.
852                #
853                set(PCAP_LINK_LIBRARIES network ${PCAP_LINK_LIBRARIES})
854                set(LIBS "-lnetwork ${LIBS}")
855                set(LIBS_STATIC "-lnetwork ${LIBS_STATIC}")
856                set(LIBS_PRIVATE "-lnetwork ${LIBS_PRIVATE}")
857            else(LIBNETWORK_HAS_GETADDRINFO)
858                #
859                # We didn't find it.
860                #
861                message(FATAL_ERROR "getaddrinfo is required, but wasn't found")
862            endif(LIBNETWORK_HAS_GETADDRINFO)
863        endif(LIBSOCKET_HAS_GETADDRINFO)
864
865	#
866	# We require a version of recvmsg() that conforms to the Single
867	# UNIX Specification, so that we can check whether a datagram
868	# received with recvmsg() was truncated when received due to the
869	# buffer being too small.
870	#
871	# On most systems, the version of recvmsg() in the libraries
872	# found above conforms to the SUS.
873	#
874	# On at least some versions of Solaris, it does not conform to
875	# the SUS, and we need the version in libxnet, which does
876	# conform.
877	#
878	# Check whether libxnet exists and has a version of recvmsg();
879	# if it does, link with libxnet before we link with libsocket,
880	# to get that version.
881	#
882	# This test also links with libsocket and libnsl.
883	#
884        cmake_push_check_state()
885        set(CMAKE_REQUIRED_LIBRARIES socket nsl)
886        check_library_exists(xnet recvmsg "" LIBXNET_HAS_RECVMSG)
887        cmake_pop_check_state()
888        if(LIBXNET_HAS_RECVMSG)
889            #
890	    # libxnet has recvmsg(); link with it as well.
891            #
892            set(PCAP_LINK_LIBRARIES xnet ${PCAP_LINK_LIBRARIES})
893            set(LIBSC "-lxnet ${LIBS_LIBS}")
894            set(LIBS_STATIC "-lxnet ${LIBS_STATIC}")
895            set(LIBS_PRIVATE "-lxnet ${LIBS_PRIVATE}")
896        endif(LIBXNET_HAS_RECVMSG)
897    endif(NOT STDLIBS_HAVE_GETADDRINFO)
898
899    #
900    # DLPI needs putmsg under HP-UX, so test for -lstr while we're at it.
901    #
902    check_function_exists(putmsg STDLIBS_HAVE_PUTMSG)
903    if(NOT STDLIBS_HAVE_PUTMSG)
904        check_library_exists(str putmsg "" LIBSTR_HAS_PUTMSG)
905        if(LIBSTR_HAS_PUTMSG)
906            set(PCAP_LINK_LIBRARIES str ${PCAP_LINK_LIBRARIES})
907            set(LIBS "-lstr ${LIBS}")
908            set(LIBS_STATIC "-lstr ${LIBS_STATIC}")
909            set(LIBS_PRIVATE "-lstr ${LIBS_PRIVATE}")
910        endif(LIBSTR_HAS_PUTMSG)
911    endif(NOT STDLIBS_HAVE_PUTMSG)
912
913    # Haiku has getpass in libbsd
914    check_function_exists(getpass STDLIBS_HAVE_GETPASS)
915    if(NOT STDLIBS_HAVE_GETPASS)
916        check_library_exists(bsd getpass "" LIBBSD_HAS_GETPASS)
917        if(LIBBSD_HAS_GETPASS)
918            set(PCAP_LINK_LIBRARIES bsd ${PCAP_LINK_LIBRARIES})
919        endif(LIBBSD_HAS_GETPASS)
920    endif(NOT STDLIBS_HAVE_GETPASS)
921endif(WIN32)
922
923#
924# Check for reentrant versions of getnetbyname_r(), as provided by
925# Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
926# If we don't find one, we just use getnetbyname(), which uses
927# thread-specific data on many platforms, but doesn't use it on
928# NetBSD or OpenBSD, and may not use it on older versions of other
929# platforms.
930#
931# Only do the check if we have a declaration of getnetbyname_r();
932# without it, we can't check which API it has.  (We assume that
933# if there's a declaration, it has a prototype, so that the API
934# can be checked.)
935#
936cmake_push_check_state()
937set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LINK_LIBRARIES})
938check_symbol_exists(getnetbyname_r netdb.h NETDB_H_DECLARES_GETNETBYNAME_R)
939if(NETDB_H_DECLARES_GETNETBYNAME_R)
940    check_c_source_compiles(
941"#include <netdb.h>
942
943int
944main(void)
945{
946    struct netent netent_buf;
947    char buf[1024];
948    struct netent *resultp;
949    int h_errnoval;
950
951    return getnetbyname_r((const char *)0, &netent_buf, buf, sizeof buf, &resultp, &h_errnoval);
952}
953"
954        HAVE_LINUX_GETNETBYNAME_R)
955    if(NOT HAVE_LINUX_GETNETBYNAME_R)
956        check_c_source_compiles(
957"#include <netdb.h>
958
959int
960main(void)
961{
962    struct netent netent_buf;
963    char buf[1024];
964
965    return getnetbyname_r((const char *)0, &netent_buf, buf, (int)sizeof buf) != NULL;
966}
967"
968            HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
969        if(NOT HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
970            check_c_source_compiles(
971"#include <netdb.h>
972
973int
974main(void)
975{
976    struct netent netent_buf;
977    struct netent_data net_data;
978
979    return getnetbyname_r((const char *)0, &netent_buf, &net_data);
980}
981"
982                HAVE_AIX_GETNETBYNAME_R)
983        endif(NOT HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
984    endif(NOT HAVE_LINUX_GETNETBYNAME_R)
985endif(NETDB_H_DECLARES_GETNETBYNAME_R)
986cmake_pop_check_state()
987
988#
989# Check for reentrant versions of getprotobyname_r(), as provided by
990# Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
991# If we don't find one, we just use getprotobyname(), which uses
992# thread-specific data on many platforms, but doesn't use it on
993# NetBSD or OpenBSD, and may not use it on older versions of other
994# platforms.
995#
996# Only do the check if we have a declaration of getprotobyname_r();
997# without it, we can't check which API it has.  (We assume that
998# if there's a declaration, it has a prototype, so that the API
999# can be checked.)
1000#
1001cmake_push_check_state()
1002set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LINK_LIBRARIES})
1003check_symbol_exists(getprotobyname_r netdb.h NETDB_H_DECLARES_GETPROTOBYNAME_R)
1004if(NETDB_H_DECLARES_GETPROTOBYNAME_R)
1005    check_c_source_compiles(
1006"#include <netdb.h>
1007
1008int
1009main(void)
1010{
1011    struct protoent protoent_buf;
1012    char buf[1024];
1013    struct protoent *resultp;
1014
1015    return getprotobyname_r((const char *)0, &protoent_buf, buf, sizeof buf, &resultp);
1016}
1017"
1018        HAVE_LINUX_GETPROTOBYNAME_R)
1019    if(NOT HAVE_LINUX_GETPROTOBYNAME_R)
1020        check_c_source_compiles(
1021"#include <netdb.h>
1022
1023int
1024main(void)
1025{
1026    struct protoent protoent_buf;
1027    char buf[1024];
1028
1029    return getprotobyname_r((const char *)0, &protoent_buf, buf, (int)sizeof buf) != NULL;
1030}
1031"
1032            HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R)
1033        if(NOT HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R)
1034            check_c_source_compiles(
1035"#include <netdb.h>
1036
1037int
1038main(void)
1039{
1040    struct protoent protoent_buf;
1041    struct protoent_data proto_data;
1042
1043    return getprotobyname_r((const char *)0, &protoent_buf, &proto_data);
1044}
1045"
1046                HAVE_AIX_GETPROTOBYNAME_R)
1047        endif(NOT HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R)
1048    endif(NOT HAVE_LINUX_GETPROTOBYNAME_R)
1049endif(NETDB_H_DECLARES_GETPROTOBYNAME_R)
1050cmake_pop_check_state()
1051
1052#
1053# Data types.
1054#
1055# XXX - there's no check_type() macro that's like check_type_size()
1056# except that it only checks for the existence of the structure type,
1057# so we use check_type_size() and ignore the size.
1058#
1059cmake_push_check_state()
1060if(WIN32)
1061    set(CMAKE_EXTRA_INCLUDE_FILES winsock2.h)
1062else(WIN32)
1063    set(CMAKE_EXTRA_INCLUDE_FILES unistd.h sys/socket.h)
1064endif(WIN32)
1065check_type_size("struct sockaddr_storage" STRUCT_SOCKADDR_STORAGE)
1066check_type_size("socklen_t" SOCKLEN_T)
1067cmake_pop_check_state()
1068
1069#
1070# Structure fields.
1071#
1072if(WIN32)
1073    check_struct_has_member("struct sockaddr" sa_len winsock2.h HAVE_STRUCT_SOCKADDR_SA_LEN)
1074else(WIN32)
1075    check_struct_has_member("struct sockaddr" sa_len sys/socket.h HAVE_STRUCT_SOCKADDR_SA_LEN)
1076endif(WIN32)
1077
1078#
1079# Do we have ffs(), and is it declared in <strings.h>?
1080#
1081check_function_exists(ffs HAVE_FFS)
1082if(HAVE_FFS)
1083    #
1084    # OK, we have ffs().  Is it declared in <strings.h>?
1085    #
1086    # This test fails if we don't have <strings.h> or if we do
1087    # but it doesn't declare ffs().
1088    #
1089    check_symbol_exists(ffs strings.h STRINGS_H_DECLARES_FFS)
1090endif()
1091
1092#
1093# This requires the libraries that we require, as ether_hostton might be
1094# in one of those libraries.  That means we have to do this after
1095# we check for those libraries.
1096#
1097# You are in a twisty little maze of UN*Xes, all different.
1098# Some might not have ether_hostton().
1099# Some might have it and declare it in <net/ethernet.h>.
1100# Some might have it and declare it in <netinet/ether.h>
1101# Some might have it and declare it in <sys/ethernet.h>.
1102# Some might have it and declare it in <arpa/inet.h>.
1103# Some might have it and declare it in <netinet/if_ether.h>.
1104# Some might have it and not declare it in any header file.
1105#
1106# Before you is a C compiler.
1107#
1108cmake_push_check_state()
1109set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LINK_LIBRARIES})
1110check_function_exists(ether_hostton HAVE_ETHER_HOSTTON)
1111if(HAVE_ETHER_HOSTTON)
1112    #
1113    # OK, we have ether_hostton().  Is it declared in <net/ethernet.h>?
1114    #
1115    # This test fails if we don't have <net/ethernet.h> or if we do
1116    # but it doesn't declare ether_hostton().
1117    #
1118    check_symbol_exists(ether_hostton net/ethernet.h NET_ETHERNET_H_DECLARES_ETHER_HOSTTON)
1119    if(NET_ETHERNET_H_DECLARES_ETHER_HOSTTON)
1120        #
1121        # Yes - we have it declared.
1122        #
1123        set(HAVE_DECL_ETHER_HOSTTON TRUE)
1124    endif()
1125    #
1126    # Did that succeed?
1127    #
1128    if(NOT HAVE_DECL_ETHER_HOSTTON)
1129        #
1130        # No - how about <netinet/ether.h>, as on Linux?
1131        #
1132        # This test fails if we don't have <netinet/ether.h>
1133        # or if we do but it doesn't declare ether_hostton().
1134        #
1135        check_symbol_exists(ether_hostton netinet/ether.h NETINET_ETHER_H_DECLARES_ETHER_HOSTTON)
1136        if(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON)
1137            #
1138            # Yes - we have it declared.
1139            #
1140            set(HAVE_DECL_ETHER_HOSTTON TRUE)
1141        endif()
1142    endif()
1143    #
1144    # Did that succeed?
1145    #
1146    if(NOT HAVE_DECL_ETHER_HOSTTON)
1147        #
1148        # No - how about <sys/ethernet.h>, as on Solaris 10 and later?
1149        #
1150        # This test fails if we don't have <sys/ethernet.h>
1151        # or if we do but it doesn't declare ether_hostton().
1152        #
1153        check_symbol_exists(ether_hostton sys/ethernet.h SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON)
1154        if(SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON)
1155            #
1156            # Yes - we have it declared.
1157            #
1158            set(HAVE_DECL_ETHER_HOSTTON TRUE)
1159        endif()
1160    endif()
1161    #
1162    # Did that succeed?
1163    #
1164    if(NOT HAVE_DECL_ETHER_HOSTTON)
1165        #
1166        # No, how about <arpa/inet.h>, as on AIX?
1167        #
1168        # This test fails if we don't have <arpa/inet.h>
1169        # or if we do but it doesn't declare ether_hostton().
1170        #
1171        check_symbol_exists(ether_hostton arpa/inet.h ARPA_INET_H_DECLARES_ETHER_HOSTTON)
1172        if(ARPA_INET_H_DECLARES_ETHER_HOSTTON)
1173            #
1174            # Yes - we have it declared.
1175            #
1176            set(HAVE_DECL_ETHER_HOSTTON TRUE)
1177        endif()
1178    endif()
1179    #
1180    # Did that succeed?
1181    #
1182    if(NOT HAVE_DECL_ETHER_HOSTTON)
1183        #
1184        # No, how about <netinet/if_ether.h>?
1185        # On some platforms, it requires <net/if.h> and
1186        # <netinet/in.h>, and we always include it with
1187        # both of them, so test it with both of them.
1188        #
1189        # This test fails if we don't have <netinet/if_ether.h>
1190        # and the headers we include before it, or if we do but
1191        # <netinet/if_ether.h> doesn't declare ether_hostton().
1192        #
1193        check_symbol_exists(ether_hostton "sys/types.h;sys/socket.h;net/if.h;netinet/in.h;netinet/if_ether.h" NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON)
1194        if(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON)
1195            #
1196            # Yes - we have it declared.
1197            #
1198            set(HAVE_DECL_ETHER_HOSTTON TRUE)
1199        endif()
1200    endif()
1201    #
1202    # After all that, is ether_hostton() declared?
1203    #
1204    if(NOT HAVE_DECL_ETHER_HOSTTON)
1205        #
1206        # No, we'll have to declare it ourselves.
1207        # Do we have "struct ether_addr" if we include <netinet/if_ether.h>?
1208        #
1209        # XXX - there's no check_type() macro that's like check_type_size()
1210        # except that it only checks for the existence of the structure type,
1211        # so we use check_type_size() and ignore the size.
1212        #
1213        cmake_push_check_state()
1214        set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h sys/socket.h net/if.h netinet/in.h netinet/if_ether.h)
1215        check_type_size("struct ether_addr" STRUCT_ETHER_ADDR)
1216        cmake_pop_check_state()
1217    endif()
1218endif()
1219cmake_pop_check_state()
1220
1221#
1222# Large file support on UN*X, a/k/a LFS.
1223#
1224if(NOT WIN32)
1225  include(FindLFS)
1226  if(LFS_FOUND)
1227    #
1228    # Add the required #defines.
1229    #
1230    add_definitions(${LFS_DEFINITIONS})
1231  endif()
1232
1233  #
1234  # Check for fseeko as well.
1235  #
1236  include(FindFseeko)
1237  if(FSEEKO_FOUND)
1238    set(HAVE_FSEEKO ON)
1239
1240    #
1241    # Add the required #defines.
1242    #
1243    add_definitions(${FSEEKO_DEFINITIONS})
1244  endif()
1245endif()
1246
1247if(INET6)
1248    message(STATUS "Support IPv6")
1249endif(INET6)
1250
1251#
1252# Pthreads.
1253# We might need them, because some libraries we use might use them,
1254# but we don't necessarily need them.
1255# That's only on UN*X; on Windows, if they use threads, we assume
1256# they're native Windows threads.
1257#
1258if(NOT WIN32)
1259  set(CMAKE_THREAD_PREFER_PTHREAD ON)
1260  find_package(Threads)
1261  if(NOT CMAKE_USE_PTHREADS_INIT)
1262    #
1263    # If it's not pthreads, we won't use it; we use it for libraries
1264    # that require it.
1265    #
1266    set(CMAKE_THREAD_LIBS_INIT "")
1267  endif(NOT CMAKE_USE_PTHREADS_INIT)
1268endif(NOT WIN32)
1269
1270if(ENABLE_PROFILING)
1271    if(NOT MSVC)
1272        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pg")
1273    endif()
1274endif()
1275
1276#
1277# Based on
1278#
1279#    https://github.com/commonmark/cmark/blob/master/FindAsan.cmake
1280#
1281# The MIT License (MIT)
1282#
1283# Copyright (c) 2013 Matthew Arsenault
1284#
1285# Permission is hereby granted, free of charge, to any person obtaining a copy
1286# of this software and associated documentation files (the "Software"), to deal
1287# in the Software without restriction, including without limitation the rights
1288# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1289# copies of the Software, and to permit persons to whom the Software is
1290# furnished to do so, subject to the following conditions:
1291#
1292# The above copyright notice and this permission notice shall be included in
1293# all copies or substantial portions of the Software.
1294#
1295# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1296# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1297# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1298# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1299# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1300# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1301# THE SOFTWARE.
1302#
1303# Test if the each of the sanitizers in the ENABLE_SANITIZERS list are
1304# supported by the compiler, and, if so, adds the appropriate flags to
1305# CMAKE_C_FLAGS, and SANITIZER_FLAGS.  If not, it fails.
1306#
1307# Do this last, in the hope that it will prevent configuration on Linux
1308# from somehow deciding it doesn't need -lpthread when building rpcapd
1309# (it does require it, but somehow, in some mysterious fashion that no
1310# obvious CMake debugging flag reveals, it doesn't realize that if we
1311# turn sanitizer stuff on).
1312#
1313# Note: apparently, some projects have decided that ENABLE_SANITIZERS
1314# is a Boolean, with OFF meaning "no sanitizers" and ON meaning "all
1315# sanitizers".  Whoever decided that didn't put it up as a common
1316# CMake idiom, as far as I can tell; we only discovered this because
1317# JetBrains' CLion "helpfully" appears to pass -DENABLE_SANITIZERS=OFF
1318# to CMake by default, which causes CMake to fail on libpcap.  Thanks!
1319#
1320# We thus also allow a setting of OFF to mean "no sanitizers" and ON to
1321# mean "all supported sanitizers that we know about and that can all
1322# be used together".
1323#
1324macro(test_sanitizer _sanitizer _sanitizer_flag)
1325    message(STATUS "Checking sanitizer ${_sanitizer}")
1326    set(sanitizer_variable "sanitize_${_sanitizer}")
1327    # Set -Werror to catch "argument unused during compilation" warnings
1328    set(CMAKE_REQUIRED_FLAGS "-Werror -fsanitize=${_sanitizer}")
1329    check_c_compiler_flag("-fsanitize=${_sanitizer}" ${sanitizer_variable})
1330    if(${${sanitizer_variable}})
1331        set(${_sanitizer_flag} "-fsanitize=${_sanitizer}")
1332    else()
1333        #
1334        # Try the versions supported prior to Clang 3.2.
1335        # If the sanitizer is "address", try -fsanitize-address.
1336        # If it's "undefined", try -fcatch-undefined-behavior.
1337        # Otherwise, give up.
1338        #
1339        set(sanitizer_variable "OLD_${sanitizer_variable}")
1340        if ("${_sanitizer}" STREQUAL "address")
1341            set(CMAKE_REQUIRED_FLAGS "-Werror -fsanitize-address")
1342            check_c_compiler_flag("-fsanitize-address" ${sanitizer_variable})
1343            if(${${sanitizer_variable}})
1344                set(${_sanitizer_flag} "-fsanitize-address")
1345            endif()
1346        elseif("${_sanitizer}" STREQUAL "undefined")
1347            set(CMAKE_REQUIRED_FLAGS "-Werror -fcatch-undefined-behavior")
1348            check_c_compiler_flag("-fcatch-undefined-behavior" ${sanitizer_variable})
1349            if(${${sanitizer_variable}})
1350                set(${_sanitizer_flag} "-fcatch-undefined-behavior")
1351            endif()
1352        endif()
1353    endif()
1354    unset(CMAKE_REQUIRED_FLAGS)
1355endmacro(test_sanitizer)
1356
1357set(SANITIZER_FLAGS "")
1358if("${ENABLE_SANITIZERS}")
1359    #
1360    # This appears to indicate that ENABLE_SANITIZERS was set to a
1361    # string value that is "one of the true constants", meaning
1362    # "1, ON, YES, TRUE, Y, or a non-zero number".
1363    #
1364    # It does not appear to happen for other settings, including
1365    # setting it to a list of one or more sanitizers.
1366    #
1367    # This setting means "enable all sanitizers that the compiler
1368    # supports".
1369    #
1370    foreach(sanitizer "address" "undefined")
1371        unset(SANITIZER_FLAG)
1372        test_sanitizer(${sanitizer} SANITIZER_FLAG)
1373        if(SANITIZER_FLAG)
1374            message(STATUS "${sanitizer} sanitizer supported using ${SANITIZER_FLAG}")
1375            set(SANITIZER_FLAGS "${SANITIZER_FLAGS} ${SANITIZER_FLAG}")
1376        else()
1377            message(STATUS "${sanitizer} isn't a supported sanitizer")
1378        endif()
1379    endforeach()
1380    if("${SANITIZER_FLAGS}" STREQUAL "")
1381        message(FATAL_ERROR "No supported sanitizers found")
1382    endif()
1383else()
1384    #
1385    # This appears to indicate that ENABLE_SANITIZERS was either:
1386    #
1387    #   not set;
1388    #   set to a set to a string value that is not "one of the true
1389    #   constants", meaning "1, ON, YES, TRUE, Y, or a non-zero number".
1390    #
1391    # The latter includes setting it to "one of the false constants",
1392    # meaning the string "is 0, OFF, NO, FALSE, N, IGNORE, NOTFOUND,
1393    # the empty string, or ends in the suffix -NOTFOUND."
1394    #
1395    # It also includes setting it to a list of one or more sanitizers.
1396    #
1397    # We want to treat "not set" and "set to one of the false constants"
1398    # as meaning "do not enable any sanitizers".
1399    #
1400    # We want to treat "set to a list of one or more sanitizers" as
1401    # meaning "enable all the sanitizers in the list".
1402    #
1403    # This requires that we distinguish between those two cases.
1404    #
1405    if(ENABLE_SANITIZERS)
1406        #
1407        # This appears to indicate that ENABLE_SANITIZERS was set to
1408        # a string value that is "not one of the false constants".
1409        #
1410        # We already know it's "not one of the true constants", so
1411        # we treat it as a list of sanitizers.
1412        #
1413        foreach(sanitizer IN LISTS ENABLE_SANITIZERS)
1414            unset(SANITIZER_FLAG)
1415            test_sanitizer(${sanitizer} SANITIZER_FLAG)
1416            if(SANITIZER_FLAG)
1417                message(STATUS "${sanitizer} sanitizer supported using ${SANITIZER_FLAG}")
1418                set(SANITIZER_FLAGS "${SANITIZER_FLAGS} ${SANITIZER_FLAG}")
1419            else()
1420                message(FATAL_ERROR "${sanitizer} isn't a supported sanitizer")
1421            endif()
1422        endforeach()
1423    else()
1424        #
1425        # This appears to indicate that ENABLE_SANITIZERS was either:
1426        #
1427        #   not set;
1428        #   set to a value that's "one of the false constants";
1429        #
1430        # so we don't enable any sanitizers.
1431        #
1432        message(STATUS "Not enabling sanitizers")
1433    endif()
1434endif()
1435
1436if(NOT "${SANITIZER_FLAGS}" STREQUAL "")
1437  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O1 -g ${SANITIZER_FLAGS} -fno-omit-frame-pointer -fno-optimize-sibling-calls")
1438endif()
1439
1440if(ENABLE_REMOTE)
1441  #
1442  # OpenSSL/libressl.
1443  #
1444  find_package(OpenSSL)
1445  if(OPENSSL_FOUND)
1446    #
1447    # We have OpenSSL.
1448    #
1449    include_directories(SYSTEM ${OPENSSL_INCLUDE_DIR})
1450    set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${OPENSSL_LIBRARIES})
1451
1452    #
1453    # The find_package() module CMake provides for OpenSSL uses does not
1454    # give us a defined indication of whether it found OpenSSL with
1455    # pkg-config or not.  We need to know that as, if it was found with
1456    # pkg-config, we should set the Requires.private value in libpcap.pc
1457    # to include its package name, openssl, otherwise we should add the
1458    # names for the static libraries to Libs.private.
1459    #
1460    # On UN*X, FindOpenSSL happens to use pkg-config to find OpenSSL, but
1461    # it doesn't appear to be documented as doing so; therefore, we don't
1462    # assume that, if we got here, we have pkg-config.
1463    #
1464    # So we use pkg_get_link_info() to run pkg-config ourselves, both
1465    # because FindOpenSSL doesn't set the OPENSSL_LDFLAGS or
1466    # OPENSSL_STATIC_LDFLAGS variables and because, for reasons explained
1467    # in the comment before the pkg_get_link_info() macro, even if it did,
1468    # it wouldn't be what we want anyway.
1469    #
1470    if (PKG_CONFIG_EXECUTABLE)
1471      pkg_get_link_info(OPENSSL openssl)
1472      if (OPENSSL_FOUND_WITH_PKG_CONFIG)
1473        #
1474        # pkg-config failed; assume that means that there is no openssl
1475        # package for it to find.  Just add OPENSSL_LIBRARIES to
1476        # LIBS_PRIVATE AND LIBS_STATIC, as that's the
1477        # best we can do. XXX - need list of -l and -L flags to add....
1478        #
1479        set(LIBS "${LIBS} ${OPENSSL_LIBS}")
1480        set(LIBS_STATIC "${LIBS_STATIC} ${OPENSSL_LIBS_STATIC}")
1481        set(REQUIRES_PRIVATE "${REQUIRES_PRIVATE} ${OPENSSL_PACKAGE_NAME}")
1482      endif()
1483    else()
1484      # Get it from OPENSSL_LIBRARIES
1485      foreach(_lib IN LISTS OPENSSL_LIBRARIES)
1486        #
1487        # Get the directory in which the library resides.
1488        #
1489        get_filename_component(_lib_directory "${_lib}" DIRECTORY)
1490
1491        #
1492        # Is the library directory in CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES?
1493        # (See comment above on why we use that.)
1494        #
1495        list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${_lib_directory}" _lib_index)
1496        if(_lib_index EQUAL -1)
1497          #
1498          # No, so add a -L flag to get the linker to search in that
1499          # directory.
1500          #
1501          set(LIBS "${LIBS} -L${_lib_directory}")
1502          set(LIBS_STATIC "${LIBS_STATIC} -L${_lib_directory}")
1503          set(LIBS_PRIVATE "${LIBS_PRIVATE} -L${_lib_directory}")
1504        endif()
1505
1506        #
1507        # Get the file name of the library, without the extension.
1508        #
1509        get_filename_component(_lib_filename "${_lib}" NAME_WE)
1510
1511        #
1512        # Strip off the "lib" prefix to get the library name, and
1513        # add a -l flag based on that.
1514        #
1515        string(REGEX REPLACE "^lib" "" _library_name "${_lib_filename}")
1516        set(LIBS "${LIBS} -l${_library_name}")
1517        set(LIBS_STATIC "${LIBS_STATIC} -l${_library_name}")
1518        set(LIBS_PRIVATE "${LIBS_PRIVATE} -l${_library_name}")
1519      endforeach()
1520    endif()
1521    set(HAVE_OPENSSL YES)
1522  endif(OPENSSL_FOUND)
1523endif(ENABLE_REMOTE)
1524
1525#
1526# On macOS, build libpcap for the appropriate architectures, if
1527# CMAKE_OSX_ARCHITECTURES isn't set (if it is, let that control
1528# the architectures for which to build it).
1529#
1530if(APPLE AND "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "")
1531    #
1532    # Get the major version of Darwin.
1533    #
1534    string(REGEX MATCH "^([0-9]+)" SYSTEM_VERSION_MAJOR "${CMAKE_SYSTEM_VERSION}")
1535
1536    if(SYSTEM_VERSION_MAJOR LESS 8)
1537        #
1538        # Pre-Tiger.
1539        #
1540        # Build libraries and executables only for 32-bit PowerPC, as
1541        # that's all that is supported.
1542        #
1543        set(OSX_LIBRARY_ARCHITECTURES "ppc")
1544        set(OSX_EXECUTABLE_ARCHITECTURES "ppc")
1545    elseif(SYSTEM_VERSION_MAJOR EQUAL 8)
1546        #
1547        # Tiger.  Is this prior to, or with, Intel support?
1548        #
1549        # Get the minor version of Darwin.
1550        #
1551        string(REPLACE "${SYSTEM_VERSION_MAJOR}." "" SYSTEM_MINOR_AND_PATCH_VERSION ${CMAKE_SYSTEM_VERSION})
1552        string(REGEX MATCH "^([0-9]+)" SYSTEM_VERSION_MINOR "${SYSTEM_MINOR_AND_PATCH_VERSION}")
1553        if(SYSTEM_VERSION_MINOR LESS 4)
1554            #
1555            # Prior to Intel support.
1556            #
1557            # Build libraries and executables for 32-bit PowerPC and
1558            # 64-bit PowerPC, with 32-bit PowerPC first, as those
1559            # are both supported.  (I'm guessing that's what Apple
1560            # does.)
1561            #
1562            set(OSX_LIBRARY_ARCHITECTURES "ppc;ppc64")
1563            set(OSX_EXECUTABLE_ARCHITECTURES "ppc;ppc64")
1564        elseif(SYSTEM_VERSION_MINOR LESS 7)
1565            #
1566            # With Intel support but prior to x86-64 support.
1567            #
1568            # Build for 32-bit PowerPC, 64-bit PowerPC, and 32-bit x86,
1569            # with 32-bit PowerPC first, as those are all supported.
1570            # (I'm guessing that's what Apple does.)
1571            #
1572            set(OSX_LIBRARY_ARCHITECTURES "ppc;ppc64;i386")
1573            set(OSX_EXECUTABLE_ARCHITECTURES "ppc;ppc64;i386")
1574        else()
1575            #
1576            # With Intel support including x86-64 support.
1577            #
1578            # Build for 32-bit PowerPC, 64-bit PowerPC, 32-bit x86,
1579            # and x86-64, with 32-bit PowerPC first, as those are
1580            # all supported.  (I'm guessing that's what Apple does.)
1581            #
1582            set(OSX_LIBRARY_ARCHITECTURES "ppc;ppc64;i386;x86_64")
1583            set(OSX_EXECUTABLE_ARCHITECTURES "ppc;ppc64;i386;x86_64")
1584        endif()
1585    elseif(SYSTEM_VERSION_MAJOR EQUAL 9)
1586        #
1587        # Leopard.
1588        #
1589        # Build libraries and executables for 32-bit PowerPC, 64-bit
1590        # PowerPC, 32-bit x86, and x86-64, with 32-bit PowerPC
1591        # first, as those are all supported.  (That's what Apple
1592        # does.)
1593        #
1594        set(OSX_LIBRARY_ARCHITECTURES "ppc;ppc64;i386;x86_64")
1595        set(OSX_EXECUTABLE_ARCHITECTURES "ppc;ppc64;i386;x86_64")
1596    elseif(SYSTEM_VERSION_MAJOR EQUAL 10)
1597        #
1598        # Snow Leopard.
1599        #
1600        # Build libraries for x86-64, 32-bit x86, and 32-bit PowerPC,
1601        # with x86-64 first, because 32-bit PowerPC executables are
1602        # supported with Rosetta.  (That's what Apple does, even though
1603        # Snow Leopard doesn't run on PPC, so PPC libpcap runs under
1604        # Rosetta, and Rosetta doesn't support BPF ioctls, so PPC
1605        # executables can't do live captures.)
1606        #
1607        set(OSX_LIBRARY_ARCHITECTURES "x86_64;i386;ppc")
1608
1609        #
1610        # Build executables only for 32-bit x86 and 64-bit x86, as PPC
1611        # machines are no longer supported.
1612        #
1613        set(OSX_EXECUTABLE_ARCHITECTURES "x86_64;i386")
1614    elseif(SYSTEM_VERSION_MAJOR GREATER 10 AND SYSTEM_VERSION_MAJOR LESS 19)
1615        #
1616        # Post-Snow Leopard, pre-Catalina.
1617        #
1618        # Build libraries for 64-bit x86 and 32-bit x86, with 64-bit x86
1619        # first, as PPC machines are no longer supported, but 32-bit
1620        # x86 executables are.  (That's what Apple does.)
1621        #
1622        # First, check whether we're building with OpenSSL.
1623        # If so, don't bother trying to build fat.
1624        #
1625        if(HAVE_OPENSSL)
1626          set(X86_32_BIT_SUPPORTED NO)
1627          set(OSX_LIBRARY_ARCHITECTURES "x86_64")
1628          set(OSX_EXECUTABLE_ARCHITECTURES "x86_64")
1629          message(WARNING "We're assuming the OpenSSL libraries are 64-bit only, so we're not compiling for 32-bit x86")
1630        else()
1631          #
1632          # Now, check whether we *can* build for i386.
1633          #
1634          cmake_push_check_state()
1635          set(CMAKE_REQUIRED_FLAGS "-arch i386")
1636          check_c_source_compiles(
1637"int
1638main(void)
1639{
1640    return 0;
1641}
1642"
1643                   X86_32_BIT_SUPPORTED)
1644          cmake_pop_check_state()
1645          if(X86_32_BIT_SUPPORTED)
1646              set(OSX_LIBRARY_ARCHITECTURES "x86_64;i386")
1647          else()
1648              set(OSX_LIBRARY_ARCHITECTURES "x86_64")
1649              #
1650              # We can't build fat; suggest that the user install the
1651              # /usr/include headers if they want to build fat.
1652              #
1653              if(SYSTEM_VERSION_MAJOR LESS 18)
1654                  #
1655                  # Pre-Mojave; the command-line tools should be sufficient to
1656                  # enable 32-bit x86 builds.
1657                  #
1658                  message(WARNING "Compiling for 32-bit x86 gives an error; try installing the command-line tools")
1659              else()
1660                  message(WARNING "Compiling for 32-bit x86 gives an error; try installing the command-line tools and, after that, installing the /usr/include headers from the /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg package")
1661              endif()
1662          endif()
1663        endif()
1664
1665        #
1666        # Build executables only for 64-bit x86, as 32-bit x86 machines
1667        # are no longer supported.
1668        #
1669        set(OSX_EXECUTABLE_ARCHITECTURES "x86_64")
1670    elseif(SYSTEM_VERSION_MAJOR EQUAL 19)
1671        #
1672        # Catalina.
1673        #
1674        # Build libraries and executables only for x86-64, as 32-bit
1675        # executables are no longer supported.  (That's what Apple
1676        # does.)
1677        #
1678        set(OSX_LIBRARY_ARCHITECTURES "x86_64")
1679        set(OSX_EXECUTABLE_ARCHITECTURES "x86_64")
1680    else()
1681        #
1682        # Post-Catalina.  Build libraries and
1683        # executables for x86-64 and ARM64.
1684        # (That's what Apple does, except they
1685        # build for arm64e, which may include
1686        # some of the pointer-checking extensions.)
1687        #
1688        # If we're building with libssl, make sure
1689        # we can build fat with it (i.e., that it
1690        # was built fat); if we can't, don't set
1691        # the target architectures, and just
1692        # build for the host we're on.
1693        #
1694        # Otherwise, just add both of them.
1695        #
1696        if(HAVE_OPENSSL)
1697          cmake_push_check_state()
1698          set(CMAKE_REQUIRED_FLAGS "-arch x86_64 -arch arm64")
1699          set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
1700          set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES})
1701          #
1702          # We must test whether this compiles and links, so
1703          # check_symbol_exists() isn't sufficient.
1704          #
1705          # SSL_library_init() may be a macro that's #defined
1706          # to be the real function to call, so we have to
1707          # include <openssl/ssl.h>, and check_function_exists()
1708          # isn't sufficient.
1709          #
1710          check_c_source_compiles(
1711"#include <openssl/ssl.h>
1712int
1713main(void)
1714{
1715    SSL_library_init();
1716    return 0;
1717}
1718"
1719              FAT_SSL_BUILDS_SUPPORTED)
1720          cmake_pop_check_state()
1721          if(FAT_SSL_BUILDS_SUPPORTED)
1722            set(OSX_LIBRARY_ARCHITECTURES "x86_64;arm64")
1723            set(OSX_EXECUTABLE_ARCHITECTURES "x86_64;arm64")
1724          endif()
1725        else()
1726          set(OSX_LIBRARY_ARCHITECTURES "x86_64;arm64")
1727          set(OSX_EXECUTABLE_ARCHITECTURES "x86_64;arm64")
1728        endif()
1729    endif()
1730endif()
1731
1732#
1733# Additional linker flags.
1734#
1735set(LINKER_FLAGS "${SANITIZER_FLAGS}")
1736if(ENABLE_PROFILING)
1737    if(MSVC)
1738        set(LINKER_FLAGS " /PROFILE")
1739    else()
1740        set(LINKER_FLAGS " -pg")
1741    endif()
1742endif()
1743
1744######################################
1745# Input files
1746######################################
1747
1748set(PROJECT_SOURCE_LIST_C
1749    bpf_dump.c
1750    bpf_filter.c
1751    bpf_image.c
1752    etherent.c
1753    fmtutils.c
1754    gencode.c
1755    nametoaddr.c
1756    optimize.c
1757    pcap-common.c
1758    pcap-util.c
1759    pcap.c
1760    savefile.c
1761    sf-pcapng.c
1762    sf-pcap.c
1763)
1764
1765if(WIN32)
1766    #
1767    # We add the character set conversion routines; they're Windows-only
1768    # for now.
1769    #
1770    # We assume we don't have asprintf(), and provide an implementation
1771    # that uses _vscprintf() to determine how big the string needs to be.
1772    #
1773    set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C}
1774        charconv.c missing/win_asprintf.c)
1775else()
1776    if(NOT HAVE_ASPRINTF)
1777        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/asprintf.c)
1778    endif()
1779    if(NOT HAVE_STRLCAT)
1780        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/strlcat.c)
1781    endif(NOT HAVE_STRLCAT)
1782    if(NOT HAVE_STRLCPY)
1783        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/strlcpy.c)
1784    endif(NOT HAVE_STRLCPY)
1785    if(NOT HAVE_STRTOK_R)
1786        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/strtok_r.c)
1787    endif(NOT HAVE_STRTOK_R)
1788endif(WIN32)
1789
1790#
1791# Determine the main pcap-XXX.c file to use, and the libraries with
1792# which we need to link libpcap, if any.
1793#
1794if(WIN32)
1795    #
1796    # Windows.
1797    #
1798    # Has the user explicitly specified a capture type?
1799    #
1800    if(PCAP_TYPE STREQUAL "")
1801        #
1802        # The user didn't explicitly specify a capture mechanism.
1803        # Check whether we have packet.dll.
1804        #
1805        if(HAVE_PACKET32)
1806            #
1807            # We have packet.dll.
1808            # Set the capture type to NPF.
1809            #
1810            set(PCAP_TYPE npf)
1811        else()
1812            #
1813            # We don't have any capture type we know about.
1814            # Report an error, and tell the user to configure with
1815            # -DPCAP_TYPE=null if they want a libpcap that can't
1816            # capture but that can read capture files.  That way,
1817            # nobody gets surprised by getting a no-capture
1818            # libpcap without asking for that.
1819            #
1820            message(FATAL_ERROR "No supported packet capture interface was found.
1821In order to build a version of libpcap that supports packet capture
1822on Windows, you will need to install Npcap and the Npcap SDK, or
1823WinPcap and the WinPcap SDK, and run cmake with -DPacket_ROOT={path of SDK},
1824where {path of SDK} is the path name of the top-level directory of the SDK.
1825That argument may have to be quoted if the path contains blanks.
1826If you want a libpcap that cannot capture packets but that can read
1827pcap and pcapng files, run cmake with -DPCAP_TYPE=null.")
1828        endif()
1829    endif()
1830else()
1831    #
1832    # UN*X.
1833    #
1834    # Figure out what type of packet capture mechanism we have, and
1835    # what libraries we'd need to link libpcap with, if any.
1836    #
1837
1838    #
1839    # Has the user explicitly specified a capture type?
1840    #
1841    if(PCAP_TYPE STREQUAL "")
1842        #
1843        # Check for a bunch of headers for various packet capture mechanisms.
1844        #
1845        check_include_files("sys/types.h;net/bpf.h" HAVE_NET_BPF_H)
1846        if(HAVE_NET_BPF_H)
1847            #
1848            # Does it define BIOCSETIF?
1849            # I.e., is it a header for an LBL/BSD-style capture
1850            # mechanism, or is it just a header for a BPF filter
1851            # engine?  Some versions of Arch Linux, for example,
1852            # have a net/bpf.h that doesn't define BIOCSETIF;
1853            # as it's a Linux, it should use packet sockets,
1854            # instead.
1855            #
1856            # We need:
1857            #
1858            #  sys/types.h, because FreeBSD 10's net/bpf.h
1859            #  requires that various BSD-style integer types
1860            #  be defined;
1861            #
1862            #  sys/time.h, because AIX 5.2 and 5.3's net/bpf.h
1863            #  doesn't include it but does use struct timeval
1864            #  in ioctl definitions;
1865            #
1866            #  sys/ioctl.h and, if we have it, sys/ioccom.h,
1867            #  because net/bpf.h defines ioctls;
1868            #
1869            #  net/if.h, because it defines some structures
1870            #  used in ioctls defined by net/bpf.h;
1871            #
1872            #  sys/socket.h, because OpenBSD 5.9's net/bpf.h
1873            #  defines some structure fields as being
1874            #  struct sockaddrs;
1875            #
1876            # and net/bpf.h doesn't necessarily include all
1877            # of those headers itself.
1878            #
1879            if(HAVE_SYS_IOCCOM_H)
1880                check_symbol_exists(BIOCSETIF "sys/types.h;sys/time.h;sys/ioctl.h;sys/socket.h;sys/ioccom.h;net/bpf.h;net/if.h" BPF_H_DEFINES_BIOCSETIF)
1881            else(HAVE_SYS_IOCCOM_H)
1882                check_symbol_exists(BIOCSETIF "sys/types.h;sys/time.h;sys/ioctl.h;sys/socket.h;net/bpf.h;net/if.h" BPF_H_DEFINES_BIOCSETIF)
1883            endif(HAVE_SYS_IOCCOM_H)
1884        endif(HAVE_NET_BPF_H)
1885        check_include_file(net/pfilt.h HAVE_NET_PFILT_H)
1886        check_include_file(net/enet.h HAVE_NET_ENET_H)
1887        check_include_file(net/nit.h HAVE_NET_NIT_H)
1888        check_include_file(sys/net/nit.h HAVE_SYS_NET_NIT_H)
1889        check_include_file(linux/socket.h HAVE_LINUX_SOCKET_H)
1890        check_include_file(net/raw.h HAVE_NET_RAW_H)
1891        check_include_file(sys/dlpi.h HAVE_SYS_DLPI_H)
1892        check_include_file(config/HaikuConfig.h HAVE_CONFIG_HAIKUCONFIG_H)
1893
1894        if(BPF_H_DEFINES_BIOCSETIF)
1895            #
1896            # BPF.
1897            # Check this before DLPI, so that we pick BPF on
1898            # Solaris 11 and later.
1899            #
1900            set(PCAP_TYPE bpf)
1901        elseif(HAVE_LINUX_SOCKET_H)
1902            #
1903            # No prizes for guessing this one.
1904            #
1905            set(PCAP_TYPE linux)
1906        elseif(HAVE_NET_PFILT_H)
1907            #
1908            # DEC OSF/1, Digital UNIX, Tru64 UNIX
1909            #
1910            set(PCAP_TYPE pf)
1911        elseif(HAVE_NET_ENET_H)
1912            #
1913            # Stanford Enetfilter.
1914            #
1915            set(PCAP_TYPE enet)
1916        elseif(HAVE_NET_NIT_H)
1917            #
1918            # SunOS 4.x STREAMS NIT.
1919            #
1920            set(PCAP_TYPE snit)
1921        elseif(HAVE_SYS_NET_NIT_H)
1922            #
1923            # Pre-SunOS 4.x non-STREAMS NIT.
1924            #
1925            set(PCAP_TYPE nit)
1926        elseif(HAVE_NET_RAW_H)
1927            #
1928            # IRIX snoop.
1929            #
1930            set(PCAP_TYPE snoop)
1931        elseif(HAVE_SYS_DLPI_H)
1932            #
1933            # DLPI on pre-Solaris 11 SunOS 5, HP-UX, possibly others.
1934            #
1935            set(PCAP_TYPE dlpi)
1936        elseif(HAVE_CONFIG_HAIKUCONFIG_H)
1937            #
1938            # Haiku.
1939            #
1940            set(PCAP_TYPE haiku)
1941        else()
1942            #
1943            # We don't have any capture type we know about.
1944            # Report an error, and tell the user to configure with
1945            # -DPCAP_TYPE=null if they want a libpcap that can't
1946            # capture but that can read capture files.  That way,
1947            # nobody gets surprised by getting a no-capture
1948            # libpcap without asking for that.
1949            #
1950            message(FATAL_ERROR "No supported packet capture interface was found.
1951See the INSTALL.md file for information on packet capture support in
1952various operating systems.
1953If you want a libpcap that cannot capture packets but that can read
1954pcap and pcapng files, run cmake with -DPCAP_TYPE=null.")
1955        endif()
1956    endif()
1957endif(WIN32)
1958message(STATUS "Packet capture mechanism type: ${PCAP_TYPE}")
1959
1960find_package(PkgConfig QUIET)
1961
1962#
1963# Do capture-mechanism-dependent tests.
1964#
1965if(WIN32)
1966    if(PCAP_TYPE STREQUAL "npf")
1967        #
1968        # Link with packet.dll before Winsock2.
1969        #
1970        set(PCAP_LINK_LIBRARIES ${Packet_LIBRARIES} ${PCAP_LINK_LIBRARIES})
1971    elseif(PCAP_TYPE STREQUAL "null")
1972    else()
1973        message(FATAL_ERROR "${PCAP_TYPE} is not a valid pcap type")
1974    endif()
1975else(WIN32)
1976    if(PCAP_TYPE STREQUAL "dlpi")
1977        #
1978        # Needed for common functions used by pcap-[dlpi,libdlpi].c
1979        #
1980        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} dlpisubs.c)
1981
1982        #
1983        # Checks for some header files.
1984        #
1985        check_include_file(sys/bufmod.h HAVE_SYS_BUFMOD_H)
1986        check_include_file(sys/dlpi_ext.h HAVE_SYS_DLPI_EXT_H)
1987
1988        #
1989        # Checks to see if Solaris has the public libdlpi(3LIB) library.
1990        # Note: The existence of /usr/include/libdlpi.h does not mean it is the
1991        # public libdlpi(3LIB) version. Before libdlpi was made public, a
1992        # private version also existed, which did not have the same APIs.
1993        # Due to a gcc bug, the default search path for 32-bit libraries does
1994        # not include /lib, we add it explicitly here.
1995        # [http://bugs.opensolaris.org/view_bug.do?bug_id=6619485].
1996        # Also, due to the bug above applications that link to libpcap with
1997        # libdlpi will have to add "-L/lib" option to "configure".
1998        #
1999        cmake_push_check_state()
2000        set(CMAKE_REQUIRED_FLAGS "-L/lib")
2001        set(CMAKE_REQUIRED_LIBRARIES dlpi)
2002        check_function_exists(dlpi_walk HAVE_LIBDLPI)
2003        cmake_pop_check_state()
2004        if(HAVE_LIBDLPI)
2005            #
2006            # XXX - add -L/lib
2007            #
2008            set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} dlpi)
2009            set(LIBS "${LIBS} -ldlpi")
2010            set(LIBS_STATIC "${LIBS_STATIC} -ldlpi")
2011            set(LIBS_PRIVATE "${LIBS_PRIVATE} -ldlpi")
2012            set(PCAP_TYPE libdlpi)
2013        endif()
2014
2015        #
2016        # This check is for Solaris with DLPI support for passive modes.
2017        # See dlpi(7P) for more details.
2018        #
2019        # XXX - there's no check_type() macro that's like check_type_size()
2020        # except that it only checks for the existence of the structure type,
2021        # so we use check_type_size() and ignore the size.
2022        #
2023        cmake_push_check_state()
2024        set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h sys/dlpi.h)
2025        check_type_size(dl_passive_req_t DL_PASSIVE_REQ_T)
2026        cmake_pop_check_state()
2027    elseif(PCAP_TYPE STREQUAL "linux")
2028        #
2029        # Do we have the wireless extensions?
2030        # linux/wireless.h requires sys/socket.h.
2031        #
2032        check_include_files("sys/socket.h;linux/wireless.h" HAVE_LINUX_WIRELESS_H)
2033
2034        #
2035        # Do we have libnl?
2036        # We only want version 3.  Version 2 was, apparently,
2037        # short-lived, and version 1 is source and binary
2038        # incompatible with version 3, and it appears that,
2039        # these days, everybody's using version 3.  We're
2040        # not supporting older versions of the Linux kernel;
2041        # let's drop support for older versions of libnl, too.
2042        #
2043        if(BUILD_WITH_LIBNL)
2044            pkg_check_modules(LIBNL libnl-genl-3.0)
2045            if(LIBNL_FOUND)
2046                set(PCAP_LINK_LIBRARIES ${LIBNL_LIBRARIES} ${PCAP_LINK_LIBRARIES})
2047
2048                #
2049                # Get raw link flags from pkg-config.
2050                #
2051                pkg_get_link_info(LIBNL libnl-genl-3.0)
2052                set(LIBS "${LIBNL_LIBS} ${LIBS}")
2053                set(LIBS_STATIC "${LIBNL_LIBS_STATIC} ${LIBS_STATIC}")
2054                set(REQUIRES_PRIVATE "${LIBNL_PACKAGE_NAME} ${REQUIRES_PRIVATE}")
2055            else()
2056                cmake_push_check_state()
2057                set(CMAKE_REQUIRED_LIBRARIES nl-3)
2058                check_function_exists(nl_socket_alloc HAVE_LIBNL)
2059                cmake_pop_check_state()
2060                if(HAVE_LIBNL)
2061                    #
2062                    # Yes, we have libnl 3.x.
2063                    #
2064                    set(PCAP_LINK_LIBRARIES nl-genl-3 nl-3 ${PCAP_LINK_LIBRARIES})
2065                    include_directories("/usr/include/libnl3")
2066                    set(LIBS "-lnl-genl-3 -lnl-3 ${LIBS}")
2067                    set(LIBS_STATIC "-lnl-genl-3 -lnl-3 ${LIBS_STATIC}")
2068                    set(LIBS_PRIVATE "-lnl-genl-3 -lnl-3 ${LIBS_PRIVATE}")
2069                endif()
2070            endif()
2071        else()
2072            unset(HAVE_LIBNL CACHE) # check_function_exists stores results in cache
2073        endif()
2074
2075        check_struct_has_member("struct tpacket_auxdata" tp_vlan_tci linux/if_packet.h HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI)
2076    elseif(PCAP_TYPE STREQUAL "bpf")
2077        #
2078        # Check whether we have the *BSD-style ioctls.
2079        #
2080        check_include_files("sys/types.h;net/if_media.h" HAVE_NET_IF_MEDIA_H)
2081
2082        #
2083        # Check whether we have struct BPF_TIMEVAL.
2084        #
2085        # XXX - there's no check_type() macro that's like check_type_size()
2086        # except that it only checks for the existence of the structure type,
2087        # so we use check_type_size() and ignore the size.
2088        #
2089        cmake_push_check_state()
2090        if(HAVE_SYS_IOCCOM_H)
2091            set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h sys/ioccom.h net/bpf.h)
2092            check_type_size("struct BPF_TIMEVAL" STRUCT_BPF_TIMEVAL)
2093        else()
2094            set(CMAKE_EXTRA_INCLUDE_FILES  sys/types.h net/bpf.h)
2095            check_type_size("struct BPF_TIMEVAL" STRUCT_BPF_TIMEVAL)
2096        endif()
2097        cmake_pop_check_state()
2098
2099        #
2100        # Check whether there's a inet/ipnet.h header and,
2101        # if so, whether it defines IPNET_ANY_LINK - if so,
2102        # we assume we have the "any" device (that's a
2103        # Solaris header, and later versions of Solaris
2104        # have an "any" device).
2105        #
2106        # Attempting to include it at compile time could
2107        # be a pain, as it's a kernel header.
2108        #
2109        message(STATUS "Checking whether the Solaris \"any\" device is supported")
2110        if(EXISTS /usr/include/inet/ipnet.h)
2111            file(STRINGS /usr/include/inet/ipnet.h IPNET_ANY_LINK_LINES REGEX IPNET_ANY_LINK)
2112            if(NOT IPNET_ANY_LINK_LINES STREQUAL "")
2113                set(HAVE_SOLARIS_ANY_DEVICE TRUE)
2114            endif()
2115        endif()
2116        if(HAVE_SOLARIS_ANY_DEVICE)
2117            message(STATUS "Checking whether the Solaris \"any\" device is supported - supported")
2118        else()
2119            message(STATUS "Checking whether the Solaris \"any\" device is supported - not supported")
2120        endif()
2121    elseif(PCAP_TYPE STREQUAL "haiku")
2122        #
2123        # Check for some headers just in case.
2124        #
2125        check_include_files("net/if.h;net/if_dl.h;net/if_types.h" HAVE_NET_IF_TYPES_H)
2126        set(PCAP_SRC pcap-${PCAP_TYPE}.c)
2127    elseif(PCAP_TYPE STREQUAL "null")
2128    else()
2129        message(FATAL_ERROR "${PCAP_TYPE} is not a valid pcap type")
2130    endif()
2131endif(WIN32)
2132
2133if(NOT DEFINED PCAP_SRC)
2134set(PCAP_SRC pcap-${PCAP_TYPE}.c)
2135endif()
2136
2137set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} ${PCAP_SRC})
2138
2139#
2140# Now figure out how we get a list of interfaces and addresses,
2141# if we support capturing.  Don't bother if we don't support
2142# capturing.
2143#
2144if(NOT WIN32)
2145    #
2146    # UN*X - figure out what type of interface list mechanism we
2147    # have.
2148    #
2149    # If the capture type is null, that means we can't capture,
2150    # so we can't open any capture devices, so we won't return
2151    # any interfaces.
2152    #
2153    if(NOT PCAP_TYPE STREQUAL "null")
2154        cmake_push_check_state()
2155        set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LINK_LIBRARIES})
2156        check_function_exists(getifaddrs HAVE_GETIFADDRS)
2157        cmake_pop_check_state()
2158        if(NOT HAVE_GETIFADDRS)
2159            #
2160            # It's not in the libraries that, at this point, we've
2161            # found we need to link libpcap with.
2162            #
2163            # It's in libsocket on Solaris and possibly other OSes;
2164            # as long as we're not linking with libxnet, check there.
2165            #
2166            # NOTE: if you hand check_library_exists as its last
2167            # argument a variable that's been set, it skips the test,
2168            # so we need different variables.
2169            #
2170            if(NOT LIBXNET_HAS_GETHOSTBYNAME)
2171                check_library_exists(socket getifaddrs "" SOCKET_HAS_GETIFADDRS)
2172                if(SOCKET_HAS_GETIFADDRS)
2173                    set(PCAP_LINK_LIBRARIES socket ${PCAP_LINK_LIBRARIES})
2174                    set(LIBS "-lsocket ${LIBS}")
2175                    set(LIBS_STATIC "-lsocket ${LIBS_STATIC}")
2176                    set(LIBS_PRIVATE "-lsocket ${LIBS_PRIVATE}")
2177                    set(HAVE_GETIFADDRS TRUE)
2178                endif()
2179            endif()
2180        endif()
2181        if(HAVE_GETIFADDRS)
2182            #
2183            # We have "getifaddrs()"; make sure we have <ifaddrs.h>
2184            # as well, just in case some platform is really weird.
2185            # It may require that sys/types.h be included first,
2186            # so include it first.
2187            #
2188            check_include_files("sys/types.h;ifaddrs.h" HAVE_IFADDRS_H)
2189            if(HAVE_IFADDRS_H)
2190                #
2191                # We have the header, so we use "getifaddrs()" to
2192                # get the list of interfaces.
2193                #
2194                set(FINDALLDEVS_TYPE getad)
2195            else()
2196                #
2197                # We don't have the header - give up.
2198                # XXX - we could also fall back on some other
2199                # mechanism, but, for now, this'll catch this
2200                # problem so that we can at least try to figure
2201                # out something to do on systems with "getifaddrs()"
2202                # but without "ifaddrs.h", if there is something
2203                # we can do on those systems.
2204                #
2205                message(FATAL_ERROR "Your system has getifaddrs() but doesn't have a usable <ifaddrs.h>.")
2206            endif()
2207        else()
2208            #
2209            # Well, we don't have "getifaddrs()", at least not with the
2210            # libraries with which we've decided we need to link
2211            # libpcap with, so we have to use some other mechanism.
2212            #
2213            # Note that this may happen on Solaris, which has
2214            # getifaddrs(), but in -lsocket, not in -lxnet, so we
2215            # won't find it if we link with -lxnet, which we want
2216            # to do for other reasons.
2217            #
2218            # For now, we use either the SIOCGIFCONF ioctl or the
2219            # SIOCGLIFCONF ioctl, preferring the latter if we have
2220            # it; the latter is a Solarisism that first appeared
2221            # in Solaris 8.  (Solaris's getifaddrs() appears to
2222            # be built atop SIOCGLIFCONF; using it directly
2223            # avoids a not-all-that-useful middleman.)
2224            #
2225            try_compile(HAVE_SIOCGLIFCONF ${CMAKE_CURRENT_BINARY_DIR} "${pcap_SOURCE_DIR}/cmake/have_siocglifconf.c" )
2226            if(HAVE_SIOCGLIFCONF)
2227                set(FINDALLDEVS_TYPE glifc)
2228            else()
2229                set(FINDALLDEVS_TYPE gifc)
2230            endif()
2231        endif()
2232        message(STATUS "Find-interfaces mechanism type: ${FINDALLDEVS_TYPE}")
2233        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} fad-${FINDALLDEVS_TYPE}.c)
2234    endif()
2235endif()
2236
2237# Check for hardware timestamp support.
2238if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
2239    check_include_file(linux/net_tstamp.h HAVE_LINUX_NET_TSTAMP_H)
2240endif()
2241
2242#
2243# Check for additional native sniffing capabilities.
2244#
2245
2246#
2247# Various Linux-specific mechanisms.
2248#
2249if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
2250    # Check for usbmon USB sniffing support.
2251    if(NOT DISABLE_LINUX_USBMON)
2252        set(PCAP_SUPPORT_LINUX_USBMON TRUE)
2253        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-usb-linux.c)
2254        #
2255        # Do we have a version of <linux/compiler.h> available?
2256        # If so, we might need it for <linux/usbdevice_fs.h>.
2257        #
2258        check_include_files("linux/compiler.h" HAVE_LINUX_COMPILER_H)
2259        if(HAVE_LINUX_COMPILER_H)
2260            #
2261            # Yes - include it when testing for <linux/usbdevice_fs.h>.
2262            #
2263            check_include_files("linux/compiler.h;linux/usbdevice_fs.h" HAVE_LINUX_USBDEVICE_FS_H)
2264        else(HAVE_LINUX_COMPILER_H)
2265            check_include_files("linux/usbdevice_fs.h" HAVE_LINUX_USBDEVICE_FS_H)
2266        endif(HAVE_LINUX_COMPILER_H)
2267        if(HAVE_LINUX_USBDEVICE_FS_H)
2268            #
2269            # OK, does it define bRequestType?  Older versions of the kernel
2270            # define fields with names like "requesttype, "request", and
2271            # "value", rather than "bRequestType", "bRequest", and
2272            # "wValue".
2273            #
2274            if(HAVE_LINUX_COMPILER_H)
2275                check_struct_has_member("struct usbdevfs_ctrltransfer" bRequestType "linux/compiler.h;linux/usbdevice_fs.h" HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE)
2276            else(HAVE_LINUX_COMPILER_H)
2277                check_struct_has_member("struct usbdevfs_ctrltransfer" bRequestType "linux/usbdevice_fs.h" HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE)
2278            endif(HAVE_LINUX_COMPILER_H)
2279        endif()
2280    endif()
2281
2282    #
2283    # Check for netfilter sniffing support.
2284    #
2285    # Life's too short to deal with trying to get this to compile
2286    # if you don't get the right types defined with
2287    # __KERNEL_STRICT_NAMES getting defined by some other include.
2288    #
2289    # Check whether the includes Just Work.  If not, don't turn on
2290    # netfilter support.
2291    #
2292    check_c_source_compiles(
2293"#include <sys/socket.h>
2294#include <netinet/in.h>
2295#include <linux/types.h>
2296
2297#include <linux/netlink.h>
2298#include <linux/netfilter.h>
2299#include <linux/netfilter/nfnetlink.h>
2300#include <linux/netfilter/nfnetlink_log.h>
2301#include <linux/netfilter/nfnetlink_queue.h>
2302
2303int
2304main(void)
2305{
2306    return 0;
2307}
2308"
2309        PCAP_SUPPORT_NETFILTER)
2310    if(PCAP_SUPPORT_NETFILTER)
2311        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-netfilter-linux.c)
2312    endif(PCAP_SUPPORT_NETFILTER)
2313endif()
2314
2315# Check for netmap sniffing support.
2316if(NOT DISABLE_NETMAP)
2317    #
2318    # Check whether net/netmap_user.h is usable if NETMAP_WITH_LIBS is
2319    # defined; it's not usable on DragonFly BSD 4.6 if NETMAP_WITH_LIBS
2320    # is defined, for example, as it includes a nonexistent malloc.h
2321    # header.
2322    #
2323    check_c_source_compiles(
2324"#define NETMAP_WITH_LIBS
2325#include <net/netmap_user.h>
2326
2327int
2328main(void)
2329{
2330    return 0;
2331}
2332"
2333        PCAP_SUPPORT_NETMAP)
2334    if(PCAP_SUPPORT_NETMAP)
2335        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-netmap.c)
2336    endif(PCAP_SUPPORT_NETMAP)
2337endif()
2338
2339# Check for DPDK sniffing support
2340if(NOT DISABLE_DPDK)
2341    find_package(dpdk)
2342    if(dpdk_FOUND)
2343        #
2344        # We call rte_eth_dev_count_avail(), and older versions of DPDK
2345        # didn't have it, so check for it.
2346        #
2347        cmake_push_check_state()
2348        set(CMAKE_REQUIRED_INCLUDES ${dpdk_INCLUDE_DIRS})
2349        set(CMAKE_REQUIRED_LIBRARIES ${dpdk_LIBRARIES})
2350        check_function_exists(rte_eth_dev_count_avail HAVE_RTE_ETH_DEV_COUNT_AVAIL)
2351        cmake_pop_check_state()
2352        if(HAVE_RTE_ETH_DEV_COUNT_AVAIL)
2353            set(DPDK_C_FLAGS "-march=native")
2354            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${DPDK_C_FLAGS}")
2355            include_directories(AFTER ${dpdk_INCLUDE_DIRS})
2356            link_directories(AFTER ${dpdk_LIBRARIES})
2357            set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${dpdk_LIBRARIES})
2358            set(LIBS "${LIBS} ${dpdk_LIBS}")
2359            set(LIBS_STATIC "${LIBS_STATIC} ${dpdk_LIBS_STATIC}")
2360            set(REQUIRES_PRIVATE "${REQUIRES_PRIVATE} ${dpdk_PACKAGE_NAME}")
2361            set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-dpdk.c)
2362            set(PCAP_SUPPORT_DPDK TRUE)
2363
2364            #
2365            # Check whether the rte_ether.h file defines
2366            # struct ether_addr or struct rte_ether_addr.
2367            #
2368            # ("API compatibility?  That's for losers!")
2369            #
2370            cmake_push_check_state()
2371            set(CMAKE_REQUIRED_INCLUDES ${dpdk_INCLUDE_DIRS})
2372            set(CMAKE_EXTRA_INCLUDE_FILES rte_ether.h)
2373            check_type_size("struct rte_ether_addr" STRUCT_RTE_ETHER_ADDR)
2374            cmake_pop_check_state()
2375        endif()
2376    else()
2377      message(WARNING,
2378"We couldn't find DPDK with pkg-config.  If you want DPDK support,
2379make sure that pkg-config is installed, that DPDK 18.02.2 or later is
2380installed, and that DPDK provides a .pc file.")
2381    endif()
2382endif()
2383
2384# Check for Bluetooth sniffing support
2385if(NOT DISABLE_BLUETOOTH)
2386    if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
2387        check_include_file(bluetooth/bluetooth.h HAVE_BLUETOOTH_BLUETOOTH_H)
2388        if(HAVE_BLUETOOTH_BLUETOOTH_H)
2389            set(PCAP_SUPPORT_BT TRUE)
2390            set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-bt-linux.c)
2391            #
2392            # OK, does struct sockaddr_hci have an hci_channel
2393            # member?
2394            #
2395            check_struct_has_member("struct sockaddr_hci" hci_channel "bluetooth/bluetooth.h;bluetooth/hci.h" HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL)
2396            if(HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL)
2397                #
2398                # OK, is HCI_CHANNEL_MONITOR defined?
2399                #
2400               check_c_source_compiles(
2401"#include <bluetooth/bluetooth.h>
2402#include <bluetooth/hci.h>
2403
2404int
2405main(void)
2406{
2407    int i = HCI_CHANNEL_MONITOR;
2408    return 0;
2409}
2410"
2411                   PCAP_SUPPORT_BT_MONITOR)
2412               if(PCAP_SUPPORT_BT_MONITOR)
2413                   #
2414                   # Yes, so we can also support Bluetooth monitor
2415                   # sniffing.
2416                   #
2417                   set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-bt-monitor-linux.c)
2418               endif(PCAP_SUPPORT_BT_MONITOR)
2419            endif(HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL)
2420        endif(HAVE_BLUETOOTH_BLUETOOTH_H)
2421    endif()
2422else()
2423    unset(PCAP_SUPPORT_BT_MONITOR CACHE)
2424endif()
2425
2426# Check for D-Bus sniffing support
2427if(NOT DISABLE_DBUS)
2428    #
2429    # We don't support D-Bus sniffing on macOS; see
2430    #
2431    # https://bugs.freedesktop.org/show_bug.cgi?id=74029
2432    #
2433    if(APPLE)
2434        message(FATAL_ERROR "Due to freedesktop.org bug 74029, D-Bus capture support is not available on macOS")
2435    endif(APPLE)
2436    pkg_check_modules(DBUS dbus-1)
2437    if(DBUS_FOUND)
2438        set(PCAP_SUPPORT_DBUS TRUE)
2439        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-dbus.c)
2440        include_directories(${DBUS_INCLUDE_DIRS})
2441
2442        #
2443        # This "helpfully" supplies DBUS_LIBRARIES as a bunch of
2444        # library names - not paths - and DBUS_LIBRARY_DIRS as
2445        # a bunch of directories.
2446        #
2447        # CMake *really* doesn't like the notion of specifying "here are
2448        # the directories in which to look for libraries" except in
2449        # find_library() calls; it *really* prefers using full paths to
2450        # library files, rather than library names.
2451        #
2452        # Find the libraries and add their full paths.
2453        #
2454        set(DBUS_LIBRARY_FULLPATHS)
2455        foreach(_lib IN LISTS DBUS_LIBRARIES)
2456            #
2457            # Try to find this library, so we get its full path.
2458            #
2459            find_library(_libfullpath ${_lib} HINTS ${DBUS_LIBRARY_DIRS})
2460            list(APPEND DBUS_LIBRARY_FULLPATHS ${_libfullpath})
2461        endforeach()
2462        set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${DBUS_LIBRARY_FULLPATHS})
2463
2464        #
2465        # Get library information for DPDK.
2466        #
2467        pkg_get_link_info(DBUS dbus-1)
2468        set(LIBS "${LIBS} ${DBUS_LIBS}")
2469        set(LIBS_STATIC "${LIBS_STATIC} ${DBUS_LIBS_STATIC}")
2470        set(REQUIRES_PRIVATE "${REQUIRES_PRIVATE} ${DBUS_PACKAGE_NAME}")
2471    endif(DBUS_FOUND)
2472endif(NOT DISABLE_DBUS)
2473
2474# Check for RDMA sniffing support
2475if(NOT DISABLE_RDMA)
2476    pkg_check_modules(LIBIBVERBS libibverbs)
2477    if(LIBIBVERBS_FOUND)
2478        #
2479        # pkg-config found it; remember its pkg-config name.
2480        #
2481        set(LIBIBVERBS_REQUIRES_PRIVATE ${LIBIBVERBS_PACKAGE_NAME})
2482
2483        #
2484        # Get static linking information for it.
2485        #
2486        pkg_get_link_info(LIBIBVERBS libibverbs)
2487    else()
2488        #
2489        # pkg-config didn't find it; try to look for it ourselves
2490        #
2491        check_library_exists(ibverbs ibv_get_device_list "" LIBIBVERBS_HAS_IBV_GET_DEVICE_LIST)
2492        if(LIBIBVERBS_HAS_IBV_GET_DEVICE_LIST)
2493            set(LIBIBVERBS_FOUND TRUE)
2494            set(LIBIBVERBS_LIBRARIES ibverbs)
2495            # XXX - at least on Ubuntu 20.04, there are many more
2496            # libraries needed; is there any platform where
2497            # libibverbs is available but where pkg-config
2498            # isn't available or libibverbs doesn't use it?
2499            # If not, we should only use pkg-config for it.
2500            set(LIBIBVERBS_STATIC_LIBRARIES ibverbs)
2501            set(LIBIBVERBS_LIBS -libverbs)
2502            set(LIBIBVERBS_LIBS_STATIC -libverbs)
2503            set(LIBIBVERBS_LIBS_PRIVATE -libverbs)
2504        endif()
2505    endif()
2506    if(LIBIBVERBS_FOUND)
2507        #
2508        # For unknown reasons, check_include_file() doesn't just attempt
2509        # to compile a test program that includes the header in
2510        # question, it also attempts to link it.
2511        #
2512        # For unknown reasons, at least some of the static inline
2513        # functions defined in infiniband/verbs.h are not inlined by the
2514        # Sun^WOracle Studio C compiler, so the compiler generates code
2515        # for them as part of the object code resulting from compiling
2516        # the test program. At lest some of those functions call
2517        # routines in -libverbs, so, in order to keep the compile and
2518        # link from failing, even though the header file exists and is
2519        # usable, we need to link with -libverbs.
2520        #
2521        cmake_push_check_state()
2522        set(CMAKE_REQUIRED_LIBRARIES ${LIBIBVERBS_LIBRARIES})
2523        check_include_file(infiniband/verbs.h HAVE_INFINIBAND_VERBS_H)
2524        if(HAVE_INFINIBAND_VERBS_H)
2525            check_symbol_exists(ibv_create_flow infiniband/verbs.h PCAP_SUPPORT_RDMASNIFF)
2526            if(PCAP_SUPPORT_RDMASNIFF)
2527                set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-rdmasniff.c)
2528                set(PCAP_LINK_LIBRARIES ${LIBIBVERBS_LIBRARIES} ${PCAP_LINK_LIBRARIES})
2529                set(LIBS "${LIBIBVERBS_LIBS} ${LIBS}")
2530                set(LIBS_STATIC "${LIBIBVERBS_LIBS_STATIC} ${LIBS_STATIC}")
2531                set(LIBS_PRIVATE "${LIBIBVERBS_LIBS_PRIVATE} ${LIBS_PRIVATE}")
2532                set(REQUIRES_PRIVATE "${REQUIRES_PRIVATE} ${LIBIBVERBS_PACKAGE_NAME}")
2533            endif(PCAP_SUPPORT_RDMASNIFF)
2534        endif(HAVE_INFINIBAND_VERBS_H)
2535        cmake_pop_check_state()
2536    endif(LIBIBVERBS_FOUND)
2537endif(NOT DISABLE_RDMA)
2538
2539#
2540# Check for sniffing capabilities using third-party APIs.
2541#
2542
2543# Check for Endace DAG card support.
2544if(NOT DISABLE_DAG)
2545    #
2546    # Try to find the DAG header file and library.
2547    #
2548    find_package(DAG)
2549
2550    #
2551    # Did we succeed?
2552    #
2553    if(DAG_FOUND)
2554        #
2555        # Yes.
2556        # Check for various DAG API functions.
2557        #
2558        cmake_push_check_state()
2559        set(CMAKE_REQUIRED_INCLUDES ${DAG_INCLUDE_DIRS})
2560        set(CMAKE_REQUIRED_LIBRARIES ${DAG_LIBRARIES})
2561        check_function_exists(dag_attach_stream HAVE_DAG_STREAMS_API)
2562        if(NOT HAVE_DAG_STREAMS_API)
2563            message(FATAL_ERROR "DAG library lacks streams support")
2564        endif()
2565        check_function_exists(dag_attach_stream64 HAVE_DAG_LARGE_STREAMS_API)
2566        check_function_exists(dag_get_erf_types HAVE_DAG_GET_ERF_TYPES)
2567        check_function_exists(dag_get_stream_erf_types HAVE_DAG_GET_STREAM_ERF_TYPES)
2568        cmake_pop_check_state()
2569
2570        include_directories(AFTER ${DAG_INCLUDE_DIRS})
2571        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-dag.c)
2572        set(HAVE_DAG_API TRUE)
2573        set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${DAG_LIBRARIES})
2574        set(LIBS "${LIBS} ${DAG_LIBS}")
2575        set(LIBS_STATIC "${LIBS_STATIC} ${DAG_LIBS_STATIC}")
2576        set(LIBS_PRIVATE "${LIBS_PRIVATE} ${DAG_LIBS_PRIVATE}")
2577
2578        if(HAVE_DAG_LARGE_STREAMS_API)
2579            get_filename_component(DAG_LIBRARY_DIR ${DAG_LIBRARY} PATH)
2580            check_library_exists(vdag vdag_set_device_info ${DAG_LIBRARY_DIR} HAVE_DAG_VDAG)
2581            if(HAVE_DAG_VDAG)
2582                set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
2583                set(LIBS "${LIBS} ${CMAKE_THREAD_LIBS_INIT}")
2584                set(LIBS_STATIC "${LIBS_STATIC} ${CMAKE_THREAD_LIBS_INIT}")
2585                set(LIBS_PRIVATE "${LIBS_PRIVATE} ${CMAKE_THREAD_LIBS_INIT}")
2586            endif()
2587        endif()
2588    endif()
2589endif()
2590
2591# Check for Septel card support.
2592set(PROJECT_EXTERNAL_OBJECT_LIST "")
2593if(NOT DISABLE_SEPTEL)
2594    #
2595    # Do we have the msg.h header?
2596    #
2597    set(SEPTEL_INCLUDE_DIRS "${SEPTEL_ROOT}/INC")
2598    cmake_push_check_state()
2599    set(CMAKE_REQUIRED_INCLUDES ${SEPTEL_INCLUDE_DIRS})
2600    check_include_file(msg.h HAVE_INC_MSG_H)
2601    cmake_pop_check_state()
2602    if(HAVE_INC_MSG_H)
2603        #
2604        # Yes.
2605        #
2606        include_directories(AFTER ${SEPTEL_INCLUDE_DIRS})
2607        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-septel.c)
2608        set(PROJECT_EXTERNAL_OBJECT_LIST ${PROJECT_EXTERNAL_OBJECT_LIST} "${SEPTEL_ROOT}/asciibin.o ${SEPTEL_ROOT}/bit2byte.o ${SEPTEL_ROOT}/confirm.o ${SEPTEL_ROOT}/fmtmsg.o ${SEPTEL_ROOT}/gct_unix.o ${SEPTEL_ROOT}/hqueue.o ${SEPTEL_ROOT}/ident.o ${SEPTEL_ROOT}/mem.o ${SEPTEL_ROOT}/pack.o ${SEPTEL_ROOT}/parse.o ${SEPTEL_ROOT}/pool.o ${SEPTEL_ROOT}/sdlsig.o ${SEPTEL_ROOT}/strtonum.o ${SEPTEL_ROOT}/timer.o ${SEPTEL_ROOT}/trace.o")
2609        set(HAVE_SEPTEL_API TRUE)
2610    endif()
2611endif()
2612
2613# Check for Myricom SNF support.
2614if(NOT DISABLE_SNF)
2615    #
2616    # Try to find the SNF header file and library.
2617    #
2618    find_package(SNF)
2619
2620    #
2621    # Did we succeed?
2622    #
2623    if(SNF_FOUND)
2624        #
2625        # Yes.
2626        #
2627        include_directories(AFTER ${SNF_INCLUDE_DIRS})
2628        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-snf.c)
2629        set(HAVE_SNF_API TRUE)
2630        set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${SNF_LIBRARIES})
2631        set(LIBS "${LIBS_STATIC} ${SNF_LIBS}")
2632        set(LIBS_STATIC "${LIBS_STATIC} ${SNF_LIBS_STATIC}")
2633        set(LIBS_PRIVATE "${LIBS_PRIVATE} ${SNF_LIBS_PRIVATE}")
2634    endif()
2635endif()
2636
2637# Check for Riverbed AirPcap support.
2638if(NOT DISABLE_AIRPCAP)
2639    #
2640    # Try to find the AirPcap header file and library.
2641    #
2642    find_package(AirPcap)
2643
2644    #
2645    # Did we succeed?
2646    #
2647    if(AirPcap_FOUND)
2648        #
2649        # Yes.
2650        #
2651        include_directories(AFTER ${AirPcap_INCLUDE_DIRS})
2652        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-airpcap.c)
2653        set(HAVE_AIRPCAP_API TRUE)
2654        set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${AirPcap_LIBRARIES})
2655    endif()
2656endif()
2657
2658# Check for Riverbed TurboCap support.
2659if(NOT DISABLE_TC)
2660    #
2661    # Try to find the TurboCap header file and library.
2662    #
2663    find_package(TC)
2664
2665    #
2666    # Did we succeed?
2667    #
2668    if(TC_FOUND)
2669        #
2670        # Yes.
2671        #
2672        include_directories(AFTER ${TC_INCLUDE_DIRS})
2673        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-tc.c)
2674        set(HAVE_TC_API TRUE)
2675        set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${TC_LIBRARIES} ${CMAKE_USE_PTHREADS_INIT} stdc++)
2676    endif()
2677endif()
2678
2679#
2680# Remote capture support.
2681#
2682
2683if(ENABLE_REMOTE)
2684    #
2685    # Check for various members of struct msghdr.
2686    # We need to include ftmacros.h on some platforms, to make sure we
2687    # get the POSIX/Single USER Specification version of struct msghdr,
2688    # which has those members, rather than the backwards-compatible
2689    # version, which doesn't.  That's not a system header file, and
2690    # at least some versions of CMake include it as <ftmacros.h>, which
2691    # won't check the current directory, so we add the top-level
2692    # source directory to the list of include directories when we do
2693    # the check.
2694    #
2695    cmake_push_check_state()
2696    set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR})
2697    check_struct_has_member("struct msghdr" msg_control "ftmacros.h;sys/socket.h" HAVE_STRUCT_MSGHDR_MSG_CONTROL)
2698    check_struct_has_member("struct msghdr" msg_flags "ftmacros.h;sys/socket.h" HAVE_STRUCT_MSGHDR_MSG_FLAGS)
2699    cmake_pop_check_state()
2700    set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C}
2701        pcap-new.c pcap-rpcap.c rpcap-protocol.c sockutils.c sslutils.c)
2702endif(ENABLE_REMOTE)
2703
2704###################################################################
2705#   Warning options
2706###################################################################
2707
2708#
2709# Check and add warning options if we have a .devel file.
2710#
2711if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.devel OR EXISTS ${CMAKE_BINARY_DIR}/.devel)
2712    #
2713    # Warning options.
2714    #
2715    if(MSVC AND NOT ${CMAKE_C_COMPILER} MATCHES "clang*")
2716        #
2717        # MSVC, with Microsoft's front end and code generator.
2718        # "MSVC" is also set for Microsoft's compiler with a Clang
2719        # front end and their code generator ("Clang/C2"), so we
2720        # check for clang.exe and treat that differently.
2721        #
2722        check_and_add_compiler_option(-Wall)
2723        #
2724        # Disable some pointless warnings that /Wall turns on.
2725        #
2726        # Unfortunately, MSVC does not appear to have an equivalent
2727        # to "__attribute__((unused))" to mark a particular function
2728        # parameter as being known to be unused, so that the compiler
2729        # won't warn about it (for example, the function might have
2730        # that parameter because a pointer to it is being used, and
2731        # the signature of that function includes that parameter).
2732        # C++ lets you give a parameter a type but no name, but C
2733        # doesn't have that.
2734        #
2735        check_and_add_compiler_option(-wd4100)
2736        #
2737        # In theory, we care whether somebody uses f() rather than
2738        # f(void) to declare a function with no arguments, but, in
2739        # practice, there are places in the Windows header files
2740        # that appear to do that, so we squelch that warning.
2741        #
2742        check_and_add_compiler_option(-wd4255)
2743        #
2744        # Windows FD_SET() generates this, so we suppress it.
2745        #
2746        check_and_add_compiler_option(-wd4548)
2747        #
2748        # Perhaps testing something #defined to be 0 with #ifdef is an
2749        # error, and it should be tested with #if, but perhaps it's
2750        # not, and Microsoft does that in its headers, so we squelch
2751        # that warning.
2752        #
2753        check_and_add_compiler_option(-wd4574)
2754        #
2755        # The Windows headers also test not-defined values in #if, so
2756        # we don't want warnings about that, either.
2757        #
2758        check_and_add_compiler_option(-wd4668)
2759        #
2760        # We do *not* care whether some function is, or isn't, going to be
2761        # expanded inline.
2762        #
2763        check_and_add_compiler_option(-wd4710)
2764        check_and_add_compiler_option(-wd4711)
2765        #
2766        # We do *not* care whether we're adding padding bytes after
2767        # structure members.
2768        #
2769        check_and_add_compiler_option(-wd4820)
2770        #
2771        # We do *not* care about every single place the compiler would
2772        # have inserted Spectre mitigation if only we had told it to
2773        # do so with /Qspectre.  Maybe it's worth it, as that's in
2774        # Bison-generated code that we don't control.
2775        #
2776        # XXX - add /Qspectre if that is really worth doing.
2777        #
2778        check_and_add_compiler_option(-wd5045)
2779
2780        #
2781        # Treat all (remaining) warnings as errors.
2782        #
2783        check_and_add_compiler_option(-WX)
2784    else()
2785        #
2786        # Other compilers, including MSVC with a Clang front end and
2787        # Microsoft's code generator.  We currently treat them as if
2788        # they might support GCC-style -W options.
2789        #
2790        check_and_add_compiler_option(-W)
2791        check_and_add_compiler_option(-Wall)
2792        check_and_add_compiler_option(-Wcomma)
2793        # Warns about safeguards added in case the enums are extended
2794        # check_and_add_compiler_option(-Wcovered-switch-default)
2795        check_and_add_compiler_option(-Wdocumentation)
2796        check_and_add_compiler_option(-Wformat-nonliteral)
2797        check_and_add_compiler_option(-Wmissing-noreturn)
2798        check_and_add_compiler_option(-Wmissing-prototypes)
2799        check_and_add_compiler_option(-Wmissing-variable-declarations)
2800        check_and_add_compiler_option(-Wnull-pointer-subtraction)
2801        check_and_add_compiler_option(-Wpointer-arith)
2802        check_and_add_compiler_option(-Wpointer-sign)
2803        check_and_add_compiler_option(-Wshadow)
2804        check_and_add_compiler_option(-Wshorten-64-to-32)
2805        check_and_add_compiler_option(-Wsign-compare)
2806        check_and_add_compiler_option(-Wstrict-prototypes)
2807        check_and_add_compiler_option(-Wundef)
2808        check_and_add_compiler_option(-Wunreachable-code)
2809        check_and_add_compiler_option(-Wunused-but-set-parameter)
2810        check_and_add_compiler_option(-Wunused-but-set-variable)
2811        check_and_add_compiler_option(-Wunused-parameter)
2812        check_and_add_compiler_option(-Wused-but-marked-unused)
2813    endif()
2814endif()
2815
2816#
2817# Suppress some warnings we get with MSVC even without /Wall.
2818#
2819if(MSVC AND NOT ${CMAKE_C_COMPILER} MATCHES "clang*")
2820    #
2821    # Yes, we have some functions that never return but that
2822    # have a non-void return type.  That's because, on some
2823    # platforms, they *do* return values but, on other
2824    # platforms, including Windows, they just fail and
2825    # longjmp out by calling bpf_error().
2826    #
2827    check_and_add_compiler_option(-wd4646)
2828endif()
2829
2830file(GLOB PROJECT_SOURCE_LIST_H
2831    *.h
2832    pcap/*.h
2833)
2834
2835#
2836# Try to have the compiler default to hiding symbols, so that only
2837# symbols explicitly exported with PCAP_API will be visible outside
2838# (shared) libraries.
2839#
2840# Not necessary with MSVC, as that's the default.
2841#
2842# XXX - we don't use ADD_COMPILER_EXPORT_FLAGS, because, as of CMake
2843# 2.8.12.2, it doesn't know about Sun C/Oracle Studio, and, as of
2844# CMake 2.8.6, it only sets the C++ compiler flags, rather than
2845# allowing an arbitrary variable to be set with the "hide symbols
2846# not explicitly exported" flag.
2847#
2848if(NOT MSVC)
2849    if(CMAKE_C_COMPILER_ID MATCHES "SunPro")
2850        #
2851        # Sun C/Oracle Studio.
2852        #
2853        check_and_add_compiler_option(-xldscope=hidden)
2854    else()
2855        #
2856        # Try this for all other compilers; it's what GCC uses,
2857        # and a number of other compilers, such as Clang and Intel C,
2858        # use it as well.
2859        #
2860        check_and_add_compiler_option(-fvisibility=hidden)
2861    endif()
2862endif(NOT MSVC)
2863
2864#
2865# Extra compiler options for the build matrix scripts to request -Werror or
2866# its equivalent if required.  The CMake variable name cannot be CFLAGS
2867# because that is already used for a different purpose in CMake.  Example
2868# usage: cmake -DEXTRA_CFLAGS='-Wall -Wextra -Werror' ...
2869#
2870if(NOT "${EXTRA_CFLAGS}" STREQUAL "")
2871    # The meaning of EXTRA_CFLAGS is "use the exact specified options, or the
2872    # build risks failing to fail", not "try every specified option, omit those
2873    # that do not work and use the rest".  Thus use add_compile_options(), not
2874    # foreach()/check_and_add_compiler_option().  Another reason to do that is
2875    # that the effect lasts in testprogs/ and testprogs/fuzz/.
2876    string(REPLACE " " ";" _extra_cflags_list ${EXTRA_CFLAGS})
2877    add_compile_options(${_extra_cflags_list})
2878    message(STATUS "Added extra compile options (${EXTRA_CFLAGS})")
2879endif()
2880
2881#
2882# Flex/Lex and YACC/Berkeley YACC/Bison.
2883# From a mail message to the CMake mailing list by Andy Cedilnik of
2884# Kitware.
2885#
2886
2887#
2888# Try to find Flex, a Windows version of Flex, or Lex.
2889#
2890find_program(LEX_EXECUTABLE NAMES flex win_flex lex)
2891if(LEX_EXECUTABLE STREQUAL "LEX_EXECUTABLE-NOTFOUND")
2892    message(FATAL_ERROR "Neither flex nor win_flex nor lex was found.")
2893endif()
2894message(STATUS "Lexical analyzer generator: ${LEX_EXECUTABLE}")
2895
2896#
2897# Make sure {f}lex supports the -P, --header-file, and --nounput flags
2898# and supports processing our scanner.l.
2899#
2900if(WIN32)
2901    set(NULL_DEVICE "NUL:")
2902else()
2903    set(NULL_DEVICE "/dev/null")
2904endif()
2905execute_process(COMMAND ${LEX_EXECUTABLE} -P pcap_ --header-file=${NULL_DEVICE} --nounput -t ${pcap_SOURCE_DIR}/scanner.l
2906    OUTPUT_QUIET RESULT_VARIABLE EXIT_STATUS)
2907if(NOT EXIT_STATUS EQUAL 0)
2908    message(FATAL_ERROR "${LEX_EXECUTABLE} is insufficient to compile libpcap.
2909libpcap requires Flex 2.5.31 or later, or a compatible version of lex.
2910If a suitable version of Lex/Flex is available as a non-standard command
2911and/or not in the PATH, you can specify it using the LEX environment
2912variable. That said, on some systems the error can mean that Flex/Lex is
2913actually acceptable, but m4 is not. Likewise, if a suitable version of
2914m4 (such as GNU M4) is available but has not been detected, you can
2915specify it using the M4 environment variable.")
2916endif()
2917
2918add_custom_command(
2919    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/scanner.c ${CMAKE_CURRENT_BINARY_DIR}/scanner.h
2920    SOURCE ${pcap_SOURCE_DIR}/scanner.l
2921    COMMAND ${LEX_EXECUTABLE} -P pcap_ --header-file=scanner.h --nounput -o${CMAKE_CURRENT_BINARY_DIR}/scanner.c ${pcap_SOURCE_DIR}/scanner.l
2922    DEPENDS ${pcap_SOURCE_DIR}/scanner.l
2923)
2924
2925#
2926# Since scanner.c does not exist yet when cmake is run, mark
2927# it as generated.
2928#
2929# Since scanner.c includes grammar.h, mark that as a dependency.
2930#
2931set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/scanner.c PROPERTIES
2932    GENERATED TRUE
2933    OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/grammar.h
2934)
2935
2936#
2937# Add scanner.c to the list of sources.
2938#
2939#set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} ${CMAKE_CURRENT_BINARY_DIR}/scanner.c)
2940
2941#
2942# Try to find YACC or Bison.
2943#
2944find_program(YACC_EXECUTABLE NAMES bison win_bison byacc yacc)
2945if(YACC_EXECUTABLE STREQUAL "YACC_EXECUTABLE-NOTFOUND")
2946    message(FATAL_ERROR "Neither bison nor win_bison nor byacc nor yacc was found.")
2947endif()
2948
2949if(YACC_EXECUTABLE MATCHES "byacc" OR YACC_EXECUTABLE MATCHES "yacc")
2950    #
2951    # Make sure this is Berkeley YACC, not AT&T YACC;
2952    # the latter doesn't support reentrant parsers.
2953    # Run it with "-V"; that succeeds and reports the
2954    # version number with Berkeley YACC, but will
2955    # (probably) fail with various vendor flavors
2956    # of AT&T YACC.
2957    #
2958    # Hopefully this also eliminates any versions
2959    # of Berkeley YACC that don't support reentrant
2960    # parsers, if there are any.
2961    #
2962    execute_process(COMMAND ${YACC_EXECUTABLE} -V OUTPUT_QUIET
2963        RESULT_VARIABLE EXIT_STATUS)
2964    if(NOT EXIT_STATUS EQUAL 0)
2965        message(FATAL_ERROR "${YACC_EXECUTABLE} is insufficient to compile libpcap.
2966libpcap requires Bison, a newer version of Berkeley YACC with support
2967for reentrant parsers, or another YACC compatible with them.")
2968    endif()
2969    #
2970    # Berkeley YACC doesn't support "%define api.pure", so use
2971    # "%pure-parser".
2972    #
2973    set(REENTRANT_PARSER "%pure-parser")
2974else()
2975    #
2976    # Bison prior to 2.4(.1) doesn't support "%define api.pure", so use
2977    # "%pure-parser".
2978    #
2979    execute_process(COMMAND ${YACC_EXECUTABLE} -V OUTPUT_VARIABLE bison_full_version)
2980    string(REGEX MATCH "[1-9][0-9]*[.][0-9]+" bison_major_minor ${bison_full_version})
2981    if (bison_major_minor VERSION_LESS "2.4")
2982        set(REENTRANT_PARSER "%pure-parser")
2983    else()
2984        set(REENTRANT_PARSER "%define api.pure")
2985    endif()
2986endif()
2987
2988message(STATUS "Parser generator: ${YACC_EXECUTABLE}")
2989
2990#
2991# Create custom command for the scanner.
2992#
2993add_custom_command(
2994    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/grammar.c ${CMAKE_CURRENT_BINARY_DIR}/grammar.h
2995    SOURCE ${pcap_BINARY_DIR}/grammar.y
2996    COMMAND ${YACC_EXECUTABLE} -p pcap_ -o ${CMAKE_CURRENT_BINARY_DIR}/grammar.c -d ${pcap_BINARY_DIR}/grammar.y
2997    DEPENDS ${pcap_BINARY_DIR}/grammar.y
2998)
2999
3000#
3001# Since grammar.c does not exists yet when cmake is run, mark
3002# it as generated.
3003#
3004set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/grammar.c PROPERTIES
3005    GENERATED TRUE
3006    OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/scanner.h
3007)
3008
3009#
3010# Add grammar.c to the list of sources.
3011#
3012#set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} ${CMAKE_CURRENT_BINARY_DIR}/grammar.c)
3013
3014#
3015# Assume, by default, no support for shared libraries and V7/BSD
3016# convention for man pages (devices in section 4, file formats in
3017# section 5, miscellaneous info in section 7, administrative commands
3018# and daemons in section 8).  Individual cases can override this.
3019# Individual cases can override this.
3020#
3021set(MAN_DEVICES 4)
3022set(MAN_FILE_FORMATS 5)
3023set(MAN_MISC_INFO 7)
3024set(MAN_ADMIN_COMMANDS 8)
3025if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
3026    # Workaround to enable certain features
3027    set(_SUN TRUE)
3028    if(PCAP_TYPE STREQUAL "bpf")
3029        #
3030        # If we're using BPF, we need libodm and libcfg, as
3031        # we use them to load the BPF module.
3032        #
3033        set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} odm cfg)
3034        set(LIBS "${LIBS} -lodm -lcfg")
3035        set(LIBS_STATIC "${LIBS_STATIC} -lodm -lcfg")
3036        set(LIBS_PRIVATE "${LIBS_PRIVATE} -lodm -lcfg")
3037    endif()
3038elseif(CMAKE_SYSTEM_NAME STREQUAL "HP-UX")
3039    if(CMAKE_SYSTEM_VERSION MATCHES "[A-Z.]*9\.[0-9]*")
3040        #
3041        # HP-UX 9.x.
3042        #
3043        set(HAVE_HPUX9 TRUE)
3044    elseif(CMAKE_SYSTEM_VERSION MATCHES "[A-Z.]*10\.0")
3045        #
3046        # HP-UX 10.0.
3047        #
3048    elseif(CMAKE_SYSTEM_VERSION MATCHES "[A-Z.]*10\.1")
3049        #
3050        # HP-UX 10.1.
3051        #
3052    else()
3053        #
3054        # HP-UX 10.20 and later.
3055        #
3056        set(HAVE_HPUX10_20_OR_LATER TRUE)
3057    endif()
3058
3059    #
3060    # Use System V conventions for man pages.
3061    #
3062    set(MAN_ADMIN_COMMANDS 1m)
3063    set(MAN_FILE_FORMATS 4)
3064    set(MAN_MISC_INFO 5)
3065elseif(CMAKE_SYSTEM_NAME STREQUAL "IRIX" OR CMAKE_SYSTEM_NAME STREQUAL "IRIX64")
3066    #
3067    # Use IRIX conventions for man pages; they're the same as the
3068    # System V conventions, except that they use section 8 for
3069    # administrative commands and daemons.
3070    #
3071    set(MAN_FILE_FORMATS 4)
3072    set(MAN_MISC_INFO 5)
3073elseif(CMAKE_SYSTEM_NAME STREQUAL "OSF1")
3074    #
3075    # DEC OSF/1, a/k/a Digital UNIX, a/k/a Tru64 UNIX.
3076    # Use Tru64 UNIX conventions for man pages; they're the same as the
3077    # System V conventions except that they use section 8 for
3078    # administrative commands and daemons.
3079    #
3080    set(MAN_FILE_FORMATS 4)
3081    set(MAN_MISC_INFO 5)
3082    set(MAN_DEVICES 7)
3083elseif(CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND CMAKE_SYSTEM_VERSION MATCHES "5[.][0-9.]*")
3084    #
3085    # SunOS 5.x.
3086    #
3087    set(HAVE_SOLARIS TRUE)
3088    #
3089    # Make sure errno is thread-safe, in case we're called in
3090    # a multithreaded program.  We don't guarantee that two
3091    # threads can use the *same* pcap_t safely, but the
3092    # current version does guarantee that you can use different
3093    # pcap_t's in different threads, and even that pcap_compile()
3094    # is thread-safe (it wasn't thread-safe in some older versions).
3095    #
3096    add_definitions(-D_TS_ERRNO)
3097
3098    if(CMAKE_SYSTEM_VERSION STREQUAL "5.12")
3099    else()
3100        #
3101        # Use System V conventions for man pages.
3102        #
3103        set(MAN_ADMIN_COMMANDS 1m)
3104        set(MAN_FILE_FORMATS 4)
3105        set(MAN_MISC_INFO 5)
3106        set(MAN_DEVICES 7D)
3107    endif()
3108elseif(CMAKE_SYSTEM_NAME STREQUAL "Haiku")
3109    #
3110    # Haiku needs _BSD_SOURCE for the _IO* macros because it doesn't use them.
3111    #
3112    add_definitions(-D_BSD_SOURCE)
3113endif()
3114
3115source_group("Source Files" FILES ${PROJECT_SOURCE_LIST_C})
3116source_group("Header Files" FILES ${PROJECT_SOURCE_LIST_H})
3117
3118if(WIN32)
3119    #
3120    # Add pcap-dll.rc to the list of sources.
3121    #
3122    set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} ${pcap_SOURCE_DIR}/pcap-dll.rc)
3123endif(WIN32)
3124
3125#
3126# Add subdirectories after we've set various variables, so they pick up
3127# pick up those variables.
3128#
3129if(ENABLE_REMOTE)
3130    add_subdirectory(rpcapd)
3131endif(ENABLE_REMOTE)
3132add_subdirectory(testprogs)
3133
3134######################################
3135# Register targets
3136######################################
3137
3138#
3139# Special target to serialize the building of the generated source.
3140#
3141# See
3142#
3143#  https://public.kitware.com/pipermail/cmake/2013-August/055510.html
3144#
3145add_custom_target(SerializeTarget
3146    DEPENDS
3147    ${CMAKE_CURRENT_BINARY_DIR}/grammar.c
3148    ${CMAKE_CURRENT_BINARY_DIR}/scanner.c
3149)
3150
3151set_source_files_properties(${PROJECT_EXTERNAL_OBJECT_LIST} PROPERTIES
3152    EXTERNAL_OBJECT TRUE)
3153
3154if(BUILD_SHARED_LIBS)
3155    add_library(${LIBRARY_NAME} SHARED
3156        ${PROJECT_SOURCE_LIST_C}
3157        ${CMAKE_CURRENT_BINARY_DIR}/grammar.c
3158        ${CMAKE_CURRENT_BINARY_DIR}/scanner.c
3159        ${PROJECT_EXTERNAL_OBJECT_LIST}
3160    )
3161    target_include_directories(${LIBRARY_NAME} PUBLIC
3162        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
3163        $<INSTALL_INTERFACE:include>
3164    )
3165    add_dependencies(${LIBRARY_NAME} SerializeTarget)
3166    set_target_properties(${LIBRARY_NAME} PROPERTIES
3167        COMPILE_DEFINITIONS BUILDING_PCAP)
3168    #
3169    # No matter what the library is called - it might be called "wpcap"
3170    # in a Windows build - the symbol to define to indicate that we're
3171    # building the library, rather than a program using the library,
3172    # and thus that we're exporting functions defined in our public
3173    # header files, rather than importing those functions, is
3174    # pcap_EXPORTS.
3175    #
3176    set_target_properties(${LIBRARY_NAME} PROPERTIES
3177        DEFINE_SYMBOL pcap_EXPORTS)
3178    if(NOT "${LINKER_FLAGS}" STREQUAL "")
3179        set_target_properties(${LIBRARY_NAME} PROPERTIES
3180            LINK_FLAGS "${LINKER_FLAGS}")
3181    endif()
3182endif(BUILD_SHARED_LIBS)
3183
3184add_library(${LIBRARY_NAME}_static STATIC
3185    ${PROJECT_SOURCE_LIST_C}
3186    ${CMAKE_CURRENT_BINARY_DIR}/grammar.c
3187    ${CMAKE_CURRENT_BINARY_DIR}/scanner.c
3188    ${PROJECT_EXTERNAL_OBJECT_LIST}
3189)
3190target_include_directories(${LIBRARY_NAME}_static PUBLIC
3191    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
3192    $<INSTALL_INTERFACE:include>
3193)
3194add_dependencies(${LIBRARY_NAME}_static SerializeTarget)
3195set_target_properties(${LIBRARY_NAME}_static PROPERTIES
3196    COMPILE_DEFINITIONS BUILDING_PCAP)
3197
3198if(WIN32)
3199    if(BUILD_SHARED_LIBS)
3200        set_target_properties(${LIBRARY_NAME} PROPERTIES
3201            VERSION ${PACKAGE_VERSION_NOSUFFIX} # only MAJOR and MINOR are needed
3202        )
3203    endif(BUILD_SHARED_LIBS)
3204    if(MSVC)
3205        # XXX For DLLs, the TARGET_PDB_FILE generator expression can be used to locate
3206        # its PDB file's output directory for installation.
3207        # cmake doesn't offer a generator expression for PDB files generated by the
3208        # compiler (static libraries).
3209        # So instead of considering any possible output there is (there are many),
3210        # this will search for the PDB file in the compiler's initial output directory,
3211        # which is always ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles\wpcap_static.dir
3212        # regardless of architecture, build generator etc.
3213        # Quite hackish indeed.
3214        set(CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${LIBRARY_NAME}_static>)
3215        set_target_properties(${LIBRARY_NAME}_static PROPERTIES
3216            COMPILE_PDB_NAME ${LIBRARY_NAME}_static
3217            OUTPUT_NAME "${LIBRARY_NAME}_static"
3218        )
3219    elseif(MINGW)
3220        #
3221        # For compatibility, build the shared library without the "lib" prefix on
3222        # MinGW as well.
3223        #
3224        set_target_properties(${LIBRARY_NAME} PROPERTIES
3225            PREFIX ""
3226            OUTPUT_NAME "${LIBRARY_NAME}"
3227        )
3228        set_target_properties(${LIBRARY_NAME}_static PROPERTIES
3229            OUTPUT_NAME "${LIBRARY_NAME}"
3230        )
3231    endif()
3232else(WIN32) # UN*X
3233    if(BUILD_SHARED_LIBS)
3234        if(APPLE)
3235            set_target_properties(${LIBRARY_NAME} PROPERTIES
3236                VERSION ${PACKAGE_VERSION}
3237                SOVERSION A
3238            )
3239        else(APPLE)
3240            set_target_properties(${LIBRARY_NAME} PROPERTIES
3241                VERSION ${PACKAGE_VERSION}
3242                SOVERSION ${PACKAGE_VERSION_MAJOR}
3243            )
3244        endif(APPLE)
3245    endif(BUILD_SHARED_LIBS)
3246    set_target_properties(${LIBRARY_NAME}_static PROPERTIES
3247        OUTPUT_NAME "${LIBRARY_NAME}"
3248    )
3249endif(WIN32)
3250
3251if(BUILD_SHARED_LIBS)
3252    if(NOT C_ADDITIONAL_FLAGS STREQUAL "")
3253        set_target_properties(${LIBRARY_NAME} PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS})
3254    endif()
3255
3256    #
3257    # If this is macOS and we've picked the default architectures on
3258    # which to build, build the library on them.
3259    #
3260    if(APPLE AND "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "")
3261        set_target_properties(${LIBRARY_NAME} PROPERTIES
3262            OSX_ARCHITECTURES "${OSX_LIBRARY_ARCHITECTURES}")
3263    endif()
3264    target_link_libraries(${LIBRARY_NAME} ${PCAP_LINK_LIBRARIES})
3265endif(BUILD_SHARED_LIBS)
3266
3267if(NOT C_ADDITIONAL_FLAGS STREQUAL "")
3268    set_target_properties(${LIBRARY_NAME}_static PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS})
3269endif()
3270
3271#
3272# If this is macOS and we've picked the default architectures on
3273# which to build, build the library on them.
3274#
3275if(APPLE AND "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "")
3276    set_target_properties(${LIBRARY_NAME}_static PROPERTIES
3277        OSX_ARCHITECTURES "${OSX_LIBRARY_ARCHITECTURES}")
3278endif()
3279
3280######################################
3281# Write out the config.h file
3282######################################
3283
3284configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmakeconfig.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
3285
3286######################################
3287# Write out the grammar.y file
3288######################################
3289
3290configure_file(${CMAKE_CURRENT_SOURCE_DIR}/grammar.y.in ${CMAKE_CURRENT_BINARY_DIR}/grammar.y @ONLY)
3291
3292######################################
3293# Install pcap library, include files, and man pages
3294######################################
3295
3296#
3297# "Define GNU standard installation directories", which actually
3298# are also defined, to some degree, by autotools, and at least
3299# some of which are general UN*X conventions.
3300#
3301include(GNUInstallDirs)
3302
3303set(LIBRARY_NAME_STATIC ${LIBRARY_NAME}_static)
3304
3305function(install_manpage_symlink SOURCE TARGET MANDIR)
3306    if(MINGW)
3307        #
3308        # If we haven't found an ln executable with MinGW, we don't try
3309        # generating and installing the man pages, so if we get here,
3310        # we've found that executable.
3311        set(LINK_COMMAND "\"${LINK_EXECUTABLE}\" \"-s\" \"${SOURCE}\" \"${TARGET}\"")
3312    else(MINGW)
3313        set(LINK_COMMAND "\"${CMAKE_COMMAND}\" \"-E\" \"create_symlink\" \"${SOURCE}\" \"${TARGET}\"")
3314    endif(MINGW)
3315
3316    install(CODE "
3317         if(NOT ${CMAKE_INSTALL_MESSAGE} STREQUAL \"NEVER\")
3318             message(STATUS \"Symlinking: \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${MANDIR}/${SOURCE} to ${TARGET}\")
3319         endif()
3320         execute_process(
3321            COMMAND \"${CMAKE_COMMAND}\" \"-E\" \"remove\" \"${TARGET}\"
3322            WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${MANDIR}
3323          )
3324         execute_process(
3325            COMMAND ${LINK_COMMAND}
3326            WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${MANDIR}
3327            RESULT_VARIABLE EXIT_STATUS
3328          )
3329          if(NOT EXIT_STATUS EQUAL 0)
3330              message(FATAL_ERROR \"Could not create symbolic link from \${CMAKE_INSTALL_PREFIX}/${MANDIR}/${SOURCE} to ${TARGET}\")
3331          endif()
3332          set(CMAKE_INSTALL_MANIFEST_FILES \${CMAKE_INSTALL_MANIFEST_FILES} \${CMAKE_INSTALL_PREFIX}/${MANDIR}/${TARGET})")
3333endfunction(install_manpage_symlink)
3334
3335set(MAN1_NOEXPAND pcap-config.1)
3336set(MAN3PCAP_EXPAND
3337    pcap.3pcap.in
3338    pcap_compile.3pcap.in
3339    pcap_datalink.3pcap.in
3340    pcap_dump_open.3pcap.in
3341    pcap_get_tstamp_precision.3pcap.in
3342    pcap_list_datalinks.3pcap.in
3343    pcap_list_tstamp_types.3pcap.in
3344    pcap_open_dead.3pcap.in
3345    pcap_open_offline.3pcap.in
3346    pcap_set_immediate_mode.3pcap.in
3347    pcap_set_tstamp_precision.3pcap.in
3348    pcap_set_tstamp_type.3pcap.in
3349)
3350set(MAN3PCAP_NOEXPAND
3351    pcap_activate.3pcap
3352    pcap_breakloop.3pcap
3353    pcap_can_set_rfmon.3pcap
3354    pcap_close.3pcap
3355    pcap_create.3pcap
3356    pcap_datalink_name_to_val.3pcap
3357    pcap_datalink_val_to_name.3pcap
3358    pcap_dump.3pcap
3359    pcap_dump_close.3pcap
3360    pcap_dump_file.3pcap
3361    pcap_dump_flush.3pcap
3362    pcap_dump_ftell.3pcap
3363    pcap_file.3pcap
3364    pcap_fileno.3pcap
3365    pcap_findalldevs.3pcap
3366    pcap_freecode.3pcap
3367    pcap_get_required_select_timeout.3pcap
3368    pcap_get_selectable_fd.3pcap
3369    pcap_geterr.3pcap
3370    pcap_init.3pcap
3371    pcap_inject.3pcap
3372    pcap_is_swapped.3pcap
3373    pcap_lib_version.3pcap
3374    pcap_lookupdev.3pcap
3375    pcap_lookupnet.3pcap
3376    pcap_loop.3pcap
3377    pcap_major_version.3pcap
3378    pcap_next_ex.3pcap
3379    pcap_offline_filter.3pcap
3380    pcap_open_live.3pcap
3381    pcap_set_buffer_size.3pcap
3382    pcap_set_datalink.3pcap
3383    pcap_set_promisc.3pcap
3384    pcap_set_protocol_linux.3pcap
3385    pcap_set_rfmon.3pcap
3386    pcap_set_snaplen.3pcap
3387    pcap_set_timeout.3pcap
3388    pcap_setdirection.3pcap
3389    pcap_setfilter.3pcap
3390    pcap_setnonblock.3pcap
3391    pcap_snapshot.3pcap
3392    pcap_stats.3pcap
3393    pcap_statustostr.3pcap
3394    pcap_strerror.3pcap
3395    pcap_tstamp_type_name_to_val.3pcap
3396    pcap_tstamp_type_val_to_name.3pcap
3397)
3398set(MANFILE_EXPAND
3399    pcap-savefile.manfile.in
3400)
3401set(MANMISC_EXPAND
3402    pcap-filter.manmisc.in
3403    pcap-linktype.manmisc.in
3404    pcap-tstamp.manmisc.in
3405)
3406
3407if(BUILD_SHARED_LIBS)
3408    set(LIBRARIES_TO_INSTALL "${LIBRARY_NAME}" "${LIBRARY_NAME_STATIC}")
3409else(BUILD_SHARED_LIBS)
3410    set(LIBRARIES_TO_INSTALL "${LIBRARY_NAME_STATIC}")
3411endif(BUILD_SHARED_LIBS)
3412
3413if(WIN32 OR CYGWIN OR MSYS)
3414    #
3415    # XXX - according to the CMake documentation, WIN32 is set if
3416    # the target is Windows; would there ever be a case where
3417    # CYGWIN or MSYS are set but WIN32 *isn't* set?
3418    #
3419    if(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
3420        #
3421        # Install 64-bit code built with MSVC in the x64 subdirectories,
3422        # as that's where it expects it to be.
3423        #
3424        install(TARGETS ${LIBRARIES_TO_INSTALL}
3425                RUNTIME DESTINATION bin/x64
3426                LIBRARY DESTINATION lib/x64
3427                ARCHIVE DESTINATION lib/x64)
3428        if(NOT MINGW)
3429            install(FILES $<TARGET_FILE_DIR:${LIBRARY_NAME_STATIC}>/${LIBRARY_NAME_STATIC}.pdb
3430                    DESTINATION bin/x64 OPTIONAL)
3431            if(BUILD_SHARED_LIBS)
3432                install(FILES $<TARGET_PDB_FILE:${LIBRARY_NAME}>
3433                        DESTINATION bin/x64 OPTIONAL)
3434            endif(BUILD_SHARED_LIBS)
3435        endif(NOT MINGW)
3436    else(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
3437        #
3438        # Install 32-bit code, and 64-bit code not built with MSVC
3439        # in the top-level directories, as those are where they
3440        # expect it to be.
3441        #
3442        install(TARGETS ${LIBRARIES_TO_INSTALL}
3443                RUNTIME DESTINATION bin
3444                LIBRARY DESTINATION lib
3445                ARCHIVE DESTINATION lib)
3446        if(MSVC)
3447            install(FILES $<TARGET_FILE_DIR:${LIBRARY_NAME_STATIC}>/${LIBRARY_NAME_STATIC}.pdb
3448                    DESTINATION bin OPTIONAL)
3449            if(BUILD_SHARED_LIBS)
3450                install(FILES $<TARGET_PDB_FILE:${LIBRARY_NAME}>
3451                        DESTINATION bin OPTIONAL)
3452            endif(BUILD_SHARED_LIBS)
3453        endif(MSVC)
3454    endif(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
3455else(WIN32 OR CYGWIN OR MSYS)
3456    install(TARGETS ${LIBRARIES_TO_INSTALL} DESTINATION ${CMAKE_INSTALL_LIBDIR})
3457endif(WIN32 OR CYGWIN OR MSYS)
3458
3459install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/pcap/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pcap)
3460install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/pcap.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
3461install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/pcap-bpf.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
3462install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/pcap-namedb.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
3463
3464# On UN*X, and on Windows when not using MSVC, generate libpcap.pc and
3465# pcap-config and process man pages and arrange that they be installed.
3466if(NOT MSVC)
3467    set(prefix ${CMAKE_INSTALL_PREFIX})
3468    set(exec_prefix "\${prefix}")
3469    set(includedir "\${prefix}/include")
3470    set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
3471
3472    #
3473    # If this is a platform where we need to have the .pc file and
3474    # pcap-config script supply an rpath option to specify the directory
3475    # in which the libpcap shared library is installed, and the install
3476    # prefix /usr (meaning we're not installing a system library),
3477    # provide the rpath option.
3478    #
3479    # (We must check CMAKE_INSTALL_PREFIX, as the library directory
3480    # isn't  necessarily /usr/lib in this case - for example, Linux
3481    # distributions for 64-bit platforms that also provide support for
3482    # binaries for a 32-bit version of the platform may put the 64-bit
3483    # libraries, the 32-bit libraries, or both in directories other than
3484    # /usr/lib.)
3485    #
3486    # In AIX, do we have to do this?
3487    #
3488    # In Darwin-based OSes, the full paths of the shared libraries with
3489    # which the program was linked are stored in the executable, so we
3490    # don't need to provide an rpath option.
3491    #
3492    # With the HP-UX linker, directories specified with -L are, by
3493    # default, added to the run-time search path, so we don't need to
3494    # supply them.
3495    #
3496    # For Tru64 UNIX, "-rpath" works with DEC's^WCompaq's^WHP's C
3497    # compiler for Alpha, but isn't documented as working with GCC, and
3498    # no GCC-compatible option is documented as working with the DEC
3499    # compiler.  If anybody needs this on Tru64/Alpha, they're welcome
3500    # to figure out a way to make it work.
3501    #
3502    # This must *not* depend on the compiler, as, on platforms where
3503    # there's a GCC-compatible compiler and a vendor compiler, we need
3504    # to work with both.
3505    #
3506    if(NOT CMAKE_INSTALL_PREFIX STREQUAL "/usr")
3507        if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
3508           CMAKE_SYSTEM_NAME STREQUAL "NetBSD" OR
3509           CMAKE_SYSTEM_NAME STREQUAL "OpenBSD" OR
3510           CMAKE_SYSTEM_NAME STREQUAL "DragonFly BSD" OR
3511           CMAKE_SYSTEM_NAME STREQUAL "Linux")
3512            #
3513            # Platforms where the "native" C compiler is GCC or accepts
3514            # compatible command-line arguments, and the "native" linker
3515            # is the GNU linker or accepts compatible command-line
3516            # arguments.
3517            #
3518            set(RPATH "-Wl,-rpath,\${libdir}")
3519        elseif(CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND CMAKE_SYSTEM_VERSION MATCHES "5[.][0-9.]*")
3520            #
3521            # SunOS 5.x.
3522            #
3523            # Sun/Oracle's linker, the GNU linker, and GNU-compatible
3524            # linkers all support -R.
3525            #
3526            set(RPATH "-Wl,-R,\${libdir}")
3527        else()
3528            #
3529            # No option needed to set the RPATH.
3530            #
3531            set(RPATH "")
3532        endif()
3533    endif()
3534    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pcap-config.in ${CMAKE_CURRENT_BINARY_DIR}/pcap-config @ONLY)
3535    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpcap.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libpcap.pc @ONLY)
3536    install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/pcap-config DESTINATION bin)
3537    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpcap.pc DESTINATION lib/pkgconfig)
3538
3539    #
3540    # Man pages.
3541    #
3542    # For each section of the manual for which we have man pages
3543    # that require macro expansion, do the expansion.
3544    #
3545    # If this is MinGW, maybe we have a UN*X-style ln command and
3546    # maybe we don't.  (No, we do *NOT* require MSYS!)  If we don't
3547    # have it, don't do the man pages.
3548    #
3549    if(MINGW)
3550        find_program(LINK_EXECUTABLE ln)
3551    endif(MINGW)
3552    if(UNIX OR (MINGW AND LINK_EXECUTABLE))
3553        set(MAN1 "")
3554        foreach(MANPAGE ${MAN1_NOEXPAND})
3555            set(MAN1 ${MAN1} ${CMAKE_CURRENT_SOURCE_DIR}/${MANPAGE})
3556        endforeach(MANPAGE)
3557        install(FILES ${MAN1} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
3558
3559        set(MAN3PCAP "")
3560        foreach(MANPAGE ${MAN3PCAP_NOEXPAND})
3561            set(MAN3PCAP ${MAN3PCAP} ${CMAKE_CURRENT_SOURCE_DIR}/${MANPAGE})
3562        endforeach(MANPAGE)
3563        foreach(TEMPLATE_MANPAGE ${MAN3PCAP_EXPAND})
3564            string(REPLACE ".in" "" MANPAGE ${TEMPLATE_MANPAGE})
3565            configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY)
3566            set(MAN3PCAP ${MAN3PCAP} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
3567        endforeach(TEMPLATE_MANPAGE)
3568        install(FILES ${MAN3PCAP} DESTINATION ${CMAKE_INSTALL_MANDIR}/man3)
3569        install_manpage_symlink(pcap_datalink_val_to_name.3pcap pcap_datalink_val_to_description.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
3570        install_manpage_symlink(pcap_datalink_val_to_name.3pcap pcap_datalink_val_to_description_or_dlt.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
3571        install_manpage_symlink(pcap_dump_open.3pcap pcap_dump_fopen.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
3572        install_manpage_symlink(pcap_findalldevs.3pcap pcap_freealldevs.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
3573        install_manpage_symlink(pcap_geterr.3pcap pcap_perror.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
3574        install_manpage_symlink(pcap_inject.3pcap pcap_sendpacket.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
3575        install_manpage_symlink(pcap_list_datalinks.3pcap pcap_free_datalinks.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
3576        install_manpage_symlink(pcap_list_tstamp_types.3pcap pcap_free_tstamp_types.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
3577        install_manpage_symlink(pcap_loop.3pcap pcap_dispatch.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
3578        install_manpage_symlink(pcap_major_version.3pcap pcap_minor_version.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
3579        install_manpage_symlink(pcap_next_ex.3pcap pcap_next.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
3580        install_manpage_symlink(pcap_open_dead.3pcap pcap_open_dead_with_tstamp_precision.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
3581        install_manpage_symlink(pcap_open_offline.3pcap pcap_open_offline_with_tstamp_precision.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
3582        install_manpage_symlink(pcap_open_offline.3pcap pcap_fopen_offline.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
3583        install_manpage_symlink(pcap_open_offline.3pcap pcap_fopen_offline_with_tstamp_precision.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
3584        install_manpage_symlink(pcap_tstamp_type_val_to_name.3pcap pcap_tstamp_type_val_to_description.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
3585        install_manpage_symlink(pcap_setnonblock.3pcap pcap_getnonblock.3pcap ${CMAKE_INSTALL_MANDIR}/man3)
3586
3587        set(MANFILE "")
3588        foreach(TEMPLATE_MANPAGE ${MANFILE_EXPAND})
3589            string(REPLACE ".manfile.in" ".${MAN_FILE_FORMATS}" MANPAGE ${TEMPLATE_MANPAGE})
3590            configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY)
3591            set(MANFILE ${MANFILE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
3592        endforeach(TEMPLATE_MANPAGE)
3593        install(FILES ${MANFILE} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${MAN_FILE_FORMATS})
3594
3595        set(MANMISC "")
3596        foreach(TEMPLATE_MANPAGE ${MANMISC_EXPAND})
3597            string(REPLACE ".manmisc.in" ".${MAN_MISC_INFO}" MANPAGE ${TEMPLATE_MANPAGE})
3598            configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY)
3599            set(MANMISC ${MANMISC} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
3600        endforeach(TEMPLATE_MANPAGE)
3601        install(FILES ${MANMISC} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${MAN_MISC_INFO})
3602    endif(UNIX OR (MINGW AND LINK_EXECUTABLE))
3603endif(NOT MSVC)
3604
3605# uninstall target
3606configure_file(
3607    "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
3608    "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
3609    IMMEDIATE @ONLY)
3610
3611add_custom_target(uninstall
3612    COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
3613