From 3a80b79497279a95ed10e7d51078862cb0302ca1 Mon Sep 17 00:00:00 2001 From: Elad Solomon Date: Sun, 27 Jun 2021 17:12:56 +0000 Subject: [PATCH] Compile Zeek with MSVC Allow Zeek to be embedded in another project --- .gitignore | 7 + CMakeLists.txt | 128 ++++++++++++++++-- ci/build.ps1 | 33 +++++ ci/windows/Dockerfile | 56 ++++++++ ci/windows/conanfile_windows.txt | 9 ++ ci/windows/default | 12 ++ src/CMakeLists.txt | 103 ++++++++++---- src/DebugCmdInfoConstants.in | 2 +- src/DebugLogger.h | 22 +-- src/Flare.cc | 74 +++++++++- src/Flare.h | 15 +- src/Hash.cc | 2 +- src/Hash.h | 1 + src/IP.cc | 18 +-- src/IP.h | 2 + src/Obj.cc | 4 + src/OpaqueVal.h | 4 + src/Options.cc | 6 +- src/PolicyFile.cc | 5 +- src/RunState.cc | 2 + src/SerializationFormat.cc | 13 +- src/SerializationFormat.h | 3 + src/analyzer/Manager.h | 6 +- .../analyzer/extract/functions.bif | 2 +- src/file_analysis/analyzer/x509/X509Common.cc | 2 +- .../x509-signed_certificate_timestamp.pac | 2 +- src/fuzzers/FuzzBuffer.cc | 4 + src/fuzzers/packet-fuzzer.cc | 4 + src/iosource/Packet.h | 2 + src/iosource/pcap/Source.cc | 2 + src/main.cc | 9 +- src/net_util.h | 2 + src/packet_analysis/protocol/arp/ARP.cc | 8 +- src/plugin/Manager.cc | 95 +++++++++---- src/plugin/Manager.h | 2 +- src/plugin/Plugin.cc | 4 + src/plugin/Plugin.h | 28 ++++ src/script_opt/ZAM/Stmt.cc | 4 + src/supervisor/Supervisor.cc | 20 ++- src/supervisor/Supervisor.h | 4 + src/telemetry/Counter.h | 12 +- src/telemetry/Gauge.h | 12 +- src/telemetry/Histogram.h | 12 +- src/threading/BasicThread.cc | 10 +- src/threading/BasicThread.h | 1 + src/util.cc | 54 ++++++-- src/util.h | 31 ++++- src/zeek | 1 - src/zeek-setup.cc | 9 ++ src/zeek.bif | 4 +- src/zeekygen/Target.cc | 5 + zeek-config.h.in | 3 +- zeek-path-dev.in | 2 +- 53 files changed, 724 insertions(+), 153 deletions(-) create mode 100644 ci/build.ps1 create mode 100644 ci/windows/Dockerfile create mode 100644 ci/windows/conanfile_windows.txt create mode 100644 ci/windows/default mode change 120000 => 100644 src/file_analysis/analyzer/x509/x509-signed_certificate_timestamp.pac delete mode 120000 src/zeek diff --git a/.gitignore b/.gitignore index 47d737f573..5a24d31e0f 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,10 @@ cmake-build-* # clangd .cache + +out/ + +# Visual Studio +.vs/ +.vscode/ +CMakeSettings.json diff --git a/CMakeLists.txt b/CMakeLists.txt index a2061b010c..f7c147d488 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,9 +2,86 @@ # auxil/zeek-aux/plugin-support/skeleton/CMakeLists.txt cmake_minimum_required(VERSION 3.15.0 FATAL_ERROR) +if ( WIN32 ) + # Enable usage of CMAKE_MSVC_RUNTIME_LIBRARY variable + cmake_policy(SET CMP0091 NEW) +endif() + project(Zeek C CXX) -include(GNUInstallDirs) +option(ZEEK_STANDALONE "Is Zeek compiled stand-alone or embedded in a parent project." ON) + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR}) +list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR}) + +# Windows: Configure runtime and dependencies +if ( MSVC ) + cmake_policy(SET CMP0091 NEW) + if (CMAKE_BUILD_TYPE STREQUAL "Debug") + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDebug") + set(CMAKE_MSVC_RUNTIME_LIBRARY_FLAG "MTd") + else () + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded") + set(CMAKE_MSVC_RUNTIME_LIBRARY_FLAG "MT") + endif () + set(OPENSSL_USE_STATIC_LIBS true) + set(OPENSSL_MSVC_STATIC_RT true) + + if ( ZEEK_STANDALONE ) + include(${CMAKE_SOURCE_DIR}/cmake/conan.cmake) + + conan_cmake_configure(REQUIRES + zlib/1.2.11 + openssl/1.1.1i + winflexbison/2.5.24 + npcap-wpcap/1.31 + GENERATORS cmake_find_package) + + # Install packages from conanfile + conan_cmake_install(PATH_OR_REFERENCE ${CMAKE_SOURCE_DIR}/ci/windows/conanfile_windows.txt + BUILD missing + SETTINGS ${settings}) + endif() + + # Set LibPCAP to point to wpcap binaries. + find_package(npcap-wpcap) + set(PCAP_ROOT_DIR "${npcap-wpcap_LIB_DIRS}/../") + set(PCAP_INCLUDE_DIR ${npcap-wpcap_INCLUDES}) + set(PCAP_LIBRARY ${npcap-wpcap_LIBS}) + set(LIBPCAP_PCAP_COMPILE_NOPCAP_HAS_ERROR_PARAMETER false) + + # Set ZLib to point at the right variable. + find_package(ZLIB) + set(ZLIB_LIBRARY ${ZLIB_LIBRARIES}) + + add_subdirectory(auxil/libunistd) + set(UNISTD_INCLUDES ${CMAKE_SOURCE_DIR}/auxil/libunistd/unistd ${CMAKE_SOURCE_DIR}/auxil/libunistd/regex) + include_directories(BEFORE ${UNISTD_INCLUDES}) + # Required for `check_include_files` to operate correctly + list(APPEND CMAKE_REQUIRED_INCLUDES ${UNISTD_INCLUDES}) + list(APPEND zeekdeps libunistd libregex) + + # Set CMAKE flags for supported windows build. + set(DISABLE_PYTHON_BINDINGS true) + set(BROKER_DISABLE_TESTS true) + set(BROKER_DISABLE_DOC_EXAMPLES true) +else () + include(GNUInstallDirs) +endif () + +set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) +if ( CMAKE_SYSTEM_NAME STREQUAL Linux ) + set(CMAKE_DL_LIBS pthread ${CMAKE_DL_LIBS}) +endif () + +if ( NOT CMAKE_INSTALL_LIBDIR ) + # Currently, some sub-projects may use GNUInstallDirs.cmake to choose the + # library install dir, while others just default to "lib". For sake of + # consistency, this just overrides the former to always use "lib" in case + # it would have chosen something else, like "lib64", but a thing for the + # future may be to standardize all sub-projects to use GNUInstallDirs. + set(CMAKE_INSTALL_LIBDIR lib) +endif () include(cmake/CommonCMakeConfig.cmake) include(cmake/FindClangTidy.cmake) @@ -63,6 +140,21 @@ if (ZEEK_PLUGIN_DIR) else () set(BRO_PLUGIN_INSTALL_PATH ${ZEEK_LIBDIR_PATH}/plugins CACHE STRING "Installation path for plugins" FORCE) +endif() + +set(bro_plugin_install_path "${BRO_PLUGIN_INSTALL_PATH}") +set(cmake_binary_dir "${CMAKE_BINARY_DIR}") +set(cmake_current_binary_dir "${CMAKE_CURRENT_BINARY_DIR}") +set(cmake_install_prefix "${CMAKE_INSTALL_PREFIX}") +set(cmake_source_dir "${CMAKE_SOURCE_DIR}") +set(zeek_script_install_path "${ZEEK_SCRIPT_INSTALL_PATH}") +if ( MSVC ) + string(REGEX REPLACE "^([A-Za-z]):/(.*)" "/\\1/\\2" bro_plugin_install_path "${bro_plugin_install_path}") + string(REGEX REPLACE "^([A-Za-z]):/(.*)" "/\\1/\\2" cmake_binary_dir "${cmake_binary_dir}") + string(REGEX REPLACE "^([A-Za-z]):/(.*)" "/\\1/\\2" cmake_current_binary_dir "${cmake_current_binary_dir}") + string(REGEX REPLACE "^([A-Za-z]):/(.*)" "/\\1/\\2" cmake_install_prefix "${cmake_install_prefix}") + string(REGEX REPLACE "^([A-Za-z]):/(.*)" "/\\1/\\2" cmake_source_dir "${cmake_source_dir}") + string(REGEX REPLACE "^([A-Za-z]):/(.*)" "/\\1/\\2" zeek_script_install_path "${zeek_script_install_path}") endif () if ( NOT ZEEK_ETC_INSTALL_DIR ) @@ -300,7 +392,9 @@ FindRequiredPackage(FLEX) FindRequiredPackage(BISON) FindRequiredPackage(PCAP) FindRequiredPackage(OpenSSL) -FindRequiredPackage(BIND) +if ( NOT WIN32 ) + FindRequiredPackage(BIND) +endif () FindRequiredPackage(ZLIB) # Installation directory for the distribution's Python modules. An @@ -325,6 +419,9 @@ set(PY_MOD_INSTALL_DIR ${py_mod_install_dir} if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/auxil/binpac/CMakeLists.txt) set(ENABLE_STATIC_ONLY_SAVED ${ENABLE_STATIC_ONLY}) + if ( MSVC ) + set(BUILD_STATIC_BINPAC true) + endif() if ( BUILD_STATIC_BINPAC ) set(ENABLE_STATIC_ONLY true) @@ -381,6 +478,11 @@ if ( PYTHON_VERSION_STRING VERSION_LESS ${ZEEK_PYTHON_MIN} ) endif () add_subdirectory(auxil/paraglob) +if ( MSVC ) + cmake_policy(SET CMP0079 NEW) + target_link_libraries(paraglob shlwapi) + set(BROKER_DISABLE_TOOLS true) +endif () set(zeekdeps ${zeekdeps} paraglob) if ( Broker_ROOT ) @@ -397,6 +499,9 @@ else () endif () set(ENABLE_STATIC_ONLY_SAVED ${ENABLE_STATIC_ONLY}) + if ( MSVC ) + set(BUILD_STATIC_BROKER true) + endif() if ( BUILD_STATIC_BROKER ) set(ENABLE_STATIC_ONLY true) @@ -599,7 +704,12 @@ if ( ${CMAKE_SYSTEM_NAME} MATCHES Linux ) endif () endif () -set(DEFAULT_ZEEKPATH .:${ZEEK_SCRIPT_INSTALL_PATH}:${ZEEK_SCRIPT_INSTALL_PATH}/policy:${ZEEK_SCRIPT_INSTALL_PATH}/site:${ZEEK_SCRIPT_INSTALL_PATH}/builtin-plugins) +set(DEFAULT_ZEEKPATH_PATHS . ${ZEEK_SCRIPT_INSTALL_PATH} ${ZEEK_SCRIPT_INSTALL_PATH}/policy ${ZEEK_SCRIPT_INSTALL_PATH}/site ${ZEEK_SCRIPT_INSTALL_PATH}/builtin-plugins) +if ( WIN32 ) + list(JOIN DEFAULT_ZEEKPATH_PATHS ";" DEFAULT_ZEEKPATH) +else () + list(JOIN DEFAULT_ZEEKPATH_PATHS ":" DEFAULT_ZEEKPATH) +endif () if ( NOT BINARY_PACKAGING_MODE ) set(ZEEK_DIST ${PROJECT_SOURCE_DIR}) @@ -653,11 +763,13 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/cmake DESTINATION share/zeek USE_SOURCE_PERMISSIONS PATTERN ".git" EXCLUDE) -# Install wrapper script for Bro-to-Zeek renaming. -include(InstallShellScript) -include(InstallSymlink) -InstallShellScript("bin" "zeek-wrapper.in" "zeek-wrapper") -InstallSymlink("${CMAKE_INSTALL_PREFIX}/bin/zeek-wrapper" "${CMAKE_INSTALL_PREFIX}/bin/bro-config") +if ( NOT WIN32 ) + # Install wrapper script for Bro-to-Zeek renaming. + include(InstallShellScript) + include(InstallSymlink) + InstallShellScript("bin" "zeek-wrapper.in" "zeek-wrapper") + InstallSymlink("${CMAKE_INSTALL_PREFIX}/bin/zeek-wrapper" "${CMAKE_INSTALL_PREFIX}/bin/bro-config") +endif () ######################################################################## ## zkg configuration diff --git a/ci/build.ps1 b/ci/build.ps1 new file mode 100644 index 0000000000..9b8d397c59 --- /dev/null +++ b/ci/build.ps1 @@ -0,0 +1,33 @@ +param( + [Parameter()] + [ValidateSet("Debug", "Release")] + [string] $BuildType = "Release" +) + +$SourceDirectory = (Convert-Path "$PSScriptRoot/../").Replace("\", "/") +$WorkingDirectory = $pwd.Path + +$commands = @() +if (!(Get-Command cl)) { + $commands += '"C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat"' +} + +$commands += @" +cmake.exe + -G "Ninja" + -S "$SourceDirectory" + -B "$WorkingDirectory" + -DCMAKE_BUILD_TYPE:STRING=$BuildType + -DCMAKE_INSTALL_PREFIX:PATH="$SourceDirectory/out/install/$BuildType" + -DDISABLE_PYTHON_BINDINGS=1 ` + 2>&1 +"@.Replace("`r`n", "") + +$commands += @" +cmake.exe --build $WorkingDirectory --config $BuildType +"@ + +$commands += @" +cmake.exe --install $WorkingDirectory +"@ +cmd /c ($commands -join " && ") \ No newline at end of file diff --git a/ci/windows/Dockerfile b/ci/windows/Dockerfile new file mode 100644 index 0000000000..c6ce894f74 --- /dev/null +++ b/ci/windows/Dockerfile @@ -0,0 +1,56 @@ +# escape=` +FROM mcr.microsoft.com/dotnet/framework/sdk:4.8-windowsservercore-ltsc2019 + +# Restore the default Windows shell for correct batch processing. +SHELL ["cmd", "/S", "/C"] + +# Download the Build Tools bootstrapper. +ADD https://aka.ms/vs/16/release/vs_buildtools.exe C:\TEMP\vs_buildtools.exe + +# Install Build Tools. +RUN C:\TEMP\vs_buildtools.exe --quiet --wait --norestart --nocache ` + --installPath C:\BuildTools ` + --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended ` + --add Microsoft.VisualStudio.Component.VC.ATLMFC ` + --add Microsoft.VisualStudio.Component.Windows10SDK.18362 ` + --add Microsoft.VisualStudio.Component.Windows10SDK.17763 ` + --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 ` + --add Microsoft.VisualStudio.Component.VC.v141.x86.x64 ` + --remove Microsoft.VisualStudio.Component.Windows10SDK.10240 ` + --remove Microsoft.VisualStudio.Component.Windows10SDK.10586 ` + --remove Microsoft.VisualStudio.Component.Windows10SDK.14393 ` + --remove Microsoft.VisualStudio.Component.Windows81SDK ` + || IF "%ERRORLEVEL%"=="3010" EXIT 0 + + +SHELL [ "powershell" ] + +RUN Set-ExecutionPolicy Unrestricted -Force + +# Install Chocolatey +RUN [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; ` + iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) + +# Restore the default Windows shell for correct batch processing. +SHELL ["cmd", "/S", "/C"] + +# Install prerequisites +RUN choco install conan -y +RUN choco install winflexbison -y +RUN choco install openssl -y +RUN choco install python -y +# Can't install a proper msys2 because it caused console hanging in the container during docker build. +RUN choco install msysgit -y +RUN choco install sed -y + +# Set working environment. +RUN setx /M PATH "%PATH%;C:\\Program Files\\Git\\bin" +RUN mkdir C:\build +WORKDIR C:\build + +# Configure conan +ADD default C:\Users\ContainerAdministrator\.conan\profiles\default + +# Define the entry point for the docker container. +# This entry point starts the developer command prompt and launches the PowerShell shell. +ENTRYPOINT ["C:\\BuildTools\\VC\\Auxiliary\\Build\\vcvars64.bat", "&&", "powershell.exe", "-NoLogo", "-ExecutionPolicy", "Unrestricted"] \ No newline at end of file diff --git a/ci/windows/conanfile_windows.txt b/ci/windows/conanfile_windows.txt new file mode 100644 index 0000000000..79db1eccc4 --- /dev/null +++ b/ci/windows/conanfile_windows.txt @@ -0,0 +1,9 @@ +[requires] +openssl/1.1.1i +zlib/1.2.11 +libpcap/1.10.1 +c-ares/1.18.1 + +[generators] +cmake_find_package +cmake diff --git a/ci/windows/default b/ci/windows/default new file mode 100644 index 0000000000..620a4bf3a9 --- /dev/null +++ b/ci/windows/default @@ -0,0 +1,12 @@ +[settings] +os=Windows +os_build=Windows +arch=x86_64 +arch_build=x86_64 +compiler=Visual Studio +compiler.version=16 +compiler.runtime=MT +build_type=Release +[options] +[build_requires] +[env] diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8c6ad63ba5..af63e54fd3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,6 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/include ) @@ -31,9 +32,9 @@ configure_file(util-config.h.in ${CMAKE_CURRENT_BINARY_DIR}/util-config.h) # - deletes instances of 'extern char.*getenv' in inFile # - writes results to outFile and adds it to list TRANSFORMED_BISON_OUTPUTS macro(REPLACE_YY_PREFIX_TARGET inFile outFile yylexPrefix yyPrefix) - set(args "'/extern char.*getenv/d") + set(args "\"/extern char.*getenv/d") set(args "${args}\;s/yylex/${yylexPrefix}lex/") - set(args "${args}\;s/yy/${yyPrefix}/g'" < ${inFile} > ${outFile}) + set(args "${args}\;s/yy/${yyPrefix}/g\"" < ${inFile} > ${outFile}) add_custom_command(OUTPUT ${outFile} COMMAND ${SED_EXE} ARGS ${args} @@ -48,6 +49,12 @@ endmacro(REPLACE_YY_PREFIX_TARGET) set(BISON_FLAGS "--debug") +if ( MSVC ) + set(SIGN_COMPARE_FLAG "/wd4018") +else() + set(SIGN_COMPARE_FLAG "-Wno-sign-compare") +endif() + # BIF parser/scanner bison_target(BIFParser builtin-func.y ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.cc @@ -56,7 +63,7 @@ bison_target(BIFParser builtin-func.y COMPILE_FLAGS "${BISON_FLAGS}") flex_target(BIFScanner builtin-func.l ${CMAKE_CURRENT_BINARY_DIR}/bif_lex.cc) add_flex_bison_dependency(BIFScanner BIFParser) -set_property(SOURCE bif_lex.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") +set_property(SOURCE bif_lex.cc APPEND_STRING PROPERTY COMPILE_FLAGS "${SIGN_COMPARE_FLAG}") # Rule parser/scanner bison_target(RuleParser rule-parse.y @@ -72,7 +79,7 @@ replace_yy_prefix_target(${CMAKE_CURRENT_BINARY_DIR}/rup.h rules_ rules_) flex_target(RuleScanner rule-scan.l ${CMAKE_CURRENT_BINARY_DIR}/rule-scan.cc COMPILE_FLAGS "-Prules_") -set_property(SOURCE rule-scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") +set_property(SOURCE rule-scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "${SIGN_COMPARE_FLAG}") # RE parser/scanner bison_target(REParser re-parse.y @@ -86,7 +93,7 @@ replace_yy_prefix_target(${CMAKE_CURRENT_BINARY_DIR}/rep.cc flex_target(REScanner re-scan.l ${CMAKE_CURRENT_BINARY_DIR}/re-scan.cc COMPILE_FLAGS "-Pre_") add_flex_bison_dependency(REScanner REParser) -set_property(SOURCE re-scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") +set_property(SOURCE re-scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "${SIGN_COMPARE_FLAG}") # Parser/Scanner bison_target(Parser parse.y @@ -99,13 +106,15 @@ replace_yy_prefix_target(${CMAKE_CURRENT_BINARY_DIR}/p.cc zeek yy) flex_target(Scanner scan.l ${CMAKE_CURRENT_BINARY_DIR}/scan.cc COMPILE_FLAGS "-Pzeek") -set_property(SOURCE scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-sign-compare") +set_property(SOURCE scan.cc APPEND_STRING PROPERTY COMPILE_FLAGS "${SIGN_COMPARE_FLAG}") ######################################################################## ## bifcl-dependent targets include(BifCl) +set(SUPERVISOR_SRCS supervisor/Supervisor.cc Pipe.cc) + set(BIF_SRCS zeek.bif stats.bif @@ -139,9 +148,9 @@ endforeach () include(BinPAC) set(BINPAC_AUXSRC - ${PROJECT_SOURCE_DIR}/src/binpac.pac - ${PROJECT_SOURCE_DIR}/src/zeek.pac - ${PROJECT_SOURCE_DIR}/src/binpac_zeek.h + ${CMAKE_CURRENT_SOURCE_DIR}/binpac.pac + ${CMAKE_CURRENT_SOURCE_DIR}/zeek.pac + ${CMAKE_CURRENT_SOURCE_DIR}/binpac_zeek.h ) binpac_target(binpac-lib.pac) @@ -258,6 +267,11 @@ set(_gen_zeek_script_cpp ${CMAKE_CURRENT_BINARY_DIR}/../CPP-gen.cc) add_custom_command(OUTPUT ${_gen_zeek_script_cpp} COMMAND ${CMAKE_COMMAND} -E touch ${_gen_zeek_script_cpp}) +if (!MSVC) + set_source_files_properties(legacy-netvar-init.cc PROPERTIES COMPILE_FLAGS + -Wno-deprecated-declarations) +endif() + set(MAIN_SRCS digest.cc net_util.cc @@ -311,7 +325,6 @@ set(MAIN_SRCS Options.cc Overflow.cc PacketFilter.cc - Pipe.cc PolicyFile.cc PrefixTable.cc PriorityQueue.cc @@ -346,7 +359,7 @@ set(MAIN_SRCS ZeekString.cc ZVal.cc - supervisor/Supervisor.cc + ${SUPERVISOR_SRCS} threading/BasicThread.cc threading/Formatter.cc @@ -504,23 +517,59 @@ collect_headers(zeek_HEADERS ${zeek_SRCS}) add_library(zeek_objs OBJECT ${zeek_SRCS}) -add_executable(zeek main.cc - $ - ${zeek_HEADERS} - ${bro_SUBDIR_LIBS} - ${bro_PLUGIN_LIBS} -) -target_link_libraries(zeek ${bro_PLUGIN_LINK_LIBS} ${zeekdeps} ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) -# Export symbols from zeek executable for use by plugins -set_target_properties(zeek PROPERTIES ENABLE_EXPORTS TRUE) +if (ZEEK_STANDALONE) + add_executable(zeek main.cc + $ + ${zeek_HEADERS} + ${bro_SUBDIR_LIBS} + ${bro_PLUGIN_LIBS} + ) + target_link_libraries(zeek ${bro_PLUGIN_LINK_LIBS} ${zeekdeps} ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) + # Export symbols from zeek executable for use by plugins + set_target_properties(zeek PROPERTIES ENABLE_EXPORTS TRUE) -install(TARGETS zeek DESTINATION bin) + if ( MSVC ) + set(WINDOWS_EXPORT_ALL_SYMBOLS ON) + endif () -set(BRO_EXE zeek - CACHE STRING "Zeek executable binary" FORCE) + install(TARGETS zeek RUNTIME DESTINATION bin ARCHIVE DESTINATION lib) -set(BRO_EXE_PATH ${CMAKE_CURRENT_BINARY_DIR}/zeek - CACHE STRING "Path to Zeek executable binary" FORCE) + set(BRO_EXE zeek + CACHE STRING "Zeek executable binary" FORCE) + + set(BRO_EXE_PATH ${CMAKE_CURRENT_BINARY_DIR}/zeek + CACHE STRING "Path to Zeek executable binary" FORCE) + +else() + add_library(zeek STATIC $ ${zeek_HEADERS}) + + target_link_libraries(zeek PUBLIC ${zeekdeps} + ${CMAKE_THREAD_LIBS_INIT} + ${CMAKE_DL_LIBS} + ${bro_SUBDIR_LIBS} + ${bro_PLUGIN_LIBS}) + + target_include_directories(zeek PUBLIC + ${CMAKE_SOURCE_DIR}/zeek/src + ${CMAKE_SOURCE_DIR}/zeek/src/include + ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}/zeek/src + ${CMAKE_BINARY_DIR}/zeek/src/include + ${CMAKE_SOURCE_DIR}/zeek/src/windows/usr.include) +endif() + +if ( NOT WIN32 ) + # Install wrapper script for Bro-to-Zeek renaming. + include(InstallSymlink) + InstallSymlink("${CMAKE_INSTALL_PREFIX}/bin/zeek-wrapper" "${CMAKE_INSTALL_PREFIX}/bin/bro") +endif () + +if ( NOT BINARY_PACKAGING_MODE ) + # Older plugins may still use `bro` in unit tests. + execute_process(COMMAND "${CMAKE_COMMAND}" -E create_symlink + "${CMAKE_CURRENT_BINARY_DIR}/../zeek-wrapper.in" + "${CMAKE_CURRENT_BINARY_DIR}/bro") +endif () # Target to create all the autogenerated files. add_custom_target(generate_outputs_stage1) @@ -567,7 +616,7 @@ install(CODE " # Make sure to escape a bunch of special characters in the path before trying to use it as a # regular expression below. -string(REGEX REPLACE "([][+.*()^])" "\\\\\\1" escaped_path "${CMAKE_CURRENT_SOURCE_DIR}/zeek") +string(REGEX REPLACE "([][+.*()^])" "\\\\\\1" escaped_path "${CMAKE_CURRENT_SOURCE_DIR}/include/*") install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION include/zeek @@ -592,6 +641,8 @@ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/ PATTERN "*.bif.netvar_h" PATTERN "*.bif.h" PATTERN "CMakeFiles" EXCLUDE + # The "include/zeek -> .." symlink isn't needed in the install-tree + REGEX "${escaped_path}$" EXCLUDE ) install(FILES diff --git a/src/DebugCmdInfoConstants.in b/src/DebugCmdInfoConstants.in index ad90d7ed83..c1b3d112fd 100644 --- a/src/DebugCmdInfoConstants.in +++ b/src/DebugCmdInfoConstants.in @@ -1,6 +1,6 @@ // This invalid entry should always be first cmd: dcInvalid -names: +names: _ resume: false help: This function should not be called repeatable: false diff --git a/src/DebugLogger.h b/src/DebugLogger.h index 591bfb85c4..e60c1b8c3c 100644 --- a/src/DebugLogger.h +++ b/src/DebugLogger.h @@ -13,17 +13,17 @@ #include "zeek/util.h" -#define DBG_LOG(stream, args...) \ - if ( ::zeek::detail::debug_logger.IsEnabled(stream) ) \ - ::zeek::detail::debug_logger.Log(stream, args) -#define DBG_LOG_VERBOSE(stream, args...) \ - if ( ::zeek::detail::debug_logger.IsVerbose() && \ - ::zeek::detail::debug_logger.IsEnabled(stream) ) \ - ::zeek::detail::debug_logger.Log(stream, args) +#define DBG_LOG(stream, ...) \ + if ( ::zeek::detail::debug_logger.IsEnabled(stream) ) \ + ::zeek::detail::debug_logger.Log(stream, __VA_ARGS__) +#define DBG_LOG_VERBOSE(stream, ...) \ + if ( ::zeek::detail::debug_logger.IsVerbose() && \ + ::zeek::detail::debug_logger.IsEnabled(stream) ) \ + ::zeek::detail::debug_logger.Log(stream, __VA_ARGS__) #define DBG_PUSH(stream) ::zeek::detail::debug_logger.PushIndent(stream) #define DBG_POP(stream) ::zeek::detail::debug_logger.PopIndent(stream) -#define PLUGIN_DBG_LOG(plugin, args...) ::zeek::detail::debug_logger.Log(plugin, args) +#define PLUGIN_DBG_LOG(plugin, ...) ::zeek::detail::debug_logger.Log(plugin, __VA_ARGS__) namespace zeek { @@ -123,9 +123,9 @@ extern DebugLogger debug_logger; } // namespace zeek #else -#define DBG_LOG(args...) -#define DBG_LOG_VERBOSE(args...) +#define DBG_LOG(...) +#define DBG_LOG_VERBOSE(...) #define DBG_PUSH(stream) #define DBG_POP(stream) -#define PLUGIN_DBG_LOG(plugin, args...) +#define PLUGIN_DBG_LOG(plugin, ...) #endif diff --git a/src/Flare.cc b/src/Flare.cc index e2f42fa34e..cbe47ab005 100644 --- a/src/Flare.cc +++ b/src/Flare.cc @@ -8,10 +8,62 @@ #include "zeek/Reporter.h" +#if defined(_MSC_VER) + +#include + +#define fatalError(...) \ +do \ + { \ + if ( reporter ) \ + reporter->FatalError(__VA_ARGS__); \ + else \ + { \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + _exit(1); \ + } \ + } \ +while (0) + +#endif + namespace zeek::detail { -Flare::Flare() : pipe(FD_CLOEXEC, FD_CLOEXEC, O_NONBLOCK, O_NONBLOCK) { } +Flare::Flare() +#if ! defined(_MSC_VER) + : pipe(FD_CLOEXEC, FD_CLOEXEC, O_NONBLOCK, O_NONBLOCK) + { + } +#else + { + WSADATA wsaData; + if ( WSAStartup(MAKEWORD(2,2), &wsaData) != 0 ) + fatalError("WSAStartup failure: %d", WSAGetLastError()); + + recvfd = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, nullptr, 0, + WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT); + if ( recvfd == (int) INVALID_SOCKET ) + fatalError("WSASocket failure: %d", WSAGetLastError()); + sendfd = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, nullptr, 0, + WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT); + if ( sendfd == (int) INVALID_SOCKET ) + fatalError("WSASocket failure: %d", WSAGetLastError()); + + sockaddr_in sa; + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = inet_addr("127.0.0.1"); + if ( bind(recvfd, (sockaddr*) &sa, sizeof(sa)) == SOCKET_ERROR ) + fatalError("bind failure: %d", WSAGetLastError()); + int salen = sizeof(sa); + if ( getsockname(recvfd, (sockaddr*) &sa, &salen) == SOCKET_ERROR ) + fatalError("getsockname failure: %d", WSAGetLastError()); + if ( connect(sendfd, (sockaddr*) &sa, sizeof(sa)) == SOCKET_ERROR ) + fatalError("connect failure: %d", WSAGetLastError()); + } +#endif [[noreturn]] static void bad_pipe_op(const char* which, bool signal_safe) { @@ -36,14 +88,22 @@ void Flare::Fire(bool signal_safe) for ( ;; ) { +#if ! defined(_MSC_VER) int n = write(pipe.WriteFD(), &tmp, 1); +#else + int n = send(sendfd, &tmp, 1, 0); +#endif if ( n > 0 ) // Success -- wrote a byte to pipe. break; if ( n < 0 ) { +#if defined(_MSC_VER) + errno = WSAGetLastError(); + bad_pipe_op("send", signal_safe); +#endif if ( errno == EAGAIN ) // Success: pipe is full and just need at least one byte in it. break; @@ -66,15 +126,23 @@ int Flare::Extinguish(bool signal_safe) for ( ;; ) { +#if ! defined(_MSC_VER) int n = read(pipe.ReadFD(), &tmp, sizeof(tmp)); - +#else + int n = recv(recvfd, tmp, sizeof(tmp), 0); +#endif if ( n >= 0 ) { rval += n; // Pipe may not be empty yet: try again. continue; } - +#if defined(_MSC_VER) + if ( WSAGetLastError() == WSAEWOULDBLOCK ) + break; + errno = WSAGetLastError(); + bad_pipe_op("recv", signal_safe); +#endif if ( errno == EAGAIN ) // Success: pipe is now empty. break; diff --git a/src/Flare.h b/src/Flare.h index e1bfe3b6af..a06996338f 100644 --- a/src/Flare.h +++ b/src/Flare.h @@ -2,7 +2,9 @@ #pragma once -#include "zeek/Pipe.h" +#if ! defined(_MSC_VER) +#include "Pipe.h" +#endif namespace zeek::detail { @@ -22,7 +24,12 @@ public: * @return a file descriptor that will become ready if the flare has been * Fire()'d and not yet Extinguished()'d. */ - int FD() const { return pipe.ReadFD(); } + int FD() const +#if ! defined(_MSC_VER) + { return pipe.ReadFD(); } +#else + { return recvfd; } +#endif /** * Put the object in the "ready" state. @@ -41,7 +48,11 @@ public: int Extinguish(bool signal_safe = false); private: +#if ! defined(_MSC_VER) Pipe pipe; +#else + int sendfd, recvfd; +#endif }; } // namespace zeek::detail diff --git a/src/Hash.cc b/src/Hash.cc index 9229655800..68db773de8 100644 --- a/src/Hash.cc +++ b/src/Hash.cc @@ -345,7 +345,7 @@ void HashKey::Reserve(const char* tag, size_t addl_size, size_t alignment) void HashKey::Allocate() { - if ( key != nullptr and key != reinterpret_cast(&key_u) ) + if ( key != nullptr && key != reinterpret_cast(&key_u) ) { reporter->InternalWarning("usage error in HashKey::Allocate(): already allocated"); return; diff --git a/src/Hash.h b/src/Hash.h index 4f70ce1219..06ec01ae0b 100644 --- a/src/Hash.h +++ b/src/Hash.h @@ -20,6 +20,7 @@ #pragma once #include +#include #include "zeek/util.h" // for zeek_int_t diff --git a/src/IP.cc b/src/IP.cc index c85cdc1e96..4de4506387 100644 --- a/src/IP.cc +++ b/src/IP.cc @@ -66,8 +66,8 @@ RecordValPtr IPv6_Hdr::ToVal(VectorValPtr chain) const static auto ip6_hdr_type = id::find_type("ip6_hdr"); rv = make_intrusive(ip6_hdr_type); const struct ip6_hdr* ip6 = (const struct ip6_hdr*)data; - rv->Assign(0, (ntohl(ip6->ip6_flow) & 0x0ff00000) >> 20); - rv->Assign(1, ntohl(ip6->ip6_flow) & 0x000fffff); + rv->Assign(0, static_cast(ntohl(ip6->ip6_flow) & 0x0ff00000) >> 20); + rv->Assign(1, static_cast(ntohl(ip6->ip6_flow) & 0x000fffff)); rv->Assign(2, ntohs(ip6->ip6_plen)); rv->Assign(3, ip6->ip6_nxt); rv->Assign(4, ip6->ip6_hlim); @@ -127,7 +127,7 @@ RecordValPtr IPv6_Hdr::ToVal(VectorValPtr chain) const rv->Assign(2, (ntohs(frag->ip6f_offlg) & 0xfff8) >> 3); rv->Assign(3, (ntohs(frag->ip6f_offlg) & 0x0006) >> 1); rv->Assign(4, static_cast(ntohs(frag->ip6f_offlg) & 0x0001)); - rv->Assign(5, ntohl(frag->ip6f_ident)); + rv->Assign(5, static_cast(ntohl(frag->ip6f_ident))); } break; @@ -138,13 +138,13 @@ RecordValPtr IPv6_Hdr::ToVal(VectorValPtr chain) const rv->Assign(0, ((ip6_ext*)data)->ip6e_nxt); rv->Assign(1, ((ip6_ext*)data)->ip6e_len); rv->Assign(2, ntohs(((uint16_t*)data)[1])); - rv->Assign(3, ntohl(((uint32_t*)data)[1])); + rv->Assign(3, static_cast(ntohl(((uint32_t*)data)[1]))); if ( Length() >= 12 ) { // Sequence Number and ICV fields can only be extracted if // Payload Len was non-zero for this header. - rv->Assign(4, ntohl(((uint32_t*)data)[2])); + rv->Assign(4, static_cast(ntohl(((uint32_t*)data)[2]))); uint16_t off = 3 * sizeof(uint32_t); rv->Assign(5, new String(data + off, Length() - off, true)); } @@ -156,8 +156,8 @@ RecordValPtr IPv6_Hdr::ToVal(VectorValPtr chain) const static auto ip6_esp_type = id::find_type("ip6_esp"); rv = make_intrusive(ip6_esp_type); const uint32_t* esp = (const uint32_t*)data; - rv->Assign(0, ntohl(esp[0])); - rv->Assign(1, ntohl(esp[1])); + rv->Assign(0, static_cast(ntohl(esp[0]))); + rv->Assign(1, static_cast(ntohl(esp[1]))); } break; @@ -401,8 +401,8 @@ RecordValPtr IP_Hdr::ToPktHdrVal(RecordValPtr pkt_hdr, int sindex) const tcp_hdr->Assign(0, val_mgr->Port(ntohs(tp->th_sport), TRANSPORT_TCP)); tcp_hdr->Assign(1, val_mgr->Port(ntohs(tp->th_dport), TRANSPORT_TCP)); - tcp_hdr->Assign(2, ntohl(tp->th_seq)); - tcp_hdr->Assign(3, ntohl(tp->th_ack)); + tcp_hdr->Assign(2, static_cast(ntohl(tp->th_seq))); + tcp_hdr->Assign(3, static_cast(ntohl(tp->th_ack))); tcp_hdr->Assign(4, tcp_hdr_len); tcp_hdr->Assign(5, data_len); tcp_hdr->Assign(6, tp->th_x2); diff --git a/src/IP.h b/src/IP.h index 0488290b00..76f17f7237 100644 --- a/src/IP.h +++ b/src/IP.h @@ -12,6 +12,8 @@ #ifdef HAVE_NETINET_IP6_H #include +#else +#include "net_util.h" // for struct ip6_hdr #endif #include diff --git a/src/Obj.cc b/src/Obj.cc index fd1b9100aa..47bbf1462d 100644 --- a/src/Obj.cc +++ b/src/Obj.cc @@ -61,10 +61,14 @@ Obj::~Obj() { if ( notify_plugins ) { +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif PLUGIN_HOOK_VOID(HOOK_BRO_OBJ_DTOR, HookBroObjDtor(this)); +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif PLUGIN_HOOK_VOID(HOOK_OBJ_DTOR, HookObjDtor(this)); } diff --git a/src/OpaqueVal.h b/src/OpaqueVal.h index e18f889530..7f63a38569 100644 --- a/src/OpaqueVal.h +++ b/src/OpaqueVal.h @@ -2,6 +2,10 @@ #pragma once +#ifdef _MSC_VER +#include +#endif + #include #if ( OPENSSL_VERSION_NUMBER < 0x30000000L ) || defined(LIBRESSL_VERSION_NUMBER) #include diff --git a/src/Options.cc b/src/Options.cc index 98f251b19a..31e5b38c86 100644 --- a/src/Options.cc +++ b/src/Options.cc @@ -6,7 +6,10 @@ #include -#ifdef HAVE_GETOPT_H +#include "zeek/ScriptProfile.h" +#include "zeek/script_opt/ScriptOpt.h" + +#if defined(HAVE_GETOPT_H) && ! defined(_MSC_VER) #include #endif @@ -15,7 +18,6 @@ #include #include -#include "zeek/ScriptProfile.h" #include "zeek/logging/writers/ascii/Ascii.h" #include "zeek/script_opt/ScriptOpt.h" diff --git a/src/PolicyFile.cc b/src/PolicyFile.cc index 31e44dcdd9..db3cf77ff2 100644 --- a/src/PolicyFile.cc +++ b/src/PolicyFile.cc @@ -117,9 +117,10 @@ bool LoadPolicyFileText(const char* policy_filename, // ### This code is not necessarily Unicode safe! // (probably fine with UTF-8) pf->filedata = new char[size + 1]; - if ( fread(pf->filedata, size, 1, f) != 1 ) + size_t n = fread(pf->filedata, 1, size, f); + if ( ferror(f) ) reporter->InternalError("Failed to fread() file data"); - pf->filedata[size] = 0; + pf->filedata[n] = 0; fclose(f); } diff --git a/src/RunState.cc b/src/RunState.cc index 315ddcd24d..6a1d4c3387 100644 --- a/src/RunState.cc +++ b/src/RunState.cc @@ -40,10 +40,12 @@ extern "C" #include "zeek/plugin/Manager.h" #include "zeek/session/Manager.h" +#ifndef _MSC_VER extern "C" { extern int select(int, fd_set*, fd_set*, fd_set*, struct timeval*); } +#endif static double last_watchdog_proc_time = 0.0; // value of above during last watchdog extern int signal_val; diff --git a/src/SerializationFormat.cc b/src/SerializationFormat.cc index 42cff63cdd..b723387ceb 100644 --- a/src/SerializationFormat.cc +++ b/src/SerializationFormat.cc @@ -325,6 +325,13 @@ bool BinarySerializationFormat::Write(uint32_t v, const char* tag) return WriteData(&v, sizeof(v)); } +#if defined(_MSC_VER) +bool BinarySerializationFormat::Write(u_long v, const char* tag) + { + return Write((uint32_t) v, tag); + } +#endif + bool BinarySerializationFormat::Write(int v, const char* tag) { DBG_LOG(DBG_SERIAL, "Write int %d [%s]", v, tag); @@ -386,7 +393,7 @@ bool BinarySerializationFormat::Write(const IPAddr& addr, const char* tag) for ( int i = 0; i < n; ++i ) { - if ( ! Write(ntohl(raw[i]), "addr-part") ) + if ( ! Write(static_cast(ntohl(raw[i])), "addr-part") ) return false; } @@ -402,7 +409,7 @@ bool BinarySerializationFormat::Write(const struct in_addr& addr, const char* ta { const uint32_t* bytes = (uint32_t*)&addr.s_addr; - if ( ! Write(ntohl(bytes[0]), "addr4") ) + if ( ! Write(static_cast(ntohl(bytes[0])), "addr4") ) return false; return true; @@ -414,7 +421,7 @@ bool BinarySerializationFormat::Write(const struct in6_addr& addr, const char* t for ( int i = 0; i < 4; ++i ) { - if ( ! Write(ntohl(bytes[i]), "addr6-part") ) + if ( ! Write(static_cast(ntohl(bytes[i])), "addr6-part") ) return false; } diff --git a/src/SerializationFormat.h b/src/SerializationFormat.h index 44215792bb..060d0a996d 100644 --- a/src/SerializationFormat.h +++ b/src/SerializationFormat.h @@ -126,6 +126,9 @@ public: bool Write(int v, const char* tag) override; bool Write(uint16_t v, const char* tag) override; bool Write(uint32_t v, const char* tag) override; +#if defined(_MSC_VER) + bool Write(u_long v, const char* tag); +#endif bool Write(int64_t v, const char* tag) override; bool Write(uint64_t v, const char* tag) override; bool Write(char v, const char* tag) override; diff --git a/src/analyzer/Manager.h b/src/analyzer/Manager.h index 22167e2f03..f33241881d 100644 --- a/src/analyzer/Manager.h +++ b/src/analyzer/Manager.h @@ -402,12 +402,12 @@ extern analyzer::Manager* analyzer_mgr; DBG_LOG(zeek::DBG_ANALYZER, "%s " txt, \ fmt_conn_id(conn->OrigAddr(), ntohs(conn->OrigPort()), conn->RespAddr(), \ ntohs(conn->RespPort()))); -#define DBG_ANALYZER_ARGS(conn, fmt, args...) \ +#define DBG_ANALYZER_ARGS(conn, fmt, ...) \ DBG_LOG(zeek::DBG_ANALYZER, "%s " fmt, \ fmt_conn_id(conn->OrigAddr(), ntohs(conn->OrigPort()), conn->RespAddr(), \ ntohs(conn->RespPort())), \ - ##args); + ##__VA_ARGS__); #else #define DBG_ANALYZER(conn, txt) -#define DBG_ANALYZER_ARGS(conn, fmt, args...) +#define DBG_ANALYZER_ARGS(conn, fmt, ...) #endif diff --git a/src/file_analysis/analyzer/extract/functions.bif b/src/file_analysis/analyzer/extract/functions.bif index 96a1b07da1..25a021449d 100644 --- a/src/file_analysis/analyzer/extract/functions.bif +++ b/src/file_analysis/analyzer/extract/functions.bif @@ -3,7 +3,7 @@ module FileExtract; %%{ -#include "zeek/zeek/file_analysis/Manager.h" +#include "zeek/file_analysis/Manager.h" #include "zeek/file_analysis/file_analysis.bif.h" %%} diff --git a/src/file_analysis/analyzer/x509/X509Common.cc b/src/file_analysis/analyzer/x509/X509Common.cc index 9d5f839b0b..85bd3ae6e9 100644 --- a/src/file_analysis/analyzer/x509/X509Common.cc +++ b/src/file_analysis/analyzer/x509/X509Common.cc @@ -279,7 +279,7 @@ void X509Common::ParseExtension(X509_EXTENSION* ex, const EventHandlerPtr& h, bo auto pX509Ext = make_intrusive(BifType::Record::X509::Extension); pX509Ext->Assign(0, name); - if ( short_name and strlen(short_name) > 0 ) + if ( short_name && strlen(short_name) > 0 ) pX509Ext->Assign(1, short_name); pX509Ext->Assign(2, oid); diff --git a/src/file_analysis/analyzer/x509/x509-signed_certificate_timestamp.pac b/src/file_analysis/analyzer/x509/x509-signed_certificate_timestamp.pac deleted file mode 120000 index 88305ed8fd..0000000000 --- a/src/file_analysis/analyzer/x509/x509-signed_certificate_timestamp.pac +++ /dev/null @@ -1 +0,0 @@ -../../../analyzer/protocol/ssl/tls-handshake-signed_certificate_timestamp.pac \ No newline at end of file diff --git a/src/file_analysis/analyzer/x509/x509-signed_certificate_timestamp.pac b/src/file_analysis/analyzer/x509/x509-signed_certificate_timestamp.pac new file mode 100644 index 0000000000..5ebb1abe9a --- /dev/null +++ b/src/file_analysis/analyzer/x509/x509-signed_certificate_timestamp.pac @@ -0,0 +1 @@ +%include ../../../analyzer/protocol/ssl/tls-handshake-signed_certificate_timestamp.pac \ No newline at end of file diff --git a/src/fuzzers/FuzzBuffer.cc b/src/fuzzers/FuzzBuffer.cc index 5529e98531..81251473a4 100644 --- a/src/fuzzers/FuzzBuffer.cc +++ b/src/fuzzers/FuzzBuffer.cc @@ -2,6 +2,10 @@ #define _GNU_SOURCE #endif +#ifdef _MSC_VER +#include +#endif + #include "zeek/fuzzers/FuzzBuffer.h" #include diff --git a/src/fuzzers/packet-fuzzer.cc b/src/fuzzers/packet-fuzzer.cc index af199a1544..49b183bda4 100644 --- a/src/fuzzers/packet-fuzzer.cc +++ b/src/fuzzers/packet-fuzzer.cc @@ -1,3 +1,7 @@ +#ifdef _MSC_VER +#include +#endif + extern "C" { #include diff --git a/src/iosource/Packet.h b/src/iosource/Packet.h index cedc235493..2719047415 100644 --- a/src/iosource/Packet.h +++ b/src/iosource/Packet.h @@ -11,6 +11,8 @@ using pkt_timeval = bpf_timeval; #else using pkt_timeval = struct timeval; +#include +#include #endif #include // For DLT_ constants diff --git a/src/iosource/pcap/Source.cc b/src/iosource/pcap/Source.cc index 210263cf7c..4ebd8e77ca 100644 --- a/src/iosource/pcap/Source.cc +++ b/src/iosource/pcap/Source.cc @@ -160,7 +160,9 @@ void PcapSource::OpenLive() Info(util::fmt("pcap bufsize = %d\n", ((struct pcap*)pd)->bufsize)); #endif +#ifndef _MSC_VER props.selectable_fd = pcap_get_selectable_fd(pd); +#endif props.link_type = pcap_datalink(pd); props.is_live = true; diff --git a/src/main.cc b/src/main.cc index 254fb14c58..7436292039 100644 --- a/src/main.cc +++ b/src/main.cc @@ -7,8 +7,16 @@ #include "zeek/supervisor/Supervisor.h" #include "zeek/zeek-setup.h" +#if defined(_MSC_VER) +#include // For _O_BINARY. +#endif + int main(int argc, char** argv) { +#if defined(_MSC_VER) + _setmode(_fileno(stdout), _O_BINARY); + _setmode(_fileno(stderr), _O_BINARY); +#endif auto time_start = zeek::util::current_time(true); auto setup_result = zeek::detail::setup(argc, argv); @@ -41,7 +49,6 @@ int main(int argc, char** argv) zeek::detail::timer_mgr->Add(new zeek::detail::ParentProcessCheckTimer(1, 1)); double time_net_start = zeek::util::current_time(true); - ; uint64_t mem_net_start_total; uint64_t mem_net_start_malloced; diff --git a/src/net_util.h b/src/net_util.h index 8ddc4d99e9..7031eed81e 100644 --- a/src/net_util.h +++ b/src/net_util.h @@ -283,6 +283,7 @@ inline uint64_t htonll(uint64_t i) #else +#ifndef _MSC_VER inline double ntohd(double d) { assert(sizeof(d) == 8); @@ -328,6 +329,7 @@ inline float htonf(float f) { return ntohf(f); } +#endif #ifndef HAVE_BYTEORDER_64 inline uint64_t ntohll(uint64_t i) diff --git a/src/packet_analysis/protocol/arp/ARP.cc b/src/packet_analysis/protocol/arp/ARP.cc index 51ec3aab02..40ee22247b 100644 --- a/src/packet_analysis/protocol/arp/ARP.cc +++ b/src/packet_analysis/protocol/arp/ARP.cc @@ -94,7 +94,7 @@ bool ARPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) auto ah = (const struct arp_pkthdr*)data; // Check the size. - size_t min_length = (ar_tpa(ah) - (char*)data) + ah->ar_pln; + size_t min_length = (ar_tpa(ah) - (caddr_t) data) + ah->ar_pln; if ( min_length > len ) { Weird("truncated_ARP", packet); @@ -149,7 +149,7 @@ bool ARPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) } // Check MAC src address = ARP sender MAC address. - if ( memcmp(packet->l2_src, ar_sha(ah), ah->ar_hln) != 0 ) + if ( memcmp(packet->l2_src, (const char*)ar_sha(ah), ah->ar_hln) != 0 ) { BadARPEvent(ah, "weird-arp-sha"); return false; @@ -219,9 +219,9 @@ void ARPAnalyzer::BadARPEvent(const struct arp_pkthdr* hdr, const char* fmt, ... vsnprintf(msg, sizeof(msg), fmt, args); va_end(args); - event_mgr.Enqueue(bad_arp, ToAddrVal(ar_spa(hdr), hdr->ar_pln), + event_mgr.Enqueue(bad_arp, ToAddrVal(reinterpret_cast(ar_spa(hdr)), hdr->ar_pln), ToEthAddrStr(reinterpret_cast(ar_sha(hdr)), hdr->ar_hln), - ToAddrVal(ar_tpa(hdr), hdr->ar_pln), + ToAddrVal(reinterpret_cast(ar_tpa(hdr)), hdr->ar_pln), ToEthAddrStr(reinterpret_cast(ar_tha(hdr)), hdr->ar_hln), zeek::make_intrusive(msg)); } diff --git a/src/plugin/Manager.cc b/src/plugin/Manager.cc index fcf46295af..e4ee83dd83 100644 --- a/src/plugin/Manager.cc +++ b/src/plugin/Manager.cc @@ -3,8 +3,9 @@ #include "zeek/plugin/Manager.h" #include +#if !defined(_MSC_VER) #include -#include +#endif #include #include #include // for PATH_MAX @@ -56,13 +57,13 @@ void Manager::SearchDynamicPlugins(const std::string& dir) if ( dir.empty() ) return; - if ( dir.find(':') != string::npos ) + if ( dir.find(path_list_separator) != string::npos ) { // Split at ":". std::stringstream s(dir); std::string d; - while ( std::getline(s, d, ':') ) + while ( std::getline(s, d, path_list_separator) ) SearchDynamicPlugins(d); return; @@ -213,30 +214,51 @@ bool Manager::ActivateDynamicPluginInternal(const std::string& name, bool ok_if_ } // Load shared libraries. + string dydir = dir + "/lib"; + const char *dyext = "." HOST_ARCHITECTURE DYNAMIC_PLUGIN_SUFFIX; - string dypattern = dir + "/lib/*." + HOST_ARCHITECTURE + DYNAMIC_PLUGIN_SUFFIX; + DBG_LOG(DBG_PLUGINS, " Searching for shared libraries in %s with extension %s", dydir.c_str(), dyext); - DBG_LOG(DBG_PLUGINS, " Searching for shared libraries %s", dypattern.c_str()); + DIR* d = opendir(dydir.c_str()); - glob_t gl; - - if ( glob(dypattern.c_str(), 0, 0, &gl) == 0 ) + if ( ! d ) { - for ( size_t i = 0; i < gl.gl_pathc; i++ ) - { - const char* path = gl.gl_pathv[i]; + DBG_LOG(DBG_PLUGINS, "Cannot open directory %s", dydir.c_str()); + return true; + } - current_plugin = nullptr; - current_dir = dir.c_str(); - current_sopath = path; - void* hdl = dlopen(path, RTLD_NOW | RTLD_GLOBAL); - current_dir = nullptr; - current_sopath = nullptr; + struct dirent *dp; + + while ( (dp = readdir(d)) ) + { + if ( strlen(dp->d_name) >= strlen(dyext) + && zeek::util::streq(dp->d_name + strlen(dp->d_name) - strlen(dyext), dyext) ) + { + string path = dydir + "/" + dp->d_name; + + current_plugin = nullptr; + current_dir = dydir.c_str(); + current_sopath = path.c_str(); +#if defined(_MSC_VER) + void* hdl = LoadLibraryA(path.c_str()); +#else + void* hdl = dlopen(path.c_str(), RTLD_LAZY | RTLD_GLOBAL); +#endif + current_dir = nullptr; + current_sopath = nullptr; if ( ! hdl ) { - const char* err = dlerror(); - errors->push_back(util::fmt("cannot load plugin library %s: %s", path, + const char* err = nullptr; +#if defined(_MSC_VER) + char buf[65535]; + const int flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; + if ( FormatMessageA(flags, nullptr, GetLastError(), 0, buf, sizeof(buf), nullptr ) ) + err = buf; +#else + err = dlerror(); +#endif + errors->push_back(util::fmt("cannot load plugin library %s: %s", path.c_str(), err ? err : "")); continue; } @@ -244,7 +266,7 @@ bool Manager::ActivateDynamicPluginInternal(const std::string& name, bool ok_if_ if ( ! current_plugin ) { errors->push_back( - util::fmt("load plugin library %s did not instantiate a plugin", path)); + util::fmt("load plugin library %s did not instantiate a plugin", path.c_str())); continue; } @@ -256,10 +278,10 @@ bool Manager::ActivateDynamicPluginInternal(const std::string& name, bool ok_if_ plugins_by_path.insert( std::make_pair(util::detail::normalize_path(dir), current_plugin)); - // We execute the pre-script initialization here; this in - // fact could be *during* script initialization if we got - // triggered via @load-plugin. - current_plugin->InitPreScript(); + // We execute the pre-script initialization here; this in + // fact could be *during* script initialization if we got + // triggered via @load-plugin. + current_plugin->InitPreScript(); // Make sure the name the plugin reports is consistent with // what we expect from its magic file. @@ -271,20 +293,21 @@ bool Manager::ActivateDynamicPluginInternal(const std::string& name, bool ok_if_ } current_plugin = nullptr; - DBG_LOG(DBG_PLUGINS, " Loaded %s", path); + DBG_LOG(DBG_PLUGINS, " Loaded %s", path.c_str()); } - globfree(&gl); - if ( ! errors->empty() ) return false; } - else + closedir(d); + + if ( current_plugin == nullptr ) { DBG_LOG(DBG_PLUGINS, " No shared library found"); } + // Add the "scripts" and "bif" directories to ZEEKPATH. std::string scripts = dir + "scripts"; @@ -911,32 +934,48 @@ void Manager::HookBroObjDtor(void* obj) const if ( HavePluginForHook(META_HOOK_PRE) ) { args.push_back(HookArgument(obj)); +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif MetaHookPre(HOOK_BRO_OBJ_DTOR, args); +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif } +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif hook_list* l = hooks[HOOK_BRO_OBJ_DTOR]; +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif if ( l ) for ( hook_list::iterator i = l->begin(); i != l->end(); ++i ) { Plugin* p = (*i).second; +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif p->HookBroObjDtor(obj); +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif } if ( HavePluginForHook(META_HOOK_POST) ) +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif MetaHookPost(HOOK_BRO_OBJ_DTOR, args, HookArgument()); +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif } void Manager::HookObjDtor(void* obj) const diff --git a/src/plugin/Manager.h b/src/plugin/Manager.h index c3fcc287fc..e23ef65cc9 100644 --- a/src/plugin/Manager.h +++ b/src/plugin/Manager.h @@ -77,7 +77,7 @@ public: * This must be called only before InitPluginsPreScript(). * * @param dir The directory to search for plugins. Multiple directories - * can be given by splitting them with ':'. + * can be given by separating them with zeek::util::path_list_separator. */ void SearchDynamicPlugins(const std::string& dir); diff --git a/src/plugin/Plugin.cc b/src/plugin/Plugin.cc index 6b5a201564..af005a40f9 100644 --- a/src/plugin/Plugin.cc +++ b/src/plugin/Plugin.cc @@ -383,10 +383,14 @@ void Plugin::RequestEvent(EventHandlerPtr handler) void Plugin::RequestBroObjDtor(Obj* obj) { +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif plugin_mgr->RequestBroObjDtor(obj, this); +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif } void Plugin::RequestObjDtor(Obj* obj) diff --git a/src/plugin/Plugin.h b/src/plugin/Plugin.h index b3879ec9fb..e49d80b461 100644 --- a/src/plugin/Plugin.h +++ b/src/plugin/Plugin.h @@ -25,6 +25,10 @@ struct Field; namespace zeek { +#if defined(_MSC_VER) +#undef VOID +#endif + // Increase this when making incompatible changes to the plugin API. Note // that the constant is never used in C code. It's picked up on by CMake. constexpr int PLUGIN_API_VERSION = 7; @@ -116,17 +120,23 @@ public: // We force this to inline so that the API version gets hardcoded // into the external plugin. (Technically, it's not a "force", just a // strong hint.). The attribute seems generally available. +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif inline Configuration() __attribute__((always_inline)) { bro_version = ZEEK_PLUGIN_ZEEK_VERSION; zeek_version = ZEEK_PLUGIN_ZEEK_VERSION; } +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif Configuration(Configuration&& c) { bro_version = std::move(c.bro_version); @@ -136,10 +146,14 @@ public: description = std::move(c.description); version = std::move(c.version); } +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif Configuration(const Configuration& c) { bro_version = c.bro_version; @@ -149,10 +163,14 @@ public: description = c.description; version = c.version; } +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif Configuration& operator=(Configuration&& c) { bro_version = std::move(c.bro_version); @@ -164,10 +182,14 @@ public: return *this; } +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif Configuration& operator=(const Configuration& c) { bro_version = c.bro_version; @@ -179,12 +201,18 @@ public: return *this; } +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif ~Configuration() { } +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif /** * One can assign ZEEK_PLUGIN_ZEEK_VERSION to this to catch diff --git a/src/script_opt/ZAM/Stmt.cc b/src/script_opt/ZAM/Stmt.cc index 7bf47a8dc0..51e6d0e6e5 100644 --- a/src/script_opt/ZAM/Stmt.cc +++ b/src/script_opt/ZAM/Stmt.cc @@ -384,8 +384,10 @@ const ZAMStmt ZAMCompiler::GenCond(const Expr* e, int& branch_v) // from "ZAM-Conds.h". It really shouldn't worry about indentation mismatches // across included files since those are not indicative of possible // logic errors, but Oh Well. +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmisleading-indentation" +#endif switch ( e->Tag() ) { #include "ZAM-Conds.h" @@ -393,7 +395,9 @@ const ZAMStmt ZAMCompiler::GenCond(const Expr* e, int& branch_v) default: reporter->InternalError("bad expression type in ZAMCompiler::GenCond"); } +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif // Not reached. } diff --git a/src/supervisor/Supervisor.cc b/src/supervisor/Supervisor.cc index 4dde94d4cf..2ae656b8c9 100644 --- a/src/supervisor/Supervisor.cc +++ b/src/supervisor/Supervisor.cc @@ -41,7 +41,7 @@ extern "C" #include "zeek/zeek-affinity.h" #ifdef DEBUG -#define DBG_STEM(args...) stem->LogDebug(args); +#define DBG_STEM(...) stem->LogDebug(__VA_ARGS__); #else #define DBG_STEM #endif @@ -990,6 +990,7 @@ std::optional Stem::Poll() pfds[pfd_idx++] = {pipe->InFD(), POLLIN, 0}; pfds[pfd_idx++] = {signal_flare->FD(), POLLIN, 0}; +#if !defined(_MSC_VER) for ( const auto& [name, node] : nodes ) { node_pollfd_indices[name] = pfd_idx; @@ -1004,6 +1005,7 @@ std::optional Stem::Poll() else pfds[pfd_idx++] = {-1, POLLIN, 0}; } +#endif // Note: the poll timeout here is for periodically checking if the parent // process died (see below). @@ -1277,10 +1279,14 @@ Supervisor::NodeConfig Supervisor::NodeConfig::FromRecord(const RecordVal* node) for ( auto i = 0u; i < scripts_val->Size(); ++i ) { auto script = scripts_val->StringValAt(i)->ToStdString(); +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif rval.scripts.emplace_back(std::move(script)); +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif } auto env_table_val = node->GetField("env")->AsTableVal(); @@ -1364,10 +1370,14 @@ Supervisor::NodeConfig Supervisor::NodeConfig::FromJSON(std::string_view json) auto& scripts = j["scripts"]; for ( auto it = scripts.Begin(); it != scripts.End(); ++it ) +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif rval.scripts.emplace_back(it->GetString()); +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif auto& env = j["env"]; @@ -1447,10 +1457,14 @@ RecordValPtr Supervisor::NodeConfig::ToRecord() const auto st = rt->GetFieldType("scripts"); auto scripts_val = make_intrusive(std::move(st)); +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif for ( const auto& s : scripts ) +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif scripts_val->Assign(scripts_val->Size(), make_intrusive(s)); rval->AssignField("scripts", std::move(scripts_val)); @@ -1656,10 +1670,14 @@ void SupervisedNode::Init(Options* options) const stl.insert(stl.begin(), config.addl_base_scripts.begin(), config.addl_base_scripts.end()); stl.insert(stl.end(), config.addl_user_scripts.begin(), config.addl_user_scripts.end()); +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif stl.insert(stl.end(), config.scripts.begin(), config.scripts.end()); +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif } RecordValPtr Supervisor::Status(std::string_view node_name) diff --git a/src/supervisor/Supervisor.h b/src/supervisor/Supervisor.h index 93520854c1..cee3a758f2 100644 --- a/src/supervisor/Supervisor.h +++ b/src/supervisor/Supervisor.h @@ -143,8 +143,10 @@ public: */ struct NodeConfig { +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif // This block exists because the default implementations // themselves trigger deprecation warnings for accessing the // "scripts" field. It can go when we remove that deprecation. @@ -154,7 +156,9 @@ public: NodeConfig(NodeConfig&&) = default; ~NodeConfig() = default; NodeConfig& operator=(const NodeConfig&) = default; +#ifdef __GNUC__ #pragma GCC diagnostic pop +#endif /** * Create configuration from script-layer record value. diff --git a/src/telemetry/Counter.h b/src/telemetry/Counter.h index 6f5e360a89..afa836999a 100644 --- a/src/telemetry/Counter.h +++ b/src/telemetry/Counter.h @@ -57,7 +57,7 @@ public: /** * @return Whether @c this and @p other refer to the same counter. */ - constexpr bool IsSameAs(IntCounter other) const noexcept { return hdl == other.hdl; } + constexpr bool IsSameAs(const IntCounter& other) const noexcept { return hdl == other.hdl; } private: using Handle = broker::telemetry::int_counter_hdl*; @@ -72,13 +72,13 @@ private: * @return Whether @p lhs and @p rhs refer to the same object. * @note compare their @c value instead to check for equality. */ -constexpr bool operator==(IntCounter lhs, IntCounter rhs) noexcept +constexpr bool operator==(const IntCounter& lhs, const IntCounter& rhs) noexcept { return lhs.IsSameAs(rhs); } /// @relates IntCounter -constexpr bool operator!=(IntCounter lhs, IntCounter rhs) noexcept +constexpr bool operator!=(const IntCounter& lhs, const IntCounter& rhs) noexcept { return ! (lhs == rhs); } @@ -155,7 +155,7 @@ public: /** * @return Whether @c this and @p other refer to the same counter. */ - constexpr bool IsSameAs(DblCounter other) const noexcept { return hdl == other.hdl; } + constexpr bool IsSameAs(const DblCounter& other) const noexcept { return hdl == other.hdl; } private: using Handle = broker::telemetry::dbl_counter_hdl*; @@ -170,13 +170,13 @@ private: * @return Whether @p lhs and @p rhs refer to the same object. * @note compare their @c value instead to check for equality. */ -constexpr bool operator==(DblCounter lhs, DblCounter rhs) noexcept +constexpr bool operator==(const DblCounter& lhs, const DblCounter& rhs) noexcept { return lhs.IsSameAs(rhs); } /// @relates DblCounter -constexpr bool operator!=(DblCounter lhs, DblCounter rhs) noexcept +constexpr bool operator!=(const DblCounter& lhs, const DblCounter& rhs) noexcept { return ! (lhs == rhs); } diff --git a/src/telemetry/Gauge.h b/src/telemetry/Gauge.h index 294f9b1ab1..68cc6ca6e2 100644 --- a/src/telemetry/Gauge.h +++ b/src/telemetry/Gauge.h @@ -73,7 +73,7 @@ public: /** * @return Whether @c this and @p other refer to the same counter. */ - constexpr bool IsSameAs(IntGauge other) const noexcept { return hdl == other.hdl; } + constexpr bool IsSameAs(const IntGauge& other) const noexcept { return hdl == other.hdl; } private: using Handle = broker::telemetry::int_gauge_hdl*; @@ -88,13 +88,13 @@ private: * @return Whether @p lhs and @p rhs refer to the same object. * @note compare their @c value instead to check for equality. */ -constexpr bool operator==(IntGauge lhs, IntGauge rhs) noexcept +constexpr bool operator==(const IntGauge& lhs, const IntGauge& rhs) noexcept { return lhs.IsSameAs(rhs); } /// @relates IntGauge -constexpr bool operator!=(IntGauge lhs, IntGauge rhs) noexcept +constexpr bool operator!=(const IntGauge& lhs, const IntGauge& rhs) noexcept { return ! (lhs == rhs); } @@ -180,7 +180,7 @@ public: /** * @return Whether @c this and @p other refer to the same counter. */ - constexpr bool IsSameAs(DblGauge other) const noexcept { return hdl == other.hdl; } + constexpr bool IsSameAs(const DblGauge& other) const noexcept { return hdl == other.hdl; } private: using Handle = broker::telemetry::dbl_gauge_hdl*; @@ -195,13 +195,13 @@ private: * @return Whether @p lhs and @p rhs refer to the same object. * @note compare their @c value instead to check for equality. */ -constexpr bool operator==(DblGauge lhs, DblGauge rhs) noexcept +constexpr bool operator==(const DblGauge& lhs, const DblGauge& rhs) noexcept { return lhs.IsSameAs(rhs); } /// @relates DblGauge -constexpr bool operator!=(DblGauge lhs, DblGauge rhs) noexcept +constexpr bool operator!=(const DblGauge& lhs, const DblGauge& rhs) noexcept { return ! (lhs == rhs); } diff --git a/src/telemetry/Histogram.h b/src/telemetry/Histogram.h index 069c2fc38d..0ccfc823dd 100644 --- a/src/telemetry/Histogram.h +++ b/src/telemetry/Histogram.h @@ -60,7 +60,7 @@ public: /** * @return Whether @c this and @p other refer to the same histogram. */ - constexpr bool IsSameAs(IntHistogram other) const noexcept { return hdl == other.hdl; } + constexpr bool IsSameAs(const IntHistogram& other) const noexcept { return hdl == other.hdl; } private: using Handle = broker::telemetry::int_histogram_hdl*; @@ -74,13 +74,13 @@ private: * Checks whether two @ref IntHistogram handles are identical. * @return Whether @p lhs and @p rhs refer to the same object. */ -constexpr bool operator==(IntHistogram lhs, IntHistogram rhs) noexcept +constexpr bool operator==(const IntHistogram& lhs, const IntHistogram& rhs) noexcept { return lhs.IsSameAs(rhs); } /// @relates IntHistogram -constexpr bool operator!=(IntHistogram lhs, IntHistogram rhs) noexcept +constexpr bool operator!=(const IntHistogram& lhs, const IntHistogram& rhs) noexcept { return ! (lhs == rhs); } @@ -165,7 +165,7 @@ public: /** * @return Whether @c this and @p other refer to the same histogram. */ - constexpr bool IsSameAs(DblHistogram other) const noexcept { return hdl == other.hdl; } + constexpr bool IsSameAs(const DblHistogram& other) const noexcept { return hdl == other.hdl; } private: using Handle = broker::telemetry::dbl_histogram_hdl*; @@ -179,13 +179,13 @@ private: * Checks whether two @ref DblHistogram handles are identical. * @return Whether @p lhs and @p rhs refer to the same object. */ -constexpr bool operator==(DblHistogram lhs, DblHistogram rhs) noexcept +constexpr bool operator==(const DblHistogram& lhs, const DblHistogram& rhs) noexcept { return lhs.IsSameAs(rhs); } /// @relates DblHistogram -constexpr bool operator!=(DblHistogram lhs, DblHistogram rhs) noexcept +constexpr bool operator!=(const DblHistogram& lhs, const DblHistogram& rhs) noexcept { return ! (lhs == rhs); } diff --git a/src/threading/BasicThread.cc b/src/threading/BasicThread.cc index acb1b0087d..457906a152 100644 --- a/src/threading/BasicThread.cc +++ b/src/threading/BasicThread.cc @@ -48,9 +48,9 @@ void BasicThread::SetName(const char* arg_name) void BasicThread::SetOSName(const char* arg_name) { - static_assert(std::is_same::value, - "libstdc++ doesn't use pthread_t"); - util::detail::set_thread_name(arg_name, thread.native_handle()); + // Do it only if libc++ supports pthread_t. + if constexpr(std::is_same::value) + zeek::util::detail::set_thread_name(arg_name, reinterpret_cast(thread.native_handle())); } const char* BasicThread::Fmt(const char* format, ...) @@ -172,10 +172,9 @@ void BasicThread::Done() void* BasicThread::launcher(void* arg) { - static_assert(std::is_same::value, - "libstdc++ doesn't use pthread_t"); BasicThread* thread = (BasicThread*)arg; +#ifndef _MSC_VER // Block signals in thread. We handle signals only in the main // process. sigset_t mask_set; @@ -190,6 +189,7 @@ void* BasicThread::launcher(void* arg) sigdelset(&mask_set, SIGBUS); int res = pthread_sigmask(SIG_BLOCK, &mask_set, 0); assert(res == 0); +#endif // Run thread's main function. thread->Run(); diff --git a/src/threading/BasicThread.h b/src/threading/BasicThread.h index 9d78e8dd05..2afddab509 100644 --- a/src/threading/BasicThread.h +++ b/src/threading/BasicThread.h @@ -3,6 +3,7 @@ #include "zeek/zeek-config.h" +#include #include #include #include diff --git a/src/util.cc b/src/util.cc index 5530488e19..9f61daeb80 100644 --- a/src/util.cc +++ b/src/util.cc @@ -42,6 +42,9 @@ #include #include #include +#include +#include +#include #include "zeek/3rdparty/ConvertUTF.h" #include "zeek/3rdparty/doctest.h" @@ -51,6 +54,7 @@ #include "zeek/Obj.h" #include "zeek/Reporter.h" #include "zeek/RunState.h" +#include "zeek/ScannedFile.h" #include "zeek/Val.h" #include "zeek/digest.h" #include "zeek/input.h" @@ -67,6 +71,7 @@ static bool can_read(const string& path) } static string zeek_path_value; +const string zeek_path_list_separator(1, path_list_separator); namespace zeek::util { @@ -254,6 +259,16 @@ const char* fmt_access_time(double t) time_t time = (time_t)t; struct tm ts; + if (!time) + { + // Use wall clock. + struct timeval tv = { 0 }; + if (gettimeofday(&tv, 0) < 0) + reporter->InternalError("unable to gettimeofday"); + else + time = tv.tv_sec; + } + if ( ! localtime_r(&time, &ts) ) { reporter->InternalError("unable to get time"); @@ -432,6 +447,7 @@ void init_random_seed(const char* read_file, const char* write_file, bool use_em pos += sizeof(struct timeval) / sizeof(uint32_t); // use urandom. For reasons see e.g. http://www.2uo.de/myths-about-urandom/ +#ifndef _MSC_VER #if defined(O_NONBLOCK) int fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK); #elif defined(O_NDELAY) @@ -454,6 +470,12 @@ void init_random_seed(const char* read_file, const char* write_file, bool use_em errno = 0; } #endif + // C++ random device implementation in MSVC is sufficient for this purpose. + thread_local std::mt19937 gen(std::random_device{}()); + while ( pos < zeek::detail::KeyedHash::SEED_INIT_SIZE ) { + buf[pos++] = (uint32_t)gen(); + } +#endif if ( pos < zeek::detail::KeyedHash::SEED_INIT_SIZE ) reporter->FatalError("Could not read enough random data. Wanted %d, got %zu", @@ -554,7 +576,7 @@ void add_to_zeek_path(const string& dir) // Make sure path is initialized. zeek_path(); - zeek_path_value += string(":") + dir; + zeek_path_value += string(zeek_path_list_separator) + dir; } FILE* open_package(string& path, const string& mode) @@ -649,6 +671,12 @@ TEST_CASE("util normalize_path") string normalize_path(std::string_view path) { +#ifdef _MSC_VER + if (0 == path.compare(zeek::detail::ScannedFile::canonical_stdin_path)) { + return string(path); + } + return std::filesystem::canonical(path).string(); +#else if ( path.find("/.") == std::string_view::npos && path.find("//") == std::string_view::npos ) { // no need to normalize anything @@ -713,13 +741,14 @@ string normalize_path(std::string_view path) new_path.erase(new_path.size() - 1); return new_path; +#endif } string without_zeekpath_component(std::string_view path) { string rval = normalize_path(path); - const auto paths = tokenize_string(zeek_path(), ':'); + const auto paths = tokenize_string(zeek_path(), path_list_separator); for ( size_t i = 0; i < paths.size(); ++i ) { @@ -746,12 +775,13 @@ std::string get_exe_path(const std::string& invocation) { if ( invocation.empty() ) return ""; + std::filesystem::path invocation_path(invocation); - if ( invocation[0] == '/' || invocation[0] == '~' ) + if ( invocation_path.is_absolute() || invocation_path.root_directory() == "~" ) // Absolute path return invocation; - if ( invocation.find('/') != std::string::npos ) + if ( invocation_path.is_relative() ) { // Relative path char cwd[PATH_MAX]; @@ -762,7 +792,7 @@ std::string get_exe_path(const std::string& invocation) exit(1); } - return std::string(cwd) + "/" + invocation; + return (std::filesystem::path(cwd) / invocation_path).string(); } auto path = getenv("PATH"); @@ -1576,7 +1606,7 @@ const char* fmt_bytes(const char* data, int len) for ( int i = 0; i < len && p - buf < int(sizeof(buf)); ++i ) { - if ( isprint(data[i]) ) + if ( isprint((unsigned char)(data[i])) ) *p++ = data[i]; else p += snprintf(p, sizeof(buf) - (p - buf), "\\x%02x", (unsigned char)data[i]); @@ -1756,7 +1786,7 @@ string zeek_prefixes() for ( const auto& prefix : zeek::detail::zeek_script_prefixes ) { if ( ! rval.empty() ) - rval.append(":"); + rval.append(zeek_path_list_separator); rval.append(prefix); } @@ -1937,8 +1967,10 @@ static string find_file_in_path(const string& filename, const string& path, if ( filename.empty() ) return string(); + std::filesystem::path filepath(filename); + // If file name is an absolute path, searching within *path* is pointless. - if ( filename[0] == '/' ) + if ( filepath.is_absolute() ) { if ( can_read(filename) ) return filename; @@ -1946,7 +1978,7 @@ static string find_file_in_path(const string& filename, const string& path, return string(); } - string abs_path = path + '/' + filename; + auto abs_path = (std::filesystem::path(path) / filepath).string(); if ( ! opt_ext.empty() ) { @@ -1968,7 +2000,7 @@ static string find_file_in_path(const string& filename, const string& path, string find_file(const string& filename, const string& path_set, const string& opt_ext) { vector paths; - tokenize_string(path_set, ":", &paths); + tokenize_string(path_set, zeek_path_list_separator, &paths); vector ext; if ( ! opt_ext.empty() ) @@ -1988,7 +2020,7 @@ string find_file(const string& filename, const string& path_set, const string& o string find_script_file(const string& filename, const string& path_set) { vector paths; - tokenize_string(path_set, ":", &paths); + tokenize_string(path_set, zeek_path_list_separator, &paths); vector ext = {".zeek"}; diff --git a/src/util.h b/src/util.h index bdea606a8b..5acb449df7 100644 --- a/src/util.h +++ b/src/util.h @@ -15,6 +15,8 @@ #endif #include +#include + #include #include #include @@ -38,19 +40,23 @@ #endif #endif +#ifdef _MSC_VER +#include +#endif + #ifdef DEBUG #include #define ASSERT(x) assert(x) -#define DEBUG_MSG(x...) fprintf(stderr, x) +#define DEBUG_MSG(...) fprintf(stderr, __VA_ARGS__) #define DEBUG_fputs fputs #else #define ASSERT(x) -#define DEBUG_MSG(x...) -#define DEBUG_fputs(x...) +#define DEBUG_MSG(...) +#define DEBUG_fputs(...) #endif @@ -60,9 +66,10 @@ extern HeapLeakChecker* heap_checker; #endif -#include +#include #ifdef HAVE_LINUX +#include #include #endif @@ -70,12 +77,22 @@ extern HeapLeakChecker* heap_checker; #include #endif +#if defined(_MSC_VER) +const char path_list_separator = ';'; +#else +const char path_list_separator = ':'; +#endif + extern "C" { #include "zeek/3rdparty/modp_numtoa.h" } +#if defined(_MSC_VER) +#include +#else #include "zeek/3rdparty/ghc/filesystem.hpp" +#endif using zeek_int_t = int64_t; using zeek_uint_t = uint64_t; @@ -96,8 +113,12 @@ class ODesc; class RecordVal; // Expose ghc::filesystem as zeek::filesystem until we can -// switch to std::filesystem. +// switch to std::filesystem on all platforms. +#if defined(_MSC_VER) +namespace filesystem = std::filesystem; +#else namespace filesystem = ghc::filesystem; +#endif namespace util { diff --git a/src/zeek b/src/zeek deleted file mode 120000 index 945c9b46d6..0000000000 --- a/src/zeek +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file diff --git a/src/zeek-setup.cc b/src/zeek-setup.cc index 44bae3527d..676cc7a49d 100644 --- a/src/zeek-setup.cc +++ b/src/zeek-setup.cc @@ -49,6 +49,7 @@ #include "zeek/Traverse.h" #include "zeek/Trigger.h" #include "zeek/Var.h" + #include "zeek/analyzer/Manager.h" #include "zeek/binpac_zeek.h" #include "zeek/broker/Manager.h" @@ -63,6 +64,7 @@ #include "zeek/plugin/Manager.h" #include "zeek/script_opt/ScriptOpt.h" #include "zeek/session/Manager.h" +#include "zeek/script_opt/ScriptOpt.h" #include "zeek/supervisor/Supervisor.h" #include "zeek/telemetry/Manager.h" #include "zeek/threading/Manager.h" @@ -200,7 +202,11 @@ std::shared_ptr zeek::detail::sample_logger; zeek::detail::FragmentManager* zeek::detail::fragment_mgr = nullptr; int signal_val = 0; +#ifdef _MSC_VER +char version[] = VERSION; +#else extern char version[]; +#endif const char* zeek::detail::command_line_policy = nullptr; vector zeek::detail::params; set requested_plugins; @@ -236,6 +242,9 @@ char** zeek::detail::zeek_argv; namespace zeek { +// Define zeek version explicitly for MSVC + + const char* zeek_version() { #ifdef DEBUG diff --git a/src/zeek.bif b/src/zeek.bif index 11960435c2..e052392793 100644 --- a/src/zeek.bif +++ b/src/zeek.bif @@ -2226,7 +2226,7 @@ function is_local_interface%(ip: addr%) : bool %{ if ( ip->AsAddr().IsLoopback() ) return zeek::val_mgr->True(); - +#ifndef _MSC_VER list addrs; char host[MAXHOSTNAMELEN]; @@ -2259,7 +2259,7 @@ function is_local_interface%(ip: addr%) : bool if ( *it == ip->AsAddr() ) return zeek::val_mgr->True(); } - +#endif return zeek::val_mgr->False(); %} diff --git a/src/zeekygen/Target.cc b/src/zeekygen/Target.cc index 5236b8b070..eba9c81c83 100644 --- a/src/zeekygen/Target.cc +++ b/src/zeekygen/Target.cc @@ -2,7 +2,9 @@ #include "zeek/zeekygen/Target.h" +#ifndef _MSC_VER #include +#endif #include #include #include @@ -490,6 +492,8 @@ vector dir_contents_recursive(string dir) scan_path[0] = dir_copy; scan_path[1] = NULL; + // Zeekygen isn't supported in Windows, due to missing FTS library. +#ifndef _MSC_VER FTS* fts = fts_open(scan_path, FTS_NOCHDIR, 0); if ( ! fts ) @@ -516,6 +520,7 @@ vector dir_contents_recursive(string dir) delete[] scan_path; delete[] dir_copy; +#endif return rval; } diff --git a/zeek-config.h.in b/zeek-config.h.in index 5e68cff57a..d8601f7e3f 100644 --- a/zeek-config.h.in +++ b/zeek-config.h.in @@ -184,6 +184,7 @@ #define DLT_NFLOG @DLT_NFLOG@ #endif +#ifndef _MSC_VER /* IPv6 Next Header values defined by RFC 3542 */ #cmakedefine HAVE_IPPROTO_HOPOPTS #ifndef HAVE_IPPROTO_HOPOPTS @@ -225,7 +226,7 @@ #ifndef HAVE_IPPROTO_DSTOPTS #define IPPROTO_DSTOPTS 60 #endif - +#endif /* IPv6 options structure defined by RFC 3542 */ #cmakedefine HAVE_IP6_OPT diff --git a/zeek-path-dev.in b/zeek-path-dev.in index 6dcdc71c7c..0c5fa4fbd2 100755 --- a/zeek-path-dev.in +++ b/zeek-path-dev.in @@ -10,4 +10,4 @@ # ZEEKPATH=`./zeek-path-dev` ./src/zeek # -echo .:${PROJECT_SOURCE_DIR}/scripts:${PROJECT_SOURCE_DIR}/scripts/policy:${PROJECT_SOURCE_DIR}/scripts/site:${PROJECT_BINARY_DIR}/scripts:${PROJECT_BINARY_DIR}/scripts/builtin-plugins +echo .:${cmake_source_dir}/scripts:${cmake_source_dir}/scripts/policy:${cmake_source_dir}/scripts/site:${cmake_binary_dir}/scripts:${cmake_binary_dir}/scripts/builtin-plugins