mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
Merge remote-tracking branch 'origin/topic/robin/spicy-plugin'
* origin/topic/robin/spicy-plugin: Update doc submodule. Remove unused file. Move Spicy version information out of `zeek-config.h`. Revert unnecessary change to plugin class. Tweak format of `zkg` information in build info. Remove left-over file. Move `spicy/misc` scripts to policy and clarify purpose. Do not load Spicy scripts if Spicy is not available. Update comment. Use ccache on CI when compiling Spicy analyzers. Add `zkg_provides` to `--build-info`. Fix tuple type conversion. Fix generation of file IDs. Integrate the Spicy plugin into Zeek proper. Modernize plugin test.
This commit is contained in:
commit
85f8da6766
217 changed files with 10534 additions and 174 deletions
|
@ -160,6 +160,9 @@ env:
|
||||||
# a solution for the mtime pruning above.
|
# a solution for the mtime pruning above.
|
||||||
ZEEK_CCACHE_EPOCH: 2
|
ZEEK_CCACHE_EPOCH: 2
|
||||||
|
|
||||||
|
# Cache Spicy JIT results.
|
||||||
|
HILTI_CXX_COMPILER_LAUNCHER: ccache
|
||||||
|
|
||||||
# Linux EOL timelines: https://linuxlifecycle.com/
|
# Linux EOL timelines: https://linuxlifecycle.com/
|
||||||
# Fedora (~13 months): https://fedoraproject.org/wiki/Fedora_Release_Life_Cycle
|
# Fedora (~13 months): https://fedoraproject.org/wiki/Fedora_Release_Life_Cycle
|
||||||
|
|
||||||
|
|
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -58,9 +58,6 @@
|
||||||
[submodule "auxil/out_ptr"]
|
[submodule "auxil/out_ptr"]
|
||||||
path = auxil/out_ptr
|
path = auxil/out_ptr
|
||||||
url = https://github.com/soasis/out_ptr.git
|
url = https://github.com/soasis/out_ptr.git
|
||||||
[submodule "auxil/spicy-plugin"]
|
|
||||||
path = auxil/spicy-plugin
|
|
||||||
url = https://github.com/zeek/spicy-plugin
|
|
||||||
[submodule "auxil/spicy"]
|
[submodule "auxil/spicy"]
|
||||||
path = auxil/spicy/spicy
|
path = auxil/spicy/spicy
|
||||||
url = https://github.com/zeek/spicy
|
url = https://github.com/zeek/spicy
|
||||||
|
|
54
CHANGES
54
CHANGES
|
@ -1,3 +1,57 @@
|
||||||
|
6.0.0-dev.587 | 2023-05-16 11:40:40 +0200
|
||||||
|
|
||||||
|
* Integrate Spicy plugin into Zeek proper. (Robin Sommer, Corelight)
|
||||||
|
|
||||||
|
The plugin code is now a part of Zeek, located inside the standard
|
||||||
|
`src/` tree. Going forward, we will maintain it here and phase out
|
||||||
|
the external plugin.
|
||||||
|
|
||||||
|
The integration reflects the `spicy-plugin` code as of
|
||||||
|
`d8c296b81cc2a11`.
|
||||||
|
|
||||||
|
In addition to moving the code into Zeek's source tree, this comes
|
||||||
|
with a couple small functional changes:
|
||||||
|
|
||||||
|
- `spicyz` no longer tries to infer if it's running from the build
|
||||||
|
directory. Instead `ZEEK_SPICY_LIBRARY` can be set to a custom
|
||||||
|
location. `zeek-set-path.sh` does that now.
|
||||||
|
|
||||||
|
- ZEEK_CONFIG can be set to change what `spicyz -z` print out. This is
|
||||||
|
primarily for backwards compatibility.
|
||||||
|
|
||||||
|
The minimum Spicy version is now 1.8 (i.e., current `main` branch
|
||||||
|
at the time of merge).
|
||||||
|
|
||||||
|
For now, this all remains backwards compatible with the current
|
||||||
|
`zkg` analyzer templates so that they work with both external and
|
||||||
|
integrated Spicy support. Later, once we don't need to support any
|
||||||
|
external Spicy plugin versions anymore, we can clean up the
|
||||||
|
templates as well.
|
||||||
|
|
||||||
|
* Add `zkg_provides` to `--build-info`. (Robin Sommer, Corelight)
|
||||||
|
|
||||||
|
This makes dependencies explicit that Zeek provides built-in for
|
||||||
|
`zkg`. It's in support of
|
||||||
|
https://github.com/zeek/package-manager/pull/157.
|
||||||
|
|
||||||
|
For now, `zkg_provides` contains the same data as `included_plugins`
|
||||||
|
plus an entry for `spicy-plugin`.
|
||||||
|
|
||||||
|
* Fix Spicy tuple type conversion. (Robin Sommer, Corelight)
|
||||||
|
|
||||||
|
With an anonymous Spicy-side tuple type, we'd be missing an ID to
|
||||||
|
create a Zeek-side record, leading to undefined behavior. To still
|
||||||
|
support this case, we now make up an ID. In addition, we also could
|
||||||
|
end up not correctly tracking type ID during conversion; using a stack
|
||||||
|
now to handle recursion correctly.
|
||||||
|
|
||||||
|
* Fix generation of Spicy's file IDs. (Robin Sommer, Corelight)
|
||||||
|
|
||||||
|
They weren't stable, and potentially repetitive.
|
||||||
|
* Modernize plugin test. (Robin Sommer, Corelight)
|
||||||
|
|
||||||
|
Not using the `zeek/` include style could lead to path problems.
|
||||||
|
|
||||||
6.0.0-dev.570 | 2023-05-12 23:29:09 +0200
|
6.0.0-dev.570 | 2023-05-12 23:29:09 +0200
|
||||||
|
|
||||||
* Introduce ZEEK_SEED_VALUES environment variable (Arne Welzel, Corelight)
|
* Introduce ZEEK_SEED_VALUES environment variable (Arne Welzel, Corelight)
|
||||||
|
|
106
CMakeLists.txt
106
CMakeLists.txt
|
@ -497,17 +497,19 @@ file(
|
||||||
WRITE ${CMAKE_CURRENT_BINARY_DIR}/zeek-path-dev.sh
|
WRITE ${CMAKE_CURRENT_BINARY_DIR}/zeek-path-dev.sh
|
||||||
"export ZEEKPATH=`${cmake_binary_dir}/zeek-path-dev`\n"
|
"export ZEEKPATH=`${cmake_binary_dir}/zeek-path-dev`\n"
|
||||||
"export ZEEK_PLUGIN_PATH=\"${cmake_binary_dir}/src\":$\{ZEEK_PLUGIN_PATH\}\n"
|
"export ZEEK_PLUGIN_PATH=\"${cmake_binary_dir}/src\":$\{ZEEK_PLUGIN_PATH\}\n"
|
||||||
"export PATH=\"${cmake_binary_dir}\":\"${cmake_binary_dir}/src\":\"${cmake_binary_dir}/auxil/spicy/spicy/bin\":\"${cmake_binary_dir}/src/builtin-plugins/spicy-plugin/bin\":$\{PATH\}\n"
|
"export PATH=\"${cmake_binary_dir}\":\"${cmake_binary_dir}/src\":\"${cmake_binary_dir}/auxil/spicy/spicy/bin\":\"${cmake_binary_dir}/src/spicy/spicyz\":$\{PATH\}\n"
|
||||||
"export SPICY_PATH=`${cmake_binary_dir}/spicy-path`\n"
|
"export SPICY_PATH=`${cmake_binary_dir}/spicy-path`\n"
|
||||||
"export HILTI_CXX_INCLUDE_DIRS=`${cmake_binary_dir}/hilti-cxx-include-dirs`\n")
|
"export HILTI_CXX_INCLUDE_DIRS=`${cmake_binary_dir}/hilti-cxx-include-dirs`\n"
|
||||||
|
"export ZEEK_SPICY_LIBRARY_PATH=${cmake_source_dir}/scripts/spicy\n")
|
||||||
|
|
||||||
file(
|
file(
|
||||||
WRITE ${CMAKE_CURRENT_BINARY_DIR}/zeek-path-dev.csh
|
WRITE ${CMAKE_CURRENT_BINARY_DIR}/zeek-path-dev.csh
|
||||||
"setenv ZEEKPATH `${cmake_binary_dir}/zeek-path-dev`\n"
|
"setenv ZEEKPATH `${cmake_binary_dir}/zeek-path-dev`\n"
|
||||||
"setenv ZEEK_PLUGIN_PATH \"${cmake_binary_dir}/src\":$\{ZEEK_PLUGIN_PATH\}\n"
|
"setenv ZEEK_PLUGIN_PATH \"${cmake_binary_dir}/src\":$\{ZEEK_PLUGIN_PATH\}\n"
|
||||||
"setenv PATH \"${cmake_binary_dir}\":\"${cmake_binary_dir}/src\":\"${cmake_binary_dir}/auxil/spicy/spicy/bin\":\"${cmake_binary_dir}/src/builtin-plugins/spicy-plugin/bin\":$\{PATH\}\n"
|
"setenv PATH \"${cmake_binary_dir}\":\"${cmake_binary_dir}/src\":\"${cmake_binary_dir}/auxil/spicy/spicy/bin\":\"${cmake_binary_dir}/src/spicy/spicyz\":$\{PATH\}\n"
|
||||||
"setenv SPICY_PATH \"`${cmake_binary_dir}/spicy-path`\"\n"
|
"setenv SPICY_PATH \"`${cmake_binary_dir}/spicy-path`\"\n"
|
||||||
"setenv HILTI_CXX_INCLUDE_DIRS \"`${cmake_binary_dir}/hilti-cxx-include-dirs`\"\n")
|
"setenv HILTI_CXX_INCLUDE_DIRS \"`${cmake_binary_dir}/hilti-cxx-include-dirs`\"\n"
|
||||||
|
"setenv ZEEK_SPICY_LIBRARY_PATH \"${cmake_source_dir}/scripts/spicy\"\n")
|
||||||
|
|
||||||
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" VERSION LIMIT_COUNT 1)
|
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" VERSION LIMIT_COUNT 1)
|
||||||
execute_process(
|
execute_process(
|
||||||
|
@ -887,53 +889,28 @@ else ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (NOT DISABLE_SPICY)
|
if (NOT DISABLE_SPICY)
|
||||||
set(USE_SPICY_ANALYZERS yes)
|
if (SPICY_ROOT_DIR)
|
||||||
|
find_package(Spicy REQUIRED) # will set HAVE_SPICY
|
||||||
|
spicy_require_version("1.8.0")
|
||||||
|
|
||||||
if (NOT SPICY_ROOT_DIR)
|
if (NOT SPICY_HAVE_TOOLCHAIN)
|
||||||
set(HAVE_SPICY yes) # evaluated by Spicy plugin build
|
message(FATAL_ERROR "Spicy not built with toolchain support")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
spicy_print_summary()
|
||||||
|
else ()
|
||||||
|
set(HAVE_SPICY yes)
|
||||||
add_subdirectory(auxil/spicy)
|
add_subdirectory(auxil/spicy)
|
||||||
|
zeek_add_dependencies(spicy)
|
||||||
|
|
||||||
# Set variables used by the spicy-plugin build since we are building Spicy
|
|
||||||
# as part of Zeek so spicy-plugin cannot use `spicy-config` at configure
|
|
||||||
# time to set these.
|
|
||||||
set(SPICY_CONFIG "<builtin>")
|
|
||||||
set(SPICY_HAVE_TOOLCHAIN "YES")
|
|
||||||
set(SPICY_INCLUDE_DIRS_RUNTIME
|
|
||||||
${PROJECT_SOURCE_DIR}/auxil/spicy/spicy/hilti/runtime/include
|
|
||||||
${PROJECT_SOURCE_DIR}/auxil/spicy/spicy/spicy/runtime/include
|
|
||||||
${PROJECT_BINARY_DIR}/auxil/spicy/spicy/include)
|
|
||||||
set(SPICY_INCLUDE_DIRS_TOOLCHAIN
|
|
||||||
${PROJECT_SOURCE_DIR}/auxil/spicy/spicy/hilti/toolchain/include
|
|
||||||
${PROJECT_SOURCE_DIR}/auxil/spicy/spicy/spicy/toolchain/include)
|
|
||||||
set(SPICY_LIBRARY spicy)
|
|
||||||
set(HILTI_LIBRARY_RT hilti-rt)
|
|
||||||
set(HILTI_LIBRARY_RT_DEBUG hilti-rt-debug)
|
|
||||||
set(SPICY_LIBRARY_RT spicy-rt)
|
|
||||||
set(SPICY_LIBRARY_RT_DEBUG spicy-rt-debug)
|
|
||||||
|
|
||||||
# Needed only for logging from CMake configure phase.
|
|
||||||
get_directory_property(SPICY_VERSION DIRECTORY ${PROJECT_SOURCE_DIR}/auxil/spicy/spicy
|
|
||||||
DEFINITION SPICY_VERSION)
|
|
||||||
get_directory_property(
|
get_directory_property(
|
||||||
SPICY_VERSION_NUMBER DIRECTORY ${PROJECT_SOURCE_DIR}/auxil/spicy/spicy DEFINITION
|
SPICY_VERSION_NUMBER DIRECTORY ${PROJECT_SOURCE_DIR}/auxil/spicy/spicy DEFINITION
|
||||||
SPICY_VERSION_NUMBER)
|
SPICY_VERSION_NUMBER)
|
||||||
get_directory_property(SPICY_PREFIX DIRECTORY ${PROJECT_SOURCE_DIR}/auxil/spicy/spicy
|
|
||||||
DEFINITION CMAKE_INSTALL_PREFIX)
|
|
||||||
get_directory_property(SPICY_BUILD_MODE DIRECTORY ${PROJECT_SOURCE_DIR}/auxil/spicy/spicy
|
|
||||||
DEFINITION CMAKE_BUILD_TYPE)
|
|
||||||
set(SPICYC "<bundled>")
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (NOT SPICY_PLUGIN_PATH)
|
set(USE_SPICY_ANALYZERS yes)
|
||||||
set(_spicy_plugin "included")
|
|
||||||
set(SPICY_PLUGIN_PATH ${CMAKE_SOURCE_DIR}/auxil/spicy-plugin)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set(SPICY_PLUGIN_BINARY_PATH ${CMAKE_BINARY_DIR}/src/builtin-plugins/spicy-plugin)
|
|
||||||
list(APPEND ZEEK_INCLUDE_PLUGINS ${SPICY_PLUGIN_PATH})
|
|
||||||
else ()
|
else ()
|
||||||
set(HAVE_SPICY no) # evaluated by Spicy plugin build
|
set(HAVE_SPICY no)
|
||||||
set(USE_SPICY_ANALYZERS no)
|
set(USE_SPICY_ANALYZERS no)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
@ -1255,6 +1232,10 @@ add_subdirectory(scripts)
|
||||||
add_subdirectory(man)
|
add_subdirectory(man)
|
||||||
add_subdirectory(testing)
|
add_subdirectory(testing)
|
||||||
|
|
||||||
|
if (NOT DISABLE_SPICY)
|
||||||
|
zeek_add_dependencies(spicyz)
|
||||||
|
endif ()
|
||||||
|
|
||||||
include(CheckOptionalBuildSources)
|
include(CheckOptionalBuildSources)
|
||||||
|
|
||||||
checkoptionalbuildsources(auxil/btest BTest INSTALL_BTEST)
|
checkoptionalbuildsources(auxil/btest BTest INSTALL_BTEST)
|
||||||
|
@ -1264,37 +1245,8 @@ checkoptionalbuildsources(auxil/zeek-aux Zeek-Aux INSTALL_AUX_TOOLS)
|
||||||
checkoptionalbuildsources(auxil/zeek-archiver ZeekArchiver INSTALL_ZEEK_ARCHIVER)
|
checkoptionalbuildsources(auxil/zeek-archiver ZeekArchiver INSTALL_ZEEK_ARCHIVER)
|
||||||
checkoptionalbuildsources(auxil/zeek-client ZeekClient INSTALL_ZEEK_CLIENT)
|
checkoptionalbuildsources(auxil/zeek-client ZeekClient INSTALL_ZEEK_CLIENT)
|
||||||
|
|
||||||
if (NOT DISABLE_SPICY)
|
# Generate Spicy helper scripts referenced in e.g., `zeek-path-dev.*`. These
|
||||||
# The `zeek` binary implicitly depends on the driver object file built as part
|
# set Spicy-side environment variables to run it out of the build directory.
|
||||||
# of `spicy`; make that dependency explicit.
|
|
||||||
zeek_add_dependencies(spicyz)
|
|
||||||
|
|
||||||
if (NOT SPICY_ROOT_DIR)
|
|
||||||
# Make sure we build targets of spicy-plugin after the `spicy` target.
|
|
||||||
add_dependencies(plugin-Zeek-Spicy spicy)
|
|
||||||
add_dependencies(spicyz spicy)
|
|
||||||
|
|
||||||
# Also install spicy-plugin's CMake files into Zeek's global `cmake/`
|
|
||||||
# folder.
|
|
||||||
#
|
|
||||||
# NOTE: We do not install spicy-plugin's `FindZeek.cmake` since another
|
|
||||||
# version of this file is already provided by Zeek.
|
|
||||||
install(FILES auxil/spicy-plugin/cmake/ZeekSpicyAnalyzerSupport.cmake
|
|
||||||
auxil/spicy-plugin/cmake/FindSpicy.cmake DESTINATION share/zeek/cmake)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# Always generate helper scripts referenced in e.g., `zeek-path-dev.*` so the
|
|
||||||
# scripts work in any build configuration. If we do not include Spicy these
|
|
||||||
# files have no actual effect.
|
|
||||||
#
|
|
||||||
# Spicy JIT relies on the path of the current executable to figure out whether
|
|
||||||
# it is run from a build or an install tree. This assumption gets broken for
|
|
||||||
# e.g., `spicyz` when running from the build tree (probably fixable), and also
|
|
||||||
# when JIT'ing directly from a `zeek` invocation (much harder to fix). Instead
|
|
||||||
# we generate shell definitions to support running and using Spicy or
|
|
||||||
# spicy-plugin functionality in the build tree, including JIT'ing directly from
|
|
||||||
# Zeek.
|
|
||||||
configure_file(${CMAKE_SOURCE_DIR}/auxil/spicy/spicy-path.in ${CMAKE_BINARY_DIR}/spicy-path @ONLY)
|
configure_file(${CMAKE_SOURCE_DIR}/auxil/spicy/spicy-path.in ${CMAKE_BINARY_DIR}/spicy-path @ONLY)
|
||||||
configure_file(${CMAKE_SOURCE_DIR}/auxil/spicy/hilti-cxx-include-dirs.in
|
configure_file(${CMAKE_SOURCE_DIR}/auxil/spicy/hilti-cxx-include-dirs.in
|
||||||
${CMAKE_BINARY_DIR}/hilti-cxx-include-dirs @ONLY)
|
${CMAKE_BINARY_DIR}/hilti-cxx-include-dirs @ONLY)
|
||||||
|
@ -1375,12 +1327,6 @@ elseif (SPICY_ROOT_DIR)
|
||||||
set(_spicy "external (${SPICY_ROOT_DIR})")
|
set(_spicy "external (${SPICY_ROOT_DIR})")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (DISABLE_SPICY)
|
|
||||||
set(_spicy_plugin "disabled")
|
|
||||||
elseif ("${_spicy_plugin}" STREQUAL "")
|
|
||||||
set(_spicy_plugin "external (${SPICY_PLUGIN_PATH})")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (ZEEK_LEGACY_ANALYZERS)
|
if (ZEEK_LEGACY_ANALYZERS)
|
||||||
list(JOIN ZEEK_LEGACY_ANALYZERS ", " _legacy_analyzers)
|
list(JOIN ZEEK_LEGACY_ANALYZERS ", " _legacy_analyzers)
|
||||||
set(_legacy_analyzers
|
set(_legacy_analyzers
|
||||||
|
@ -1394,7 +1340,7 @@ endif ()
|
||||||
|
|
||||||
if (ZEEK_LEGACY_ANALYZERS OR ZEEK_SKIPPED_ANALYZERS)
|
if (ZEEK_LEGACY_ANALYZERS OR ZEEK_SKIPPED_ANALYZERS)
|
||||||
set(_analyzer_warning
|
set(_analyzer_warning
|
||||||
"\n\n[Warning] Some analyzers are not available due to lack of built-in Spicy support:${_legacy_analyzers}${_skipped_analyzers}"
|
"\n\n[Warning] Some analyzers are not available due to lack of Spicy support:${_legacy_analyzers}${_skipped_analyzers}"
|
||||||
)
|
)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
@ -1412,6 +1358,7 @@ message(
|
||||||
"\nScript dir: ${ZEEK_SCRIPT_INSTALL_PATH}"
|
"\nScript dir: ${ZEEK_SCRIPT_INSTALL_PATH}"
|
||||||
"\nSpool dir: ${ZEEK_SPOOL_DIR}"
|
"\nSpool dir: ${ZEEK_SPOOL_DIR}"
|
||||||
"\nState dir: ${ZEEK_STATE_DIR}"
|
"\nState dir: ${ZEEK_STATE_DIR}"
|
||||||
|
"\nSpicy modules dir: ${ZEEK_SPICY_MODULE_PATH}"
|
||||||
"\n"
|
"\n"
|
||||||
"\nDebug mode: ${ENABLE_DEBUG}"
|
"\nDebug mode: ${ENABLE_DEBUG}"
|
||||||
"\nUnit tests: ${ENABLE_ZEEK_UNIT_TESTS}"
|
"\nUnit tests: ${ENABLE_ZEEK_UNIT_TESTS}"
|
||||||
|
@ -1433,7 +1380,6 @@ message(
|
||||||
"\nGen-ZAM: ${_gen_zam_exe_path}"
|
"\nGen-ZAM: ${_gen_zam_exe_path}"
|
||||||
"\nzkg: ${INSTALL_ZKG}"
|
"\nzkg: ${INSTALL_ZKG}"
|
||||||
"\nSpicy: ${_spicy}"
|
"\nSpicy: ${_spicy}"
|
||||||
"\nSpicy plugin: ${_spicy_plugin}"
|
|
||||||
"\nSpicy analyzers: ${USE_SPICY_ANALYZERS}"
|
"\nSpicy analyzers: ${USE_SPICY_ANALYZERS}"
|
||||||
"\nJavaScript: ${ZEEK_HAVE_JAVASCRIPT}"
|
"\nJavaScript: ${ZEEK_HAVE_JAVASCRIPT}"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
6.0.0-dev.570
|
6.0.0-dev.587
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit a618f2ce0831c311f9bcff5d020b85fc44345221
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 64de5d0ef323428452827469f07b0a1da8e65e16
|
Subproject commit ec87b43037dba50648cb93be8940a4db23658905
|
|
@ -9,6 +9,7 @@ Example usage:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import copy
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import pathlib
|
import pathlib
|
||||||
|
@ -207,6 +208,11 @@ def main():
|
||||||
|
|
||||||
info["included_plugins"] = included_plugins_info
|
info["included_plugins"] = included_plugins_info
|
||||||
|
|
||||||
|
zkg_provides_info = copy.deepcopy(included_plugins_info)
|
||||||
|
# Hardcode the former spicy-plugin so that zkg knows Spicy is available.
|
||||||
|
zkg_provides_info.append({"name": "spicy-plugin", "version": info["version"].split("-")[0]})
|
||||||
|
info["zkg"] = {"provides": zkg_provides_info}
|
||||||
|
|
||||||
json_str = json.dumps(info, indent=2, sort_keys=True)
|
json_str = json.dumps(info, indent=2, sort_keys=True)
|
||||||
print(json_str)
|
print(json_str)
|
||||||
|
|
||||||
|
|
2
cmake
2
cmake
|
@ -1 +1 @@
|
||||||
Subproject commit a90d69179607c5083158f926be6d37f3db18f110
|
Subproject commit 643ca94ad9a425615414df942a4e8c8c553059b8
|
4
configure
vendored
4
configure
vendored
|
@ -104,7 +104,6 @@ Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
--with-python-inc=PATH path to Python headers
|
--with-python-inc=PATH path to Python headers
|
||||||
--with-python-lib=PATH path to libpython
|
--with-python-lib=PATH path to libpython
|
||||||
--with-spicy=PATH path to Spicy install root
|
--with-spicy=PATH path to Spicy install root
|
||||||
--with-spicy-plugin=PATH path to Spicy plugin source tree
|
|
||||||
--with-swig=PATH path to SWIG executable
|
--with-swig=PATH path to SWIG executable
|
||||||
|
|
||||||
Packaging Options (for developers):
|
Packaging Options (for developers):
|
||||||
|
@ -378,9 +377,6 @@ while [ $# -ne 0 ]; do
|
||||||
--with-spicy=*)
|
--with-spicy=*)
|
||||||
append_cache_entry SPICY_ROOT_DIR PATH $optarg
|
append_cache_entry SPICY_ROOT_DIR PATH $optarg
|
||||||
;;
|
;;
|
||||||
--with-spicy-plugin=*)
|
|
||||||
append_cache_entry SPICY_PLUGIN_PATH PATH $optarg
|
|
||||||
;;
|
|
||||||
--with-swig=*)
|
--with-swig=*)
|
||||||
append_cache_entry SWIG_EXECUTABLE PATH $optarg
|
append_cache_entry SWIG_EXECUTABLE PATH $optarg
|
||||||
;;
|
;;
|
||||||
|
|
2
doc
2
doc
|
@ -1 +1 @@
|
||||||
Subproject commit 40e049c138d830f4be5b9b12715f1244d18e23d8
|
Subproject commit 00fc392ac2d61faa40e15689acab77a6d3dc773d
|
1
scripts/base/frameworks/spicy/__load__.zeek
Normal file
1
scripts/base/frameworks/spicy/__load__.zeek
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@load ./main.zeek
|
38
scripts/base/frameworks/spicy/init-bare.zeek
Normal file
38
scripts/base/frameworks/spicy/init-bare.zeek
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
module Spicy;
|
||||||
|
|
||||||
|
export {
|
||||||
|
# doc-options-start
|
||||||
|
## Constant for testing if Spicy is available.
|
||||||
|
const available = T;
|
||||||
|
|
||||||
|
## Show output of Spicy print statements.
|
||||||
|
const enable_print = F &redef;
|
||||||
|
|
||||||
|
# Record and display profiling information, if compiled into analyzer.
|
||||||
|
const enable_profiling = F &redef;
|
||||||
|
|
||||||
|
## abort() instead of throwing HILTI exceptions.
|
||||||
|
const abort_on_exceptions = F &redef;
|
||||||
|
|
||||||
|
## Include backtraces when reporting unhandled exceptions.
|
||||||
|
const show_backtraces = F &redef;
|
||||||
|
|
||||||
|
## Maximum depth of recursive file analysis (Spicy analyzers only)
|
||||||
|
const max_file_depth: count = 5 &redef;
|
||||||
|
# doc-options-end
|
||||||
|
|
||||||
|
# doc-types-start
|
||||||
|
## Result type for `Spicy::resource_usage()`. The values reflect resource
|
||||||
|
## usage as reported by the Spicy runtime system.
|
||||||
|
type ResourceUsage: record {
|
||||||
|
user_time : interval; ##< user CPU time of the Zeek process
|
||||||
|
system_time :interval; ##< system CPU time of the Zeek process
|
||||||
|
memory_heap : count; ##< memory allocated on the heap by the Zeek process
|
||||||
|
num_fibers : count; ##< number of fibers currently in use
|
||||||
|
max_fibers: count; ##< maximum number of fibers ever in use
|
||||||
|
max_fiber_stack_size: count; ##< maximum fiber stack size ever in use
|
||||||
|
cached_fibers: count; ##< number of fibers currently cached
|
||||||
|
};
|
||||||
|
# doc-types-end
|
||||||
|
}
|
81
scripts/base/frameworks/spicy/init-framework.zeek
Normal file
81
scripts/base/frameworks/spicy/init-framework.zeek
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
@load base/misc/version
|
||||||
|
|
||||||
|
# doc-common-start
|
||||||
|
module Spicy;
|
||||||
|
|
||||||
|
export {
|
||||||
|
# doc-functions-start
|
||||||
|
## Enable a specific Spicy protocol analyzer if not already active. If this
|
||||||
|
## analyzer replaces an standard analyzer, that one will automatically be
|
||||||
|
## disabled.
|
||||||
|
##
|
||||||
|
## tag: analyzer to toggle
|
||||||
|
##
|
||||||
|
## Returns: true if the operation succeeded
|
||||||
|
global enable_protocol_analyzer: function(tag: Analyzer::Tag) : bool;
|
||||||
|
|
||||||
|
## Disable a specific Spicy protocol analyzer if not already inactive. If
|
||||||
|
## this analyzer replaces an standard analyzer, that one will automatically
|
||||||
|
## be re-enabled.
|
||||||
|
##
|
||||||
|
## tag: analyzer to toggle
|
||||||
|
##
|
||||||
|
## Returns: true if the operation succeeded
|
||||||
|
global disable_protocol_analyzer: function(tag: Analyzer::Tag) : bool;
|
||||||
|
|
||||||
|
|
||||||
|
## Enable a specific Spicy file analyzer if not already active. If this
|
||||||
|
## analyzer replaces an standard analyzer, that one will automatically be
|
||||||
|
## disabled.
|
||||||
|
##
|
||||||
|
## tag: analyzer to toggle
|
||||||
|
##
|
||||||
|
## Returns: true if the operation succeeded
|
||||||
|
global enable_file_analyzer: function(tag: Files::Tag) : bool;
|
||||||
|
|
||||||
|
## Disable a specific Spicy file analyzer if not already inactive. If
|
||||||
|
## this analyzer replaces an standard analyzer, that one will automatically
|
||||||
|
## be re-enabled.
|
||||||
|
##
|
||||||
|
## tag: analyzer to toggle
|
||||||
|
##
|
||||||
|
## Returns: true if the operation succeeded
|
||||||
|
global disable_file_analyzer: function(tag: Files::Tag) : bool;
|
||||||
|
|
||||||
|
## Returns current resource usage as reported by the Spicy runtime system.
|
||||||
|
global resource_usage: function() : ResourceUsage;
|
||||||
|
# doc-functions-end
|
||||||
|
}
|
||||||
|
|
||||||
|
# Marked with &is_used to suppress complaints when there aren't any
|
||||||
|
# Spicy file analyzers loaded, and hence this event can't be generated.
|
||||||
|
# The attribute is only supported for Zeek 5.0 and higher.
|
||||||
|
event spicy_analyzer_for_mime_type(a: Files::Tag, mt: string) &is_used
|
||||||
|
{
|
||||||
|
Files::register_for_mime_type(a, mt);
|
||||||
|
}
|
||||||
|
|
||||||
|
function enable_protocol_analyzer(tag: Analyzer::Tag) : bool
|
||||||
|
{
|
||||||
|
return Spicy::__toggle_analyzer(tag, T);
|
||||||
|
}
|
||||||
|
|
||||||
|
function disable_protocol_analyzer(tag: Analyzer::Tag) : bool
|
||||||
|
{
|
||||||
|
return Spicy::__toggle_analyzer(tag, F);
|
||||||
|
}
|
||||||
|
|
||||||
|
function enable_file_analyzer(tag: Files::Tag) : bool
|
||||||
|
{
|
||||||
|
return Spicy::__toggle_analyzer(tag, T);
|
||||||
|
}
|
||||||
|
|
||||||
|
function disable_file_analyzer(tag: Files::Tag) : bool
|
||||||
|
{
|
||||||
|
return Spicy::__toggle_analyzer(tag, F);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resource_usage() : ResourceUsage
|
||||||
|
{
|
||||||
|
return Spicy::__resource_usage();
|
||||||
|
}
|
15
scripts/base/frameworks/spicy/main.zeek
Normal file
15
scripts/base/frameworks/spicy/main.zeek
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
@load base/frameworks/notice
|
||||||
|
|
||||||
|
module Spicy;
|
||||||
|
|
||||||
|
export {
|
||||||
|
redef enum Notice::Type += { Spicy_Max_File_Depth_Exceeded };
|
||||||
|
}
|
||||||
|
|
||||||
|
event max_file_depth_exceeded(f: fa_file, args: Files::AnalyzerArgs, limit: count)
|
||||||
|
{
|
||||||
|
NOTICE([
|
||||||
|
$note=Spicy::Spicy_Max_File_Depth_Exceeded,
|
||||||
|
$msg=fmt("Maximum file depth exceeded for file %s", f$id)
|
||||||
|
]);
|
||||||
|
}
|
|
@ -5702,3 +5702,7 @@ event net_done(t: time)
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@load base/packet-protocols
|
@load base/packet-protocols
|
||||||
|
|
||||||
|
@if ( have_spicy() )
|
||||||
|
@load base/frameworks/spicy/init-bare
|
||||||
|
@endif
|
||||||
|
|
|
@ -44,6 +44,10 @@
|
||||||
@load base/frameworks/netcontrol
|
@load base/frameworks/netcontrol
|
||||||
@load base/frameworks/telemetry
|
@load base/frameworks/telemetry
|
||||||
|
|
||||||
|
@if ( have_spicy() )
|
||||||
|
@load base/frameworks/spicy
|
||||||
|
@endif
|
||||||
|
|
||||||
@load base/protocols/conn
|
@load base/protocols/conn
|
||||||
@load base/protocols/dce-rpc
|
@load base/protocols/dce-rpc
|
||||||
@load base/protocols/dhcp
|
@load base/protocols/dhcp
|
||||||
|
|
|
@ -17,6 +17,10 @@
|
||||||
# Load BiFs defined by plugins.
|
# Load BiFs defined by plugins.
|
||||||
@load base/bif/plugins
|
@load base/bif/plugins
|
||||||
|
|
||||||
|
@if ( have_spicy() )
|
||||||
|
@load base/frameworks/spicy/init-framework
|
||||||
|
@endif
|
||||||
|
|
||||||
# This sets up secondary/subdir BIFs such that they can be used by any
|
# This sets up secondary/subdir BIFs such that they can be used by any
|
||||||
# further scripts within their global initializations and is intended to be
|
# further scripts within their global initializations and is intended to be
|
||||||
# the last thing done within this script. It's called within @if simply so
|
# the last thing done within this script. It's called within @if simply so
|
||||||
|
|
90
scripts/policy/frameworks/spicy/record-spicy-batch.zeek
Normal file
90
scripts/policy/frameworks/spicy/record-spicy-batch.zeek
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
##! Saves all input traffic in Spicy's batch format.
|
||||||
|
|
||||||
|
module SpicyBatch;
|
||||||
|
|
||||||
|
export {
|
||||||
|
const filename = "batch.dat" &redef;
|
||||||
|
}
|
||||||
|
|
||||||
|
redef tcp_content_deliver_all_orig=T;
|
||||||
|
redef tcp_content_deliver_all_resp=T;
|
||||||
|
redef udp_content_deliver_all_orig=T;
|
||||||
|
redef udp_content_deliver_all_resp=T;
|
||||||
|
|
||||||
|
global output: file;
|
||||||
|
global conns: set[conn_id];
|
||||||
|
global num_conns = 0;
|
||||||
|
|
||||||
|
function id(c: connection) : string
|
||||||
|
{
|
||||||
|
local cid = c$id;
|
||||||
|
local proto = "???";
|
||||||
|
|
||||||
|
if ( is_tcp_port(cid$orig_p) )
|
||||||
|
proto = "tcp";
|
||||||
|
else if ( is_udp_port(cid$orig_p) )
|
||||||
|
proto = "udp";
|
||||||
|
else if ( is_icmp_port(cid$orig_p) )
|
||||||
|
proto = "icmp";
|
||||||
|
|
||||||
|
return fmt("%s-%d-%s-%d-%s", cid$orig_h, cid$orig_p, cid$resp_h, cid$resp_p, proto);
|
||||||
|
}
|
||||||
|
|
||||||
|
function begin(c: connection, type_: string)
|
||||||
|
{
|
||||||
|
add conns[c$id];
|
||||||
|
++num_conns;
|
||||||
|
print fmt("tracking %s", c$id);
|
||||||
|
|
||||||
|
local id_ = id(c);
|
||||||
|
print output, fmt("@begin-conn %s %s %s-orig %s%%orig %s-resp %s%%resp\n", id_, type_, id_, c$id$resp_p, id_, c$id$resp_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
event zeek_init()
|
||||||
|
{
|
||||||
|
output = open(filename);
|
||||||
|
enable_raw_output(output);
|
||||||
|
print output, "!spicy-batch v2\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
event new_connection_contents(c: connection)
|
||||||
|
{
|
||||||
|
begin(c, "stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
event tcp_contents(c: connection, is_orig: bool, seq: count, contents: string)
|
||||||
|
{
|
||||||
|
print output, fmt("@data %s-%s %d\n", id(c), (is_orig ? "orig" : "resp"), |contents|);
|
||||||
|
print output, contents;
|
||||||
|
print output, "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
event content_gap(c: connection, is_orig: bool, seq: count, length: count)
|
||||||
|
{
|
||||||
|
print output, fmt("@gap %s-%s %d\n", id(c), (is_orig ? "orig" : "resp"), length);
|
||||||
|
}
|
||||||
|
|
||||||
|
event udp_contents(c: connection, is_orig: bool, contents: string)
|
||||||
|
{
|
||||||
|
if ( c$id !in conns )
|
||||||
|
begin(c, "block");
|
||||||
|
|
||||||
|
print output, fmt("@data %s-%s %d\n", id(c), (is_orig ? "orig" : "resp"), |contents|);
|
||||||
|
print output, contents;
|
||||||
|
print output, "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
event connection_state_remove(c: connection)
|
||||||
|
{
|
||||||
|
if ( c$id !in conns )
|
||||||
|
return;
|
||||||
|
|
||||||
|
print output, fmt("@end-conn %s\n", id(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
event zeek_done()
|
||||||
|
{
|
||||||
|
close(output);
|
||||||
|
print fmt("recorded %d session%s total", num_conns, (num_conns > 1 ? "s" : ""));
|
||||||
|
print fmt("output in %s", filename);
|
||||||
|
}
|
20
scripts/policy/frameworks/spicy/resource-usage.zeek
Normal file
20
scripts/policy/frameworks/spicy/resource-usage.zeek
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
##! Logs Spicy-related resource usage continously for debugging purposes.
|
||||||
|
|
||||||
|
module Spicy;
|
||||||
|
|
||||||
|
event print_usage()
|
||||||
|
{
|
||||||
|
local r = Spicy::resource_usage();
|
||||||
|
|
||||||
|
print fmt("%.6f Spicy user=%f sys=%f heap=%d current_fibers=%d cached_fibers=%d max_fibers=%d max_stack=%d",
|
||||||
|
network_time(), r$user_time, r$system_time, r$memory_heap,
|
||||||
|
r$num_fibers, r$cached_fibers, r$max_fibers,
|
||||||
|
r$max_fiber_stack_size);
|
||||||
|
|
||||||
|
schedule 1 min { print_usage() };
|
||||||
|
}
|
||||||
|
|
||||||
|
event zeek_init()
|
||||||
|
{
|
||||||
|
schedule 1 min { print_usage() };
|
||||||
|
}
|
157
scripts/spicy/zeek.spicy
Normal file
157
scripts/spicy/zeek.spicy
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
# Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
|
||||||
|
|
||||||
|
module zeek;
|
||||||
|
|
||||||
|
# Note: Retain the formatting here, doc/scripts/autogen-spicy-lib is picking up on that.
|
||||||
|
|
||||||
|
%cxx-include = "zeek/spicy/runtime-support.h";
|
||||||
|
|
||||||
|
## [Deprecated] Triggers a DPD protocol confirmation for the current connection.
|
||||||
|
##
|
||||||
|
## This function has been deprecated and will be removed. Use ``spicy::accept_input``
|
||||||
|
## instead, which will have the same effect with Zeek.
|
||||||
|
public function confirm_protocol() : void &cxxname="zeek::spicy::rt::confirm_protocol";
|
||||||
|
|
||||||
|
## [Deprecated] Triggers a DPD protocol violation for the current connection.
|
||||||
|
##
|
||||||
|
## This function has been deprecated and will be removed. Use ``spicy::decline_input``
|
||||||
|
## instead, which will have the same effect with Zeek.
|
||||||
|
public function reject_protocol(reason: string) : void &cxxname="zeek::spicy::rt::reject_protocol";
|
||||||
|
|
||||||
|
## Reports a "weird" to Zeek. This should be used with similar semantics as in
|
||||||
|
## Zeek: something quite unexpected happening at the protocol level, which however
|
||||||
|
## does not prevent us from continuing to process the connection.
|
||||||
|
##
|
||||||
|
## id: the name of the weird, which (just like in Zeek) should be a *static*
|
||||||
|
## string identifying the situation reported (e.g., ``unexpected_command``).
|
||||||
|
##
|
||||||
|
## addl: additional information to record along with the weird
|
||||||
|
public function weird(id: string, addl: string = "") &cxxname="zeek::spicy::rt::weird";
|
||||||
|
|
||||||
|
## Returns true if we're currently parsing the originator side of a connection.
|
||||||
|
public function is_orig() : bool &cxxname="zeek::spicy::rt::is_orig";
|
||||||
|
|
||||||
|
## Returns the current connection's UID.
|
||||||
|
public function uid() : string &cxxname="zeek::spicy::rt::uid";
|
||||||
|
|
||||||
|
## Returns the current connection's 4-tuple ID.
|
||||||
|
public function conn_id() : tuple<orig_h: addr, orig_p: port, resp_h: addr, resp_p: port> &cxxname="zeek::spicy::rt::conn_id";
|
||||||
|
|
||||||
|
## Instructs Zeek to flip the directionality of the current connection.
|
||||||
|
public function flip_roles() : void &cxxname="zeek::spicy::rt::flip_roles";
|
||||||
|
|
||||||
|
## Returns the number of packets seen so far on the current side of the current connection.
|
||||||
|
public function number_packets() : uint64 &cxxname="zeek::spicy::rt::number_packets";
|
||||||
|
|
||||||
|
## Opaque handle to a protocol analyzer.
|
||||||
|
public type ProtocolHandle = __library_type("zeek::spicy::rt::ProtocolHandle");
|
||||||
|
|
||||||
|
## Adds a Zeek-side child protocol analyzer to the current connection.
|
||||||
|
##
|
||||||
|
## If the same analyzer was added previously with protocol_handle_get_or_create or
|
||||||
|
## protocol_begin with same argument, and not closed with protocol_handle_close
|
||||||
|
## or protocol_end, no new analyzer will be added.
|
||||||
|
##
|
||||||
|
## See `protocol_handle_get_or_create` for the error semantics of this function.
|
||||||
|
##
|
||||||
|
## analyzer: type of analyzer to instantiate, specified through its Zeek-side
|
||||||
|
## name (similar to what Zeek's signature action `enable` takes); if not
|
||||||
|
## specified, Zeek will perform its usual dynamic protocol detection to figure
|
||||||
|
## out how to parse the data (the latter will work only for TCP protocols, though.)
|
||||||
|
public function protocol_begin(analyzer: optional<string> = Null) : void &cxxname="zeek::spicy::rt::protocol_begin";
|
||||||
|
|
||||||
|
## Gets a handle to a Zeek-side child protocol analyzer for the current connection.
|
||||||
|
##
|
||||||
|
## If no such child exists it will be added; otherwise a handle to the
|
||||||
|
## existing child protocol analyzer will be returned.
|
||||||
|
##
|
||||||
|
## This function will return an error
|
||||||
|
##
|
||||||
|
## - if not called from a protocol analyzer, or
|
||||||
|
## - the requested child protocol analyzer is unknown, or
|
||||||
|
## - creation of a child analyzer of the requested type was prevented by a
|
||||||
|
## previous call of `disable_analyzer` with `prevent=T`
|
||||||
|
##
|
||||||
|
## analyzer: type of analyzer to instantiate, specified through its Zeek-side
|
||||||
|
## name (similar to what Zeek's signature action `enable` takes).
|
||||||
|
public function protocol_handle_get_or_create(analyzer: string) : ProtocolHandle &cxxname="zeek::spicy::rt::protocol_handle_get_or_create";
|
||||||
|
|
||||||
|
## Forwards protocol data to all previously instantiated Zeek-side child protocol analyzers.
|
||||||
|
##
|
||||||
|
## is_orig: true to feed the data to the child's originator side, false for the responder
|
||||||
|
## data: chunk of data to forward to child analyzer
|
||||||
|
## h: optional handle to the child analyzer to forward data into, else forward to all child analyzers
|
||||||
|
public function protocol_data_in(is_orig: bool, data: bytes, h: optional<ProtocolHandle> = Null) : void &cxxname="zeek::spicy::rt::protocol_data_in";
|
||||||
|
|
||||||
|
## Signals a gap in input data to all previously instantiated Zeek-side child protocol analyzers.
|
||||||
|
##
|
||||||
|
## is_orig: true to signal gap to the child's originator side, false for the responder
|
||||||
|
## offset: start offset of gap in input stream
|
||||||
|
## len: size of gap
|
||||||
|
## h: optional handle to the child analyzer signal a gap to, else signal to all child analyzers
|
||||||
|
public function protocol_gap(is_orig: bool, offset: uint64, len: uint64, h: optional<ProtocolHandle> = Null) : void &cxxname="zeek::spicy::rt::protocol_gap";
|
||||||
|
|
||||||
|
## Signals end-of-data to all previously instantiated Zeek-side child protocol
|
||||||
|
## analyzers and removes them.
|
||||||
|
public function protocol_end() : void &cxxname="zeek::spicy::rt::protocol_end";
|
||||||
|
|
||||||
|
## Signals end-of-data to the given child analyzer and removes it.
|
||||||
|
##
|
||||||
|
## The given handle must be live, i.e., it must not have been used in a
|
||||||
|
## previous protocol_handle_close call, and must not have been live when
|
||||||
|
## protocol_end was called. If the handle is not live a runtime error will
|
||||||
|
## be triggered.
|
||||||
|
##
|
||||||
|
## handle: handle to the child analyzer to remove
|
||||||
|
public function protocol_handle_close(handle: ProtocolHandle): void &cxxname="zeek::spicy::rt::protocol_handle_close";
|
||||||
|
|
||||||
|
## Signals the beginning of a file to Zeek's file analysis, associating it with the current connection.
|
||||||
|
## Optionally, a mime type can be provided. It will be passed on to Zeek's file analysis framework.
|
||||||
|
## Returns the Zeek-side file ID of the new file.
|
||||||
|
public function file_begin(mime_type: optional<string> = Null) : string &cxxname="zeek::spicy::rt::file_begin";
|
||||||
|
|
||||||
|
## Returns the current file's FUID.
|
||||||
|
public function fuid() : string &cxxname="zeek::spicy::rt::fuid";
|
||||||
|
|
||||||
|
## Terminates the currently active Zeek-side session, flushing all state. Any
|
||||||
|
## subsequent activity will start a new session from scratch. This can only be
|
||||||
|
## called from inside a protocol analyzer.
|
||||||
|
public function terminate_session() : void &cxxname="zeek::spicy::rt::terminate_session";
|
||||||
|
|
||||||
|
## Signals the expected size of a file to Zeek's file analysis.
|
||||||
|
##
|
||||||
|
## size: expected size of file
|
||||||
|
## fid: Zeek-side ID of the file to operate on; if not given, the file started by the most recent file_begin() will be used
|
||||||
|
public function file_set_size(size: uint64, fid: optional<string> = Null) : void &cxxname="zeek::spicy::rt::file_set_size";
|
||||||
|
|
||||||
|
## Passes file content on to Zeek's file analysis.
|
||||||
|
##
|
||||||
|
## data: chunk of raw data to pass into analysis
|
||||||
|
## fid: Zeek-side ID of the file to operate on; if not given, the file started by the most recent file_begin() will be used
|
||||||
|
public function file_data_in(data: bytes, fid: optional<string> = Null) : void &cxxname="zeek::spicy::rt::file_data_in";
|
||||||
|
|
||||||
|
## Passes file content at a specific offset on to Zeek's file analysis.
|
||||||
|
##
|
||||||
|
## data: chunk of raw data to pass into analysis
|
||||||
|
## offset: position in file where data starts
|
||||||
|
## fid: Zeek-side ID of the file to operate on; if not given, the file started by the most recent file_begin() will be used
|
||||||
|
public function file_data_in_at_offset(data: bytes, offset: uint64, fid: optional<string> = Null) : void &cxxname="zeek::spicy::rt::file_data_in_at_offset";
|
||||||
|
|
||||||
|
## Signals a gap in a file to Zeek's file analysis.
|
||||||
|
##
|
||||||
|
## offset: position in file where gap starts
|
||||||
|
## len: size of gap
|
||||||
|
## fid: Zeek-side ID of the file to operate on; if not given, the file started by the most recent file_begin() will be used
|
||||||
|
public function file_gap(offset: uint64, len: uint64, fid: optional<string> = Null) : void &cxxname="zeek::spicy::rt::file_gap";
|
||||||
|
|
||||||
|
## Signals the end of a file to Zeek's file analysis.
|
||||||
|
##
|
||||||
|
## fid: Zeek-side ID of the file to operate on; if not given, the file started by the most recent file_begin() will be used
|
||||||
|
public function file_end(fid: optional<string> = Null) : void &cxxname="zeek::spicy::rt::file_end";
|
||||||
|
|
||||||
|
## Inside a packet analyzer, forwards what data remains after parsing the top-level unit
|
||||||
|
## on to another analyzer. The index specifies the target, per the current dispatcher table.
|
||||||
|
public function forward_packet(identifier: uint32) : void &cxxname="zeek::spicy::rt::forward_packet";
|
||||||
|
|
||||||
|
## Gets the network time from Zeek.
|
||||||
|
public function network_time() : time &cxxname="zeek::spicy::rt::network_time";
|
31
scripts/spicy/zeek_file.spicy
Normal file
31
scripts/spicy/zeek_file.spicy
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
|
||||||
|
#
|
||||||
|
# TODO: This code would ideally just be a part of zeek.spicy, but that would
|
||||||
|
# come with compilation overhead currently even if not used, see
|
||||||
|
# https://github.com/zeek/spicy/issues/301.
|
||||||
|
|
||||||
|
module zeek_file;
|
||||||
|
|
||||||
|
import zeek;
|
||||||
|
|
||||||
|
## Convenience wrapper for passing content into Zeek's file analysis.
|
||||||
|
## After connecting an instance of this unit type to a sink, all data
|
||||||
|
## sent to the sink will be passed on to Zeek as a file.
|
||||||
|
##
|
||||||
|
## mime_type: MIME type of the file's content, if known; will be passed on to Zeek
|
||||||
|
## size: Total number of bytes the file contains, if known; will be passed on to Zeek
|
||||||
|
public type File = unit(mime_type: optional<string> = Null, size: optional<uint64> = Null) {
|
||||||
|
on %init {
|
||||||
|
self.fid = zeek::file_begin(mime_type);
|
||||||
|
|
||||||
|
if ( size )
|
||||||
|
zeek::file_set_size(*size, self.fid);
|
||||||
|
}
|
||||||
|
|
||||||
|
: bytes &chunked &eod { zeek::file_data_in($$, self.fid); }
|
||||||
|
|
||||||
|
on %finally { zeek::file_end(self.fid); }
|
||||||
|
|
||||||
|
## Zeek-side file ID
|
||||||
|
var fid: string;
|
||||||
|
};
|
43
scripts/spicy/zeek_rt.hlt
Normal file
43
scripts/spicy/zeek_rt.hlt
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
|
||||||
|
module zeek_rt {
|
||||||
|
|
||||||
|
import hilti;
|
||||||
|
|
||||||
|
%cxx-include = "zeek/spicy/runtime-support.h";
|
||||||
|
|
||||||
|
public type Val = __library_type("::zeek::ValPtr");
|
||||||
|
public type BroType = __library_type("::zeek::TypePtr");
|
||||||
|
public type EventHandlerPtr = __library_type("::zeek::EventHandlerPtr");
|
||||||
|
|
||||||
|
type ZeekTypeTag = enum {
|
||||||
|
Addr, Any, Bool, Count, Double, Enum, Error, File, Func, Int, Interval, List, Opaque, Pattern, Port, Record, String, Subnet, Table, Time, Type, Vector, Void
|
||||||
|
} &cxxname="::zeek::spicy::rt::ZeekTypeTag";
|
||||||
|
|
||||||
|
declare public void register_protocol_analyzer(string name, hilti::Protocol protocol, vector<port> ports, string parser_orig, string parser_resp, string replaces, string linker_scope) &cxxname="zeek::spicy::rt::register_protocol_analyzer" &have_prototype;
|
||||||
|
declare public void register_file_analyzer(string name, vector<string> mime_types, string parser, string replaces, string linker_scope) &cxxname="zeek::spicy::rt::register_file_analyzer" &have_prototype;
|
||||||
|
declare public void register_packet_analyzer(string name, string parser, string replaces, string linker_scope) &cxxname="zeek::spicy::rt::register_packet_analyzer" &have_prototype;
|
||||||
|
declare public void register_type(string ns, string id, BroType t) &cxxname="zeek::spicy::rt::register_type" &have_prototype;
|
||||||
|
|
||||||
|
declare public bool have_handler(EventHandlerPtr handler) &cxxname="zeek::spicy::rt::have_handler" &have_prototype;
|
||||||
|
declare public EventHandlerPtr internal_handler(string event) &cxxname="zeek::spicy::rt::internal_handler" &have_prototype;
|
||||||
|
declare public void install_handler(string event) &cxxname="zeek::spicy::rt::install_handler" &have_prototype;
|
||||||
|
|
||||||
|
declare public void raise_event(EventHandlerPtr handler, vector<Val> args) &cxxname="zeek::spicy::rt::raise_event" &have_prototype;
|
||||||
|
declare public BroType event_arg_type(EventHandlerPtr handler, uint<64> idx) &cxxname="zeek::spicy::rt::event_arg_type" &have_prototype;
|
||||||
|
declare public Val to_val(any x, BroType target) &cxxname="zeek::spicy::rt::to_val" &have_prototype;
|
||||||
|
|
||||||
|
type RecordField = tuple<string, BroType, bool>; # (ID, type, optional)
|
||||||
|
declare public BroType create_base_type(ZeekTypeTag tag) &cxxname="zeek::spicy::rt::create_base_type" &have_prototype;
|
||||||
|
declare public BroType create_enum_type(string ns, string id, vector<tuple<string, int<64>>> labels) &cxxname="zeek::spicy::rt::create_enum_type" &have_prototype;
|
||||||
|
declare public BroType create_record_type(string ns, string id, vector<RecordField> fields) &cxxname="zeek::spicy::rt::create_record_type" &have_prototype;
|
||||||
|
declare public BroType create_table_type(BroType key, optional<BroType> value = Null) &cxxname="zeek::spicy::rt::create_table_type" &have_prototype;
|
||||||
|
declare public BroType create_vector_type(BroType elem) &cxxname="zeek::spicy::rt::create_vector_type" &have_prototype;
|
||||||
|
|
||||||
|
declare public Val current_conn() &cxxname="zeek::spicy::rt::current_conn" &have_prototype;
|
||||||
|
declare public Val current_file() &cxxname="zeek::spicy::rt::current_file" &have_prototype;
|
||||||
|
declare public Val current_packet() &cxxname="zeek::spicy::rt::current_packet" &have_prototype;
|
||||||
|
declare public Val current_is_orig() &cxxname="zeek::spicy::rt::current_is_orig" &have_prototype;
|
||||||
|
|
||||||
|
declare public void debug(string msg) &cxxname="zeek::spicy::rt::debug" &have_prototype;
|
||||||
|
|
||||||
|
}
|
|
@ -72,6 +72,8 @@
|
||||||
@load frameworks/packet-filter/shunt.zeek
|
@load frameworks/packet-filter/shunt.zeek
|
||||||
@load frameworks/software/version-changes.zeek
|
@load frameworks/software/version-changes.zeek
|
||||||
@load frameworks/software/vulnerable.zeek
|
@load frameworks/software/vulnerable.zeek
|
||||||
|
# @load frameworks/spicy/record-spicy-batch.zeek
|
||||||
|
# @load frameworks/spicy/resource-usage.zeek
|
||||||
@load frameworks/software/windows-version-detection.zeek
|
@load frameworks/software/windows-version-detection.zeek
|
||||||
@load frameworks/telemetry/log.zeek
|
@load frameworks/telemetry/log.zeek
|
||||||
@load integration/collective-intel/__load__.zeek
|
@load integration/collective-intel/__load__.zeek
|
||||||
|
|
|
@ -13,6 +13,11 @@
|
||||||
@load policy/misc/dump-events.zeek
|
@load policy/misc/dump-events.zeek
|
||||||
@load policy/protocols/conn/speculative-service.zeek
|
@load policy/protocols/conn/speculative-service.zeek
|
||||||
|
|
||||||
|
@if ( have_spicy() )
|
||||||
|
@load frameworks/spicy/record-spicy-batch.zeek
|
||||||
|
@load frameworks/spicy/resource-usage.zeek
|
||||||
|
@endif
|
||||||
|
|
||||||
@load ./example.zeek
|
@load ./example.zeek
|
||||||
|
|
||||||
event zeek_init()
|
event zeek_init()
|
||||||
|
|
|
@ -172,6 +172,10 @@ add_subdirectory(logging)
|
||||||
add_subdirectory(probabilistic)
|
add_subdirectory(probabilistic)
|
||||||
add_subdirectory(session)
|
add_subdirectory(session)
|
||||||
|
|
||||||
|
if (HAVE_SPICY)
|
||||||
|
add_subdirectory(spicy)
|
||||||
|
endif ()
|
||||||
|
|
||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
# Build in the discovered external plugins and create the autogenerated scripts.
|
# Build in the discovered external plugins and create the autogenerated scripts.
|
||||||
|
|
||||||
|
@ -512,6 +516,10 @@ add_dependencies(zeek_objs zeek_autogen_files)
|
||||||
add_clang_tidy_files(${zeek_SRCS})
|
add_clang_tidy_files(${zeek_SRCS})
|
||||||
zeek_target_link_libraries(zeek_objs)
|
zeek_target_link_libraries(zeek_objs)
|
||||||
|
|
||||||
|
if (HAVE_SPICY)
|
||||||
|
target_link_libraries(zeek_objs PRIVATE hilti spicy)
|
||||||
|
endif ()
|
||||||
|
|
||||||
if (TARGET zeek_exe)
|
if (TARGET zeek_exe)
|
||||||
target_sources(zeek_exe PRIVATE main.cc ${zeek_HEADERS})
|
target_sources(zeek_exe PRIVATE main.cc ${zeek_HEADERS})
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,7 @@ DebugLogger::Stream DebugLogger::streams[NUM_DBGS] = {
|
||||||
{"logging", 0, false}, {"input", 0, false}, {"threading", 0, false},
|
{"logging", 0, false}, {"input", 0, false}, {"threading", 0, false},
|
||||||
{"plugins", 0, false}, {"zeekygen", 0, false}, {"pktio", 0, false},
|
{"plugins", 0, false}, {"zeekygen", 0, false}, {"pktio", 0, false},
|
||||||
{"broker", 0, false}, {"scripts", 0, false}, {"supervisor", 0, false},
|
{"broker", 0, false}, {"scripts", 0, false}, {"supervisor", 0, false},
|
||||||
{"hashkey", 0, false},
|
{"hashkey", 0, false}, {"spicy", 0, false}};
|
||||||
};
|
|
||||||
|
|
||||||
DebugLogger::DebugLogger()
|
DebugLogger::DebugLogger()
|
||||||
{
|
{
|
||||||
|
|
|
@ -57,6 +57,7 @@ enum DebugStream
|
||||||
DBG_SCRIPTS, // Script initialization
|
DBG_SCRIPTS, // Script initialization
|
||||||
DBG_SUPERVISOR, // Process supervisor
|
DBG_SUPERVISOR, // Process supervisor
|
||||||
DBG_HASHKEY, // HashKey buffers
|
DBG_HASHKEY, // HashKey buffers
|
||||||
|
DBG_SPICY, // Spicy functionality
|
||||||
|
|
||||||
NUM_DBGS // Has to be last
|
NUM_DBGS // Has to be last
|
||||||
};
|
};
|
||||||
|
|
132
src/spicy/.clang-format
Normal file
132
src/spicy/.clang-format
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlines: Right
|
||||||
|
AlignOperands: true
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: true
|
||||||
|
AllowShortFunctionsOnASingleLine: true
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: true
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
|
BraceWrapping:
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: false
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: false
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: true
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: false
|
||||||
|
SplitEmptyRecord: false
|
||||||
|
SplitEmptyNamespace: false
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
BreakBeforeInheritanceComma: false
|
||||||
|
BreakInheritanceList: BeforeColon
|
||||||
|
BreakBeforeTernaryOperators: false
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ColumnLimit: 120
|
||||||
|
CommentPragmas: 'NOLINT'
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
ForEachMacros:
|
||||||
|
- foreach
|
||||||
|
- Q_FOREACH
|
||||||
|
- BOOST_FOREACH
|
||||||
|
IncludeBlocks: Regroup
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: 'hilti/rt.*\.(h|hpp)>'
|
||||||
|
Priority: 5
|
||||||
|
- Regex: 'spicy/rt.*\.(h|hpp)>'
|
||||||
|
Priority: 6
|
||||||
|
- Regex: 'hilti.*\.(h|hpp)>'
|
||||||
|
Priority: 7
|
||||||
|
- Regex: 'spicy.*\.(h|hpp)>'
|
||||||
|
Priority: 8
|
||||||
|
- Regex: '<zeek-spicy\/'
|
||||||
|
Priority: 9
|
||||||
|
- Regex: '<zeek\/'
|
||||||
|
Priority: 10
|
||||||
|
- Regex: '^<([[:alnum:]]|_)+>'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '^<.*\.h>'
|
||||||
|
Priority: 1
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 11
|
||||||
|
IncludeIsMainRegex: '$'
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentWidth: 4
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
JavaScriptQuotes: Leave
|
||||||
|
JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
MacroBlockBegin: '^BEGIN_'
|
||||||
|
MacroBlockEnd: '^END_'
|
||||||
|
MaxEmptyLinesToKeep: 2
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCBinPackProtocolList: Auto
|
||||||
|
ObjCBlockIndentWidth: 2
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 500
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyBreakTemplateDeclaration: 10
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 1000
|
||||||
|
PointerAlignment: Left
|
||||||
|
ReflowComments: true
|
||||||
|
SortIncludes: true
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterTemplateKeyword: false
|
||||||
|
SpaceAfterLogicalNot: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInContainerLiterals: true
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
SpacesInConditionalStatement: true
|
||||||
|
Standard: Cpp11
|
||||||
|
StatementMacros:
|
||||||
|
- STANDARD_OPERATOR_1
|
||||||
|
TabWidth: 4
|
||||||
|
UseTab: Never
|
||||||
|
...
|
29
src/spicy/CMakeLists.txt
Normal file
29
src/spicy/CMakeLists.txt
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
add_subdirectory(spicyz)
|
||||||
|
|
||||||
|
zeek_add_subdir_library(
|
||||||
|
spicy
|
||||||
|
INTERNAL_DEPENDENCIES
|
||||||
|
${BIF_BUILD_TARGET}
|
||||||
|
INCLUDE_DIRS
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
SOURCES
|
||||||
|
manager.cc
|
||||||
|
file-analyzer.cc
|
||||||
|
packet-analyzer.cc
|
||||||
|
protocol-analyzer.cc
|
||||||
|
runtime-support.cc
|
||||||
|
BIFS
|
||||||
|
spicy.bif)
|
||||||
|
|
||||||
|
target_link_libraries(zeek_spicy_obj PRIVATE hilti spicy)
|
||||||
|
|
||||||
|
set(ZEEK_SPICY_MODULE_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/zeek/spicy" CACHE PATH "")
|
||||||
|
install(DIRECTORY DESTINATION "${ZEEK_SPICY_MODULE_PATH}")
|
||||||
|
|
||||||
|
set(ZEEK_SPICY_LIBRARY_PATH "${CMAKE_INSTALL_FULL_DATADIR}/zeek/spicy" CACHE PATH "")
|
||||||
|
install(DIRECTORY "${PROJECT_SOURCE_DIR}/scripts/spicy/" DESTINATION "${ZEEK_SPICY_LIBRARY_PATH}")
|
||||||
|
|
||||||
|
set(ZEEK_SPICY_DATA_PATH "${CMAKE_INSTALL_FULL_DATADIR}/zeek" CACHE PATH "")
|
233
src/spicy/cookie.h
Normal file
233
src/spicy/cookie.h
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cookie types that's stored in the HILTI context to provide access to the
|
||||||
|
* current analyzer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <variant>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "zeek/Val.h"
|
||||||
|
#include "zeek/analyzer/Analyzer.h"
|
||||||
|
#include "zeek/analyzer/protocol/tcp/TCP.h"
|
||||||
|
#include "zeek/file_analysis/Analyzer.h"
|
||||||
|
#include "zeek/packet_analysis/Analyzer.h"
|
||||||
|
|
||||||
|
namespace zeek::spicy::rt {
|
||||||
|
|
||||||
|
namespace cookie {
|
||||||
|
|
||||||
|
/** State representing analysis of one file. */
|
||||||
|
struct FileState {
|
||||||
|
FileState(std::string fid) : fid(std::move(fid)) {}
|
||||||
|
std::string fid; /**< unique Zeek-side file ID */
|
||||||
|
std::optional<std::string> mime_type; /**< MIME type, if explicitly set */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State stored inside protocol/file analyzer cookies retaining file analysis
|
||||||
|
* state.
|
||||||
|
*
|
||||||
|
* Internally, this maintains a stack of state objects representing individual
|
||||||
|
* files that are currently in-flight.
|
||||||
|
*/
|
||||||
|
class FileStateStack {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param analyzer_id unique ID string representing parent connection/file analyzer
|
||||||
|
*/
|
||||||
|
FileStateStack(std::string analyzer_id) : _analyzer_id(std::move(analyzer_id)) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Begins analysis for a new file, pushing a new state object onto the
|
||||||
|
* stack.
|
||||||
|
*/
|
||||||
|
FileState* push();
|
||||||
|
|
||||||
|
/** Returns true if the stack is currently empty. */
|
||||||
|
bool isEmpty() const { return _stack.empty(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an object from the stack.
|
||||||
|
*
|
||||||
|
* @param fid ID of file to remove state for; no-op if not found
|
||||||
|
*/
|
||||||
|
void remove(const std::string& fid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a pointer to the state of the most recently pushed file. Must not
|
||||||
|
* be called on an empty stack.
|
||||||
|
**/
|
||||||
|
const FileState* current() const {
|
||||||
|
assert(_stack.size());
|
||||||
|
return &_stack.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the state of a given file currently on the stack.
|
||||||
|
*
|
||||||
|
* @param fid ID of file to find
|
||||||
|
* @returns pointer to the file's state, or null if not found
|
||||||
|
*/
|
||||||
|
const FileState* find(const std::string& fid) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<FileState> _stack; // stack of files in flight
|
||||||
|
std::string _analyzer_id; // unique ID string of parent analyzer, as passed into ctor
|
||||||
|
uint64_t _id_counter = 0; // counter incremented for each file added to this stack
|
||||||
|
};
|
||||||
|
|
||||||
|
/** State on the current protocol analyzer. */
|
||||||
|
struct ProtocolAnalyzer {
|
||||||
|
analyzer::Analyzer* analyzer = nullptr; /**< current analyzer */
|
||||||
|
bool is_orig = false; /**< direction of the connection */
|
||||||
|
uint64_t num_packets = 0; /**< number of packets seen so far */
|
||||||
|
FileStateStack fstate_orig; /**< file analysis state for originator side */
|
||||||
|
FileStateStack fstate_resp; /**< file analysis state for responder side */
|
||||||
|
std::shared_ptr<packet_analysis::TCP::TCPSessionAdapter> fake_tcp; /**< fake TPC analyzer created internally */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** State on the current file analyzer. */
|
||||||
|
struct FileAnalyzer {
|
||||||
|
file_analysis::Analyzer* analyzer = nullptr; /**< current analyzer */
|
||||||
|
uint64_t depth = 0; /**< recursive depth of file analysis (Spicy-side file analysis only) */
|
||||||
|
FileStateStack fstate; /**< file analysis state for nested files */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** State on the current file analyzer. */
|
||||||
|
struct PacketAnalyzer {
|
||||||
|
packet_analysis::Analyzer* analyzer = nullptr; /**< current analyzer */
|
||||||
|
Packet* packet = nullptr; /**< current packet */
|
||||||
|
ValPtr packet_val = nullptr; /**< cached "raw_pkt_hdr" val for packet */
|
||||||
|
std::optional<uint32_t> next_analyzer;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cookie
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of state stored in HILTI's execution context during Spicy processing.
|
||||||
|
* This is optimized for fast access and small size.
|
||||||
|
*/
|
||||||
|
struct Cookie {
|
||||||
|
// Exactly one of these pointers is non-null at any time. In that way, the
|
||||||
|
// pointers provide the semantics of a tagged union. Internals are bit
|
||||||
|
// tricky because the union itself cannot be copied/moved.
|
||||||
|
cookie::ProtocolAnalyzer* protocol = nullptr;
|
||||||
|
cookie::FileAnalyzer* file = nullptr;
|
||||||
|
cookie::PacketAnalyzer* packet = nullptr;
|
||||||
|
|
||||||
|
Cookie(cookie::ProtocolAnalyzer&& c) : data(std::move(c)) { protocol = &data.protocol; }
|
||||||
|
Cookie(cookie::FileAnalyzer&& c) : data(std::move(c)) { file = &data.file; }
|
||||||
|
Cookie(cookie::PacketAnalyzer&& c) : data(std::move(c)) { packet = &data.packet; }
|
||||||
|
Cookie(Cookie&& other) noexcept : data(other.tag(), std::move(other.data)) { _initLike(other); }
|
||||||
|
~Cookie() { _delete(); }
|
||||||
|
|
||||||
|
Cookie& operator=(Cookie&& other) noexcept {
|
||||||
|
if ( this == &other )
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
_delete();
|
||||||
|
_initLike(other);
|
||||||
|
|
||||||
|
new (&data) Data(tag(), std::move(other.data));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache of values that can be expensive to compute.
|
||||||
|
struct {
|
||||||
|
ValPtr conn = nullptr; // valid only for protocol analyzers
|
||||||
|
ValPtr is_orig = nullptr; // valid only for protocol analyzers
|
||||||
|
bool confirmed = false; // valid only for protocol analyzers;
|
||||||
|
} cache;
|
||||||
|
|
||||||
|
enum Tag { Protocol, File, Packet };
|
||||||
|
|
||||||
|
/** Returns the type of cookie currently stored. */
|
||||||
|
Tag tag() const {
|
||||||
|
if ( protocol )
|
||||||
|
return Tag::Protocol;
|
||||||
|
else if ( file )
|
||||||
|
return Tag::File;
|
||||||
|
else if ( packet )
|
||||||
|
return Tag::Packet;
|
||||||
|
else
|
||||||
|
throw std::runtime_error("invalid cookie");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
union Data {
|
||||||
|
cookie::ProtocolAnalyzer protocol;
|
||||||
|
cookie::FileAnalyzer file;
|
||||||
|
cookie::PacketAnalyzer packet;
|
||||||
|
|
||||||
|
Data(cookie::ProtocolAnalyzer&& protocol) : protocol(std::move(protocol)) {}
|
||||||
|
Data(cookie::FileAnalyzer&& file) : file(std::move(file)) {}
|
||||||
|
Data(cookie::PacketAnalyzer&& packet) : packet(std::move(packet)) {}
|
||||||
|
Data(Tag tag, Data&& other) {
|
||||||
|
switch ( tag ) {
|
||||||
|
case Tag::Protocol: new (&protocol) cookie::ProtocolAnalyzer(std::move(other.protocol)); break;
|
||||||
|
case Tag::File: new (&file) cookie::FileAnalyzer(std::move(other.file)); break;
|
||||||
|
case Tag::Packet: new (&packet) cookie::PacketAnalyzer(std::move(other.packet)); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~Data() {
|
||||||
|
// don't delete anything, Cookie is in charge.
|
||||||
|
}
|
||||||
|
|
||||||
|
Data(const Data& other) = delete;
|
||||||
|
Data& operator=(const Data& other) = delete;
|
||||||
|
Data& operator=(Data&& other) = delete;
|
||||||
|
} data;
|
||||||
|
|
||||||
|
void _delete() {
|
||||||
|
if ( protocol ) {
|
||||||
|
data.protocol.~ProtocolAnalyzer();
|
||||||
|
protocol = nullptr;
|
||||||
|
cache.conn = nullptr;
|
||||||
|
cache.is_orig = nullptr;
|
||||||
|
cache.confirmed = false;
|
||||||
|
}
|
||||||
|
else if ( file ) {
|
||||||
|
data.file.~FileAnalyzer();
|
||||||
|
file = nullptr;
|
||||||
|
}
|
||||||
|
else if ( packet ) {
|
||||||
|
data.packet.~PacketAnalyzer();
|
||||||
|
packet = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _initLike(const Cookie& other) {
|
||||||
|
if ( other.protocol ) {
|
||||||
|
protocol = &data.protocol;
|
||||||
|
cache.confirmed = other.cache.confirmed;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if ( other.file )
|
||||||
|
file = &data.file;
|
||||||
|
|
||||||
|
else if ( other.packet )
|
||||||
|
packet = &data.packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cookie(const Cookie& other) = delete;
|
||||||
|
Cookie& operator=(const Cookie& other) = delete;
|
||||||
|
|
||||||
|
friend inline void swap(Cookie& lhs, Cookie& rhs) {
|
||||||
|
Cookie tmp = std::move(lhs);
|
||||||
|
lhs = std::move(rhs);
|
||||||
|
rhs = std::move(tmp);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace zeek::spicy::rt
|
138
src/spicy/file-analyzer.cc
Normal file
138
src/spicy/file-analyzer.cc
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#include "file-analyzer.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "spicy.bif.h"
|
||||||
|
#include "zeek/file_analysis/File.h"
|
||||||
|
#include "zeek/spicy/manager.h"
|
||||||
|
#include "zeek/spicy/runtime-support.h"
|
||||||
|
|
||||||
|
using namespace zeek;
|
||||||
|
using namespace zeek::spicy;
|
||||||
|
using namespace zeek::spicy::rt;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define STATE_DEBUG_MSG(...) DebugMsg(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define STATE_DEBUG_MSG(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void FileState::debug(const std::string& msg) { spicy::rt::debug(_cookie, msg); }
|
||||||
|
|
||||||
|
static auto create_file_state(FileAnalyzer* analyzer) {
|
||||||
|
uint64_t depth = 0;
|
||||||
|
if ( auto current_cookie = static_cast<Cookie*>(hilti::rt::context::cookie()) ) {
|
||||||
|
if ( const auto f = current_cookie->file )
|
||||||
|
depth = f->depth + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cookie::FileAnalyzer cookie{.analyzer = analyzer,
|
||||||
|
.depth = depth,
|
||||||
|
.fstate = cookie::FileStateStack(analyzer->GetFile()->GetID())};
|
||||||
|
return FileState(std::move(cookie));
|
||||||
|
}
|
||||||
|
|
||||||
|
FileAnalyzer::FileAnalyzer(RecordValPtr args, file_analysis::File* file)
|
||||||
|
: file_analysis::Analyzer(std::move(args), file), _state(create_file_state(this)) {}
|
||||||
|
|
||||||
|
FileAnalyzer::~FileAnalyzer() {}
|
||||||
|
|
||||||
|
void FileAnalyzer::Init() {}
|
||||||
|
|
||||||
|
void FileAnalyzer::Done() { Finish(); }
|
||||||
|
|
||||||
|
bool FileAnalyzer::DeliverStream(const u_char* data, uint64_t len) {
|
||||||
|
file_analysis::Analyzer::DeliverStream(data, len);
|
||||||
|
|
||||||
|
return Process(len, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileAnalyzer::Undelivered(uint64_t offset, uint64_t len) {
|
||||||
|
file_analysis::Analyzer::Undelivered(offset, len);
|
||||||
|
|
||||||
|
STATE_DEBUG_MSG("undelivered data, skipping further originator payload");
|
||||||
|
_state.skipRemaining();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileAnalyzer::EndOfFile() {
|
||||||
|
file_analysis::Analyzer::EndOfFile();
|
||||||
|
Finish();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileAnalyzer::Process(int len, const u_char* data) {
|
||||||
|
if ( ! _state.hasParser() && ! _state.isSkipping() ) {
|
||||||
|
auto parser = spicy_mgr->parserForFileAnalyzer(_state.file().analyzer->Tag());
|
||||||
|
if ( parser )
|
||||||
|
_state.setParser(parser);
|
||||||
|
else {
|
||||||
|
STATE_DEBUG_MSG("no unit specified for parsing");
|
||||||
|
_state.skipRemaining();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* file = _state.file().analyzer->GetFile();
|
||||||
|
|
||||||
|
const auto& max_file_depth = BifConst::Spicy::max_file_depth;
|
||||||
|
|
||||||
|
if ( _state.file().depth >= max_file_depth ) {
|
||||||
|
const auto& file_val = file->ToVal();
|
||||||
|
|
||||||
|
const auto analyzer_args = _state.file().analyzer->GetArgs();
|
||||||
|
|
||||||
|
file->FileEvent(Spicy::max_file_depth_exceeded, {file_val, analyzer_args, val_mgr->Count(_state.file().depth)});
|
||||||
|
|
||||||
|
auto tag = spicy_mgr->tagForFileAnalyzer(_state.file().analyzer->Tag());
|
||||||
|
#if ZEEK_VERSION_NUMBER >= 50200
|
||||||
|
AnalyzerViolation("maximal file depth exceeded", reinterpret_cast<const char*>(data), len, tag);
|
||||||
|
#else
|
||||||
|
// We don't have an an appropriate way to report this with older Zeeks.
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
hilti::rt::context::CookieSetter _(_state.cookie());
|
||||||
|
_state.process(len, reinterpret_cast<const char*>(data));
|
||||||
|
} catch ( const hilti::rt::RuntimeError& e ) {
|
||||||
|
STATE_DEBUG_MSG(hilti::rt::fmt("error during parsing, triggering analyzer violation: %s", e.what()));
|
||||||
|
auto tag = spicy_mgr->tagForFileAnalyzer(_state.file().analyzer->Tag());
|
||||||
|
#if ZEEK_VERSION_NUMBER >= 50200
|
||||||
|
AnalyzerViolation(e.what(), reinterpret_cast<const char*>(data), len, tag);
|
||||||
|
#else
|
||||||
|
// We don't have an an appropriate way to report this with older Zeeks.
|
||||||
|
#endif
|
||||||
|
} catch ( const hilti::rt::Exception& e ) {
|
||||||
|
STATE_DEBUG_MSG(e.what());
|
||||||
|
spicy_mgr->analyzerError(_state.file().analyzer, e.description(),
|
||||||
|
e.location()); // this sets Zeek to skip sending any further input
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileAnalyzer::Finish() {
|
||||||
|
try {
|
||||||
|
hilti::rt::context::CookieSetter _(_state.cookie());
|
||||||
|
_state.finish();
|
||||||
|
} catch ( const hilti::rt::RuntimeError& e ) {
|
||||||
|
STATE_DEBUG_MSG(hilti::rt::fmt("error during parsing, triggering analyzer violation: %s", e.what()));
|
||||||
|
auto tag = spicy_mgr->tagForFileAnalyzer(_state.file().analyzer->Tag());
|
||||||
|
#if ZEEK_VERSION_NUMBER >= 50200
|
||||||
|
AnalyzerViolation(e.what(), "", 0, tag);
|
||||||
|
#else
|
||||||
|
// We don't have an an appropriate way to report this with older Zeeks.
|
||||||
|
#endif
|
||||||
|
} catch ( const hilti::rt::Exception& e ) {
|
||||||
|
spicy_mgr->analyzerError(_state.file().analyzer, e.description(),
|
||||||
|
e.location()); // this sets Zeek to skip sending any further input
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file_analysis::Analyzer* FileAnalyzer::InstantiateAnalyzer(RecordValPtr args, file_analysis::File* file) {
|
||||||
|
return new FileAnalyzer(std::move(args), file);
|
||||||
|
}
|
91
src/spicy/file-analyzer.h
Normal file
91
src/spicy/file-analyzer.h
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <hilti/rt/types/stream.h>
|
||||||
|
|
||||||
|
#include <spicy/rt/driver.h>
|
||||||
|
#include <spicy/rt/parser.h>
|
||||||
|
|
||||||
|
#include "zeek/spicy/cookie.h"
|
||||||
|
|
||||||
|
namespace zeek::spicy::rt {
|
||||||
|
|
||||||
|
/** Parsing state for a file. */
|
||||||
|
class FileState : public ::spicy::rt::driver::ParsingState {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param cookie cookie to associated with the file
|
||||||
|
*/
|
||||||
|
FileState(Cookie cookie) : ParsingState(::spicy::rt::driver::ParsingType::Stream), _cookie(std::move(cookie)) {}
|
||||||
|
|
||||||
|
/** Returns the cookie pointer to use with the runtime library during analysis. */
|
||||||
|
auto* cookie() { return &_cookie; }
|
||||||
|
|
||||||
|
/** Returns the file-specific cookie state associated with the endpoint. */
|
||||||
|
auto& file() {
|
||||||
|
assert(_cookie.file);
|
||||||
|
return *_cookie.file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Records a debug message pertaining to the specific file.
|
||||||
|
*
|
||||||
|
* @param msg message to record
|
||||||
|
*/
|
||||||
|
void DebugMsg(const std::string& msg) { debug(msg); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Overridden from driver::ParsingState.
|
||||||
|
void debug(const std::string& msg) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Cookie _cookie;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A Spicy file analyzer. */
|
||||||
|
class FileAnalyzer : public file_analysis::Analyzer {
|
||||||
|
public:
|
||||||
|
FileAnalyzer(RecordValPtr arg_args, file_analysis::File* arg_file);
|
||||||
|
virtual ~FileAnalyzer();
|
||||||
|
|
||||||
|
static file_analysis::Analyzer* InstantiateAnalyzer(RecordValPtr args, file_analysis::File* file);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Overridden from Zeek's file analyzer.
|
||||||
|
void Init() override;
|
||||||
|
void Done() override;
|
||||||
|
bool DeliverStream(const u_char* data, uint64_t len) override;
|
||||||
|
bool Undelivered(uint64_t offset, uint64_t len) override;
|
||||||
|
bool EndOfFile() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Feeds a chunk of data into parsing.
|
||||||
|
*
|
||||||
|
* @param len number of bytes valid in *data*
|
||||||
|
* @param data pointer to data
|
||||||
|
* @return true if processing succeeded, false if an error occurred that
|
||||||
|
* stopped parsing
|
||||||
|
*/
|
||||||
|
bool Process(int len, const u_char* data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalizes parsing. After calling this, no more data can be passed into
|
||||||
|
* Process().
|
||||||
|
*/
|
||||||
|
void Finish();
|
||||||
|
|
||||||
|
/** Records a debug message. */
|
||||||
|
void DebugMsg(const std::string& msg) { _state.DebugMsg(msg); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
FileState _state;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace zeek::spicy::rt
|
919
src/spicy/manager.cc
Normal file
919
src/spicy/manager.cc
Normal file
|
@ -0,0 +1,919 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#include "zeek/spicy/manager.h"
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <glob.h>
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <hilti/rt/configuration.h>
|
||||||
|
#include <hilti/rt/filesystem.h>
|
||||||
|
#include <hilti/rt/fmt.h>
|
||||||
|
#include <hilti/rt/init.h>
|
||||||
|
#include <hilti/rt/library.h>
|
||||||
|
#include <hilti/rt/logging.h>
|
||||||
|
#include <hilti/rt/types/vector.h>
|
||||||
|
#include <hilti/rt/util.h>
|
||||||
|
|
||||||
|
#include <spicy/rt/configuration.h>
|
||||||
|
#include <spicy/rt/init.h>
|
||||||
|
#include <spicy/rt/parser.h>
|
||||||
|
|
||||||
|
#include <hilti/autogen/config.h>
|
||||||
|
|
||||||
|
#include <zeek/analyzer/Manager.h>
|
||||||
|
#include <zeek/file_analysis/Manager.h>
|
||||||
|
#include <zeek/packet_analysis/Manager.h>
|
||||||
|
|
||||||
|
#include "zeek/DebugLogger.h"
|
||||||
|
#include "zeek/spicy/file-analyzer.h"
|
||||||
|
#include "zeek/spicy/packet-analyzer.h"
|
||||||
|
#include "zeek/spicy/protocol-analyzer.h"
|
||||||
|
#include "zeek/util-config.h"
|
||||||
|
|
||||||
|
using namespace zeek;
|
||||||
|
using namespace zeek::spicy;
|
||||||
|
|
||||||
|
// Split an potentially scoped ID into namespace and local part.
|
||||||
|
static std::pair<std::string, std::string> parseID(const std::string& s) {
|
||||||
|
if ( auto i = s.rfind("::"); i != std::string::npos )
|
||||||
|
return std::make_pair(s.substr(0, i), s.substr(i + 2));
|
||||||
|
else
|
||||||
|
return std::make_pair("", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
Manager::~Manager() {}
|
||||||
|
|
||||||
|
void Manager::registerProtocolAnalyzer(const std::string& name, hilti::rt::Protocol proto,
|
||||||
|
const hilti::rt::Vector<hilti::rt::Port>& ports, const std::string& parser_orig,
|
||||||
|
const std::string& parser_resp, const std::string& replaces,
|
||||||
|
const std::string& linker_scope) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Have Spicy protocol analyzer %s", name));
|
||||||
|
|
||||||
|
ProtocolAnalyzerInfo info;
|
||||||
|
info.name_analyzer = name;
|
||||||
|
info.name_parser_orig = parser_orig;
|
||||||
|
info.name_parser_resp = parser_resp;
|
||||||
|
info.name_replaces = replaces;
|
||||||
|
info.name_zeek = hilti::rt::replace(name, "::", "_");
|
||||||
|
info.name_zeekygen = hilti::rt::fmt("<Spicy-%s>", name);
|
||||||
|
info.protocol = proto;
|
||||||
|
info.ports = ports;
|
||||||
|
info.linker_scope = linker_scope;
|
||||||
|
|
||||||
|
// We may have that analyzer already iff it was previously pre-registered
|
||||||
|
// without a linker scope. We'll then only set the scope now.
|
||||||
|
if ( auto t = _analyzer_name_to_tag_type.find(info.name_zeek); t != _analyzer_name_to_tag_type.end() ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Updating already registered protocol analyzer %s", name));
|
||||||
|
|
||||||
|
auto& existing = _protocol_analyzers_by_type.at(t->second);
|
||||||
|
assert(existing.name_analyzer == name);
|
||||||
|
existing.linker_scope = info.linker_scope;
|
||||||
|
|
||||||
|
// If the infos don't match now, we have two separate definitions.
|
||||||
|
if ( info != existing )
|
||||||
|
reporter->FatalError("redefinition of protocol analyzer %s", info.name_analyzer.c_str());
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
analyzer::Component::factory_callback factory = nullptr;
|
||||||
|
|
||||||
|
#if SPICY_VERSION_NUMBER >= 10700
|
||||||
|
auto proto_ = proto.value();
|
||||||
|
#else
|
||||||
|
auto proto_ = proto;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch ( proto_ ) {
|
||||||
|
case hilti::rt::Protocol::TCP: factory = spicy::rt::TCP_Analyzer::InstantiateAnalyzer; break;
|
||||||
|
case hilti::rt::Protocol::UDP: factory = spicy::rt::UDP_Analyzer::InstantiateAnalyzer; break;
|
||||||
|
default: reporter->Error("unsupported protocol in analyzer"); return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto c = new ::zeek::analyzer::Component(info.name_zeek, factory, 0);
|
||||||
|
AddComponent(c);
|
||||||
|
|
||||||
|
// Hack to prevent Zeekygen from reporting the ID as not having a
|
||||||
|
// location during the following initialization step.
|
||||||
|
::zeek::detail::zeekygen_mgr->Script(info.name_zeekygen);
|
||||||
|
::zeek::detail::set_location(makeLocation(info.name_zeekygen));
|
||||||
|
|
||||||
|
// TODO: Should Zeek do this? It has run component intiialization at
|
||||||
|
// this point already, so ours won't get initialized anymore.
|
||||||
|
c->Initialize();
|
||||||
|
|
||||||
|
trackComponent(c, c->Tag().Type()); // Must come after Initialize().
|
||||||
|
|
||||||
|
info.type = c->Tag().Type();
|
||||||
|
_protocol_analyzers_by_type.resize(info.type + 1);
|
||||||
|
_protocol_analyzers_by_type[info.type] = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::registerFileAnalyzer(const std::string& name, const hilti::rt::Vector<std::string>& mime_types,
|
||||||
|
const std::string& parser, const std::string& replaces,
|
||||||
|
const std::string& linker_scope) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Have Spicy file analyzer %s", name));
|
||||||
|
|
||||||
|
FileAnalyzerInfo info;
|
||||||
|
info.name_analyzer = name;
|
||||||
|
info.name_parser = parser;
|
||||||
|
info.name_replaces = replaces;
|
||||||
|
info.name_zeek = hilti::rt::replace(name, "::", "_");
|
||||||
|
info.name_zeekygen = hilti::rt::fmt("<Spicy-%s>", name);
|
||||||
|
info.mime_types = mime_types;
|
||||||
|
info.linker_scope = linker_scope;
|
||||||
|
|
||||||
|
// We may have that analyzer already iff it was previously pre-registered
|
||||||
|
// without a linker scope. We'll then only set the scope now.
|
||||||
|
if ( auto t = _analyzer_name_to_tag_type.find(info.name_zeek); t != _analyzer_name_to_tag_type.end() ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Updating already registered packet analyzer %s", name));
|
||||||
|
|
||||||
|
auto& existing = _file_analyzers_by_type.at(t->second);
|
||||||
|
existing.linker_scope = info.linker_scope;
|
||||||
|
|
||||||
|
// If the infos don't match now, we have two separate definitions.
|
||||||
|
if ( info != existing )
|
||||||
|
reporter->FatalError("redefinition of file analyzer %s", info.name_analyzer.c_str());
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto c = new ::zeek::file_analysis::Component(info.name_zeek, spicy::rt::FileAnalyzer::InstantiateAnalyzer, 0);
|
||||||
|
AddComponent(c);
|
||||||
|
|
||||||
|
// Hack to prevent Zeekygen from reporting the ID as not having a
|
||||||
|
// location during the following initialization step.
|
||||||
|
::zeek::detail::zeekygen_mgr->Script(info.name_zeekygen);
|
||||||
|
::zeek::detail::set_location(makeLocation(info.name_zeekygen));
|
||||||
|
|
||||||
|
// TODO: Should Zeek do this? It has run component intiialization at
|
||||||
|
// this point already, so ours won't get initialized anymore.
|
||||||
|
c->Initialize();
|
||||||
|
|
||||||
|
trackComponent(c, c->Tag().Type()); // Must come after Initialize().
|
||||||
|
|
||||||
|
info.type = c->Tag().Type();
|
||||||
|
_file_analyzers_by_type.resize(info.type + 1);
|
||||||
|
_file_analyzers_by_type[info.type] = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::registerPacketAnalyzer(const std::string& name, const std::string& parser, const std::string& replaces,
|
||||||
|
const std::string& linker_scope) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Have Spicy packet analyzer %s", name));
|
||||||
|
|
||||||
|
PacketAnalyzerInfo info;
|
||||||
|
info.name_analyzer = name;
|
||||||
|
info.name_replaces = replaces;
|
||||||
|
info.name_parser = parser;
|
||||||
|
info.name_zeek = hilti::rt::replace(name, "::", "_");
|
||||||
|
info.name_zeekygen = hilti::rt::fmt("<Spicy-%s>", info.name_zeek);
|
||||||
|
info.linker_scope = linker_scope;
|
||||||
|
|
||||||
|
// We may have that analyzer already iff it was previously pre-registered
|
||||||
|
// without a linker scope. We'll then set the scope now.
|
||||||
|
if ( auto t = _analyzer_name_to_tag_type.find(info.name_zeek); t != _analyzer_name_to_tag_type.end() ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Updating already registered packet analyzer %s", name));
|
||||||
|
|
||||||
|
auto& existing = _packet_analyzers_by_type.at(t->second);
|
||||||
|
assert(existing.name_analyzer == name);
|
||||||
|
existing.linker_scope = info.linker_scope;
|
||||||
|
|
||||||
|
// If the infos don't match now, we have two separate definitions.
|
||||||
|
if ( info != existing )
|
||||||
|
reporter->FatalError("redefinition of packet analyzer %s", info.name_analyzer.c_str());
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto instantiate = [info]() -> packet_analysis::AnalyzerPtr {
|
||||||
|
return spicy::rt::PacketAnalyzer::Instantiate(info.name_zeek);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto c = new ::zeek::packet_analysis::Component(info.name_zeek, instantiate, 0);
|
||||||
|
AddComponent(c);
|
||||||
|
|
||||||
|
// Hack to prevent Zeekygen from reporting the ID as not having a
|
||||||
|
// location during the following initialization step.
|
||||||
|
::zeek::detail::zeekygen_mgr->Script(info.name_zeekygen);
|
||||||
|
::zeek::detail::set_location(makeLocation(info.name_zeekygen));
|
||||||
|
|
||||||
|
// TODO: Should Zeek do this? It has run component intialization at
|
||||||
|
// this point already, so ours won't get initialized anymore.
|
||||||
|
c->Initialize();
|
||||||
|
|
||||||
|
trackComponent(c, c->Tag().Type()); // Must come after Initialize().
|
||||||
|
|
||||||
|
info.type = c->Tag().Type();
|
||||||
|
_packet_analyzers_by_type.resize(info.type + 1);
|
||||||
|
_packet_analyzers_by_type[info.type] = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::registerType(const std::string& id, const TypePtr& type) {
|
||||||
|
auto [ns, local] = parseID(id);
|
||||||
|
|
||||||
|
if ( const auto& old = detail::lookup_ID(local.c_str(), ns.c_str()) ) {
|
||||||
|
// This is most likely to trigger for IDs that other Spicy modules
|
||||||
|
// register. If we two Spicy modules need the same type, that's ok as
|
||||||
|
// long as they match.
|
||||||
|
if ( ! old->IsType() ) {
|
||||||
|
reporter->Error("Zeek type registration failed for '%s': ID already exists, but is not a type", id.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! zeek::same_type(type, old->GetType()) ) {
|
||||||
|
reporter->Error("Zeek type registration failed for '%s': Type already exists, but differs", id.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Not re-registering Zeek type %s: identical type already exists", id));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Registering Zeek type %s", id));
|
||||||
|
auto zeek_id = detail::install_ID(local.c_str(), ns.c_str(), true, true);
|
||||||
|
zeek_id->SetType(type);
|
||||||
|
zeek_id->MakeType();
|
||||||
|
AddBifItem(id, ::zeek::plugin::BifItem::TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
TypePtr Manager::findType(const std::string& id) const {
|
||||||
|
auto [ns, local] = parseID(id);
|
||||||
|
|
||||||
|
auto zid = detail::lookup_ID(local.c_str(), ns.c_str());
|
||||||
|
if ( ! zid )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if ( ! zid->IsType() )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return zid->GetType();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::registerEvent(const std::string& name) {
|
||||||
|
// Create a Zeek handler for the event.
|
||||||
|
event_registry->Register(name);
|
||||||
|
|
||||||
|
// Install the ID into the corresponding namespace and export it.
|
||||||
|
auto n = ::hilti::rt::split(name, "::");
|
||||||
|
std::string mod;
|
||||||
|
|
||||||
|
if ( n.size() > 1 )
|
||||||
|
mod = n.front();
|
||||||
|
else
|
||||||
|
mod = detail::GLOBAL_MODULE_NAME;
|
||||||
|
|
||||||
|
if ( auto id = detail::lookup_ID(name.c_str(), mod.c_str(), false, false, false) ) {
|
||||||
|
// Auto-export IDs that already exist.
|
||||||
|
id->SetExport();
|
||||||
|
_events[name] = id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// This installs & exports the ID, but it doesn't set its type yet.
|
||||||
|
// That will happen as handlers get defined. If there are no handlers,
|
||||||
|
// we set a dummy type in the plugin's InitPostScript
|
||||||
|
_events[name] = detail::install_ID(name.c_str(), mod.c_str(), false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ::spicy::rt::Parser* Manager::parserForProtocolAnalyzer(const Tag& tag, bool is_orig) {
|
||||||
|
if ( is_orig )
|
||||||
|
return _protocol_analyzers_by_type[tag.Type()].parser_orig;
|
||||||
|
else
|
||||||
|
return _protocol_analyzers_by_type[tag.Type()].parser_resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ::spicy::rt::Parser* Manager::parserForFileAnalyzer(const Tag& tag) {
|
||||||
|
return _file_analyzers_by_type[tag.Type()].parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ::spicy::rt::Parser* Manager::parserForPacketAnalyzer(const Tag& tag) {
|
||||||
|
return _packet_analyzers_by_type[tag.Type()].parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag Manager::tagForProtocolAnalyzer(const Tag& tag) {
|
||||||
|
if ( auto r = _protocol_analyzers_by_type[tag.Type()].replaces )
|
||||||
|
return r;
|
||||||
|
else
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag Manager::tagForFileAnalyzer(const Tag& tag) {
|
||||||
|
if ( auto r = _file_analyzers_by_type[tag.Type()].replaces )
|
||||||
|
return r;
|
||||||
|
else
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag Manager::tagForPacketAnalyzer(const Tag& tag) {
|
||||||
|
if ( auto r = _packet_analyzers_by_type[tag.Type()].replaces )
|
||||||
|
return r;
|
||||||
|
else
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Manager::toggleProtocolAnalyzer(const Tag& tag, bool enable) {
|
||||||
|
auto type = tag.Type();
|
||||||
|
|
||||||
|
if ( type >= _protocol_analyzers_by_type.size() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto& analyzer = _protocol_analyzers_by_type[type];
|
||||||
|
|
||||||
|
if ( ! analyzer.type )
|
||||||
|
// not set -> not ours
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( enable ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Enabling Spicy protocol analyzer %s", analyzer.name_analyzer));
|
||||||
|
analyzer_mgr->EnableAnalyzer(tag);
|
||||||
|
|
||||||
|
if ( analyzer.replaces ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Disabling standard protocol analyzer %s", analyzer.name_analyzer));
|
||||||
|
analyzer_mgr->DisableAnalyzer(analyzer.replaces);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Disabling Spicy protocol analyzer %s", analyzer.name_analyzer));
|
||||||
|
analyzer_mgr->DisableAnalyzer(tag);
|
||||||
|
|
||||||
|
if ( analyzer.replaces ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Re-enabling standard protocol analyzer %s", analyzer.name_analyzer));
|
||||||
|
analyzer_mgr->EnableAnalyzer(analyzer.replaces);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Manager::toggleFileAnalyzer(const Tag& tag, bool enable) {
|
||||||
|
auto type = tag.Type();
|
||||||
|
|
||||||
|
if ( type >= _file_analyzers_by_type.size() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto& analyzer = _file_analyzers_by_type[type];
|
||||||
|
|
||||||
|
if ( ! analyzer.type )
|
||||||
|
// not set -> not ours
|
||||||
|
return false;
|
||||||
|
|
||||||
|
file_analysis::Component* component = file_mgr->Lookup(tag);
|
||||||
|
file_analysis::Component* component_replaces = analyzer.replaces ? file_mgr->Lookup(analyzer.replaces) : nullptr;
|
||||||
|
|
||||||
|
if ( ! component ) {
|
||||||
|
// Shouldn't really happen.
|
||||||
|
reporter->InternalError("failed to lookup file analyzer component");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( enable ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Enabling Spicy file analyzer %s", analyzer.name_analyzer));
|
||||||
|
component->SetEnabled(true);
|
||||||
|
|
||||||
|
if ( component_replaces ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Disabling standard file analyzer %s", analyzer.name_analyzer));
|
||||||
|
component_replaces->SetEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Disabling Spicy file analyzer %s", analyzer.name_analyzer));
|
||||||
|
component->SetEnabled(false);
|
||||||
|
|
||||||
|
if ( component_replaces ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Enabling standard file analyzer %s", analyzer.name_analyzer));
|
||||||
|
component_replaces->SetEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Manager::togglePacketAnalyzer(const Tag& tag, bool enable) {
|
||||||
|
auto type = tag.Type();
|
||||||
|
|
||||||
|
if ( type >= _packet_analyzers_by_type.size() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto& analyzer = _packet_analyzers_by_type[type];
|
||||||
|
|
||||||
|
if ( ! analyzer.type )
|
||||||
|
// not set -> not ours
|
||||||
|
return false;
|
||||||
|
|
||||||
|
packet_analysis::Component* component = packet_mgr->Lookup(tag);
|
||||||
|
packet_analysis::Component* component_replaces =
|
||||||
|
analyzer.replaces ? packet_mgr->Lookup(analyzer.replaces) : nullptr;
|
||||||
|
|
||||||
|
if ( ! component ) {
|
||||||
|
// Shouldn't really happen.
|
||||||
|
reporter->InternalError("failed to lookup packet analyzer component");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( enable ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Enabling Spicy packet analyzer %s", analyzer.name_analyzer));
|
||||||
|
component->SetEnabled(true);
|
||||||
|
|
||||||
|
if ( component_replaces ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Disabling standard packet analyzer %s", analyzer.name_analyzer));
|
||||||
|
component_replaces->SetEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Disabling Spicy packet analyzer %s", analyzer.name_analyzer));
|
||||||
|
component->SetEnabled(false);
|
||||||
|
|
||||||
|
if ( component_replaces ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Enabling standard packet analyzer %s", analyzer.name_analyzer));
|
||||||
|
component_replaces->SetEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Manager::toggleAnalyzer(EnumVal* tag, bool enable) {
|
||||||
|
if ( tag->GetType() == analyzer_mgr->GetTagType() ) {
|
||||||
|
if ( auto analyzer = analyzer_mgr->Lookup(tag) )
|
||||||
|
return toggleProtocolAnalyzer(analyzer->Tag(), enable);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( tag->GetType() == file_mgr->GetTagType() ) {
|
||||||
|
if ( auto analyzer = file_mgr->Lookup(tag) )
|
||||||
|
return toggleFileAnalyzer(analyzer->Tag(), enable);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( tag->GetType() == packet_mgr->GetTagType() ) {
|
||||||
|
if ( auto analyzer = packet_mgr->Lookup(tag) )
|
||||||
|
return togglePacketAnalyzer(analyzer->Tag(), enable);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::unique_ptr<detail::Location> _makeLocation(const std::string& location) {
|
||||||
|
static std::set<std::string> filenames; // see comment below in parse_location
|
||||||
|
|
||||||
|
auto parse_location = [](const auto& s) -> std::unique_ptr<detail::Location> {
|
||||||
|
// This is not so great; In the HILTI runtome we pass locations
|
||||||
|
// around as string. To pass them to Zeek, we need to unsplit the
|
||||||
|
// strings into file name and line number. Zeek also won't clean up
|
||||||
|
// the file names, so we need to track them ourselves.
|
||||||
|
auto x = hilti::rt::split(s, ":");
|
||||||
|
if ( x[0].empty() )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto loc = std::make_unique<detail::Location>();
|
||||||
|
loc->filename = filenames.insert(std::string(x[0])).first->c_str(); // we retain ownership
|
||||||
|
|
||||||
|
if ( x.size() >= 2 ) {
|
||||||
|
auto y = hilti::rt::split(x[1], "-");
|
||||||
|
if ( y.size() >= 2 ) {
|
||||||
|
loc->first_line = std::stoi(std::string(y[0]));
|
||||||
|
loc->last_line = std::stoi(std::string(y[1]));
|
||||||
|
}
|
||||||
|
else if ( y[0].size() )
|
||||||
|
loc->first_line = loc->last_line = std::stoi(std::string(y[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return loc;
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( location.size() )
|
||||||
|
return parse_location(location);
|
||||||
|
else if ( auto hilti_location = hilti::rt::debug::location() )
|
||||||
|
return parse_location(hilti_location);
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::analyzerError(analyzer::Analyzer* a, const std::string& msg, const std::string& location) {
|
||||||
|
auto zeek_location = _makeLocation(location);
|
||||||
|
reporter->PushLocation(zeek_location.get());
|
||||||
|
reporter->AnalyzerError(a, "%s", msg.c_str());
|
||||||
|
reporter->PopLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::analyzerError(file_analysis::Analyzer* a, const std::string& msg, const std::string& location) {
|
||||||
|
auto zeek_location = _makeLocation(location);
|
||||||
|
reporter->PushLocation(zeek_location.get());
|
||||||
|
|
||||||
|
// We don't have an reporter error for file analyzers, so we log this as a
|
||||||
|
// weird instead.
|
||||||
|
if ( a && a->GetFile() )
|
||||||
|
reporter->Weird(a->GetFile(), "file_error", msg.c_str());
|
||||||
|
else
|
||||||
|
reporter->Weird("file_error", msg.c_str());
|
||||||
|
|
||||||
|
reporter->PopLocation();
|
||||||
|
|
||||||
|
if ( a )
|
||||||
|
a->SetSkip(1); // Imitate what AnalyzerError() does for protocol analyzers.
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::analyzerError(packet_analysis::Analyzer* a, const std::string& msg, const std::string& location) {
|
||||||
|
auto zeek_location = _makeLocation(location);
|
||||||
|
reporter->PushLocation(zeek_location.get());
|
||||||
|
// We don't have an reporter error for packet analyzers, so we log
|
||||||
|
// this as a weird instead.
|
||||||
|
reporter->Weird("packet_error", msg.c_str());
|
||||||
|
reporter->PopLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin::Configuration Manager::Configure() {
|
||||||
|
::zeek::plugin::Configuration config;
|
||||||
|
config.name = "Zeek::Spicy";
|
||||||
|
config.description = "Support for Spicy parsers (*.hlto)";
|
||||||
|
|
||||||
|
EnableHook(::zeek::plugin::HOOK_LOAD_FILE);
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::InitPreScript() {
|
||||||
|
SPICY_DEBUG("Beginning pre-script initialization");
|
||||||
|
|
||||||
|
#if SPICY_VERSION_NUMBER >= 10700
|
||||||
|
hilti::rt::executeManualPreInits();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
autoDiscoverModules();
|
||||||
|
|
||||||
|
SPICY_DEBUG("Done with pre-script initialization");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a port's Zeek-side transport protocol.
|
||||||
|
static ::TransportProto transport_protocol(const hilti::rt::Port port) {
|
||||||
|
#if SPICY_VERSION_NUMBER >= 10700
|
||||||
|
auto proto = port.protocol().value();
|
||||||
|
#else
|
||||||
|
auto proto = port.protocol();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch ( proto ) {
|
||||||
|
case hilti::rt::Protocol::TCP: return ::TransportProto::TRANSPORT_TCP;
|
||||||
|
case hilti::rt::Protocol::UDP: return ::TransportProto::TRANSPORT_UDP;
|
||||||
|
case hilti::rt::Protocol::ICMP: return ::TransportProto::TRANSPORT_ICMP;
|
||||||
|
default:
|
||||||
|
reporter->InternalError("unsupported transport protocol in port '%s' for Zeek conversion",
|
||||||
|
std::string(port).c_str());
|
||||||
|
return ::TransportProto::TRANSPORT_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hook_accept_input() {
|
||||||
|
auto cookie = static_cast<rt::Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
if ( auto x = cookie->protocol ) {
|
||||||
|
auto tag = spicy_mgr->tagForProtocolAnalyzer(x->analyzer->GetAnalyzerTag());
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("confirming protocol %s", tag.AsString()));
|
||||||
|
return x->analyzer->AnalyzerConfirmation(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hook_decline_input(const std::string& reason) {
|
||||||
|
auto cookie = static_cast<rt::Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
if ( auto x = cookie->protocol ) {
|
||||||
|
auto tag = spicy_mgr->tagForProtocolAnalyzer(x->analyzer->GetAnalyzerTag());
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("rejecting protocol %s", tag.AsString()));
|
||||||
|
return x->analyzer->AnalyzerViolation("protocol rejected", nullptr, 0, tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::InitPostScript() {
|
||||||
|
SPICY_DEBUG("Beginning post-script initialization");
|
||||||
|
|
||||||
|
disableReplacedAnalyzers();
|
||||||
|
|
||||||
|
// If there's no handler for one of our events, it won't have received a
|
||||||
|
// type. Give it a dummy event type in that case, so that we don't walk
|
||||||
|
// around with a nullptr.
|
||||||
|
for ( const auto& [name, id] : _events ) {
|
||||||
|
if ( ! id->GetType() ) {
|
||||||
|
auto args = make_intrusive<RecordType>(new type_decl_list());
|
||||||
|
auto et = make_intrusive<FuncType>(std::move(args), base_type(TYPE_VOID), FUNC_FLAVOR_EVENT);
|
||||||
|
id->SetType(std::move(et));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init runtime, which will trigger all initialization code to execute.
|
||||||
|
SPICY_DEBUG("Initializing Spicy runtime");
|
||||||
|
|
||||||
|
auto hilti_config = hilti::rt::configuration::get();
|
||||||
|
|
||||||
|
if ( id::find_const("Spicy::enable_print")->AsBool() ) // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
|
||||||
|
hilti_config.cout = std::cout;
|
||||||
|
else
|
||||||
|
hilti_config.cout.reset();
|
||||||
|
|
||||||
|
if ( id::find_const("Spicy::enable_profiling")->AsBool() )
|
||||||
|
#if SPICY_VERSION_NUMBER >= 10800
|
||||||
|
hilti_config.enable_profiling = true;
|
||||||
|
#else
|
||||||
|
std::cerr << "Profiling is not supported with this version of Spicy, ignoring "
|
||||||
|
"'Spicy::enable_profiling'\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
hilti_config.abort_on_exceptions = id::find_const("Spicy::abort_on_exceptions")->AsBool();
|
||||||
|
hilti_config.show_backtraces = id::find_const("Spicy::show_backtraces")->AsBool();
|
||||||
|
|
||||||
|
hilti::rt::configuration::set(hilti_config);
|
||||||
|
|
||||||
|
#if SPICY_VERSION_NUMBER >= 10700
|
||||||
|
auto spicy_config = ::spicy::rt::configuration::get();
|
||||||
|
spicy_config.hook_accept_input = hook_accept_input;
|
||||||
|
spicy_config.hook_decline_input = hook_decline_input;
|
||||||
|
::spicy::rt::configuration::set(std::move(spicy_config));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
try {
|
||||||
|
::hilti::rt::init();
|
||||||
|
::spicy::rt::init();
|
||||||
|
} catch ( const hilti::rt::Exception& e ) {
|
||||||
|
std::cerr << hilti::rt::fmt("uncaught runtime exception %s during initialization: %s",
|
||||||
|
hilti::rt::demangle(typeid(e).name()), e.what())
|
||||||
|
<< std::endl;
|
||||||
|
exit(1);
|
||||||
|
} catch ( const std::runtime_error& e ) {
|
||||||
|
std::cerr << hilti::rt::fmt("uncaught C++ exception %s during initialization: %s",
|
||||||
|
hilti::rt::demangle(typeid(e).name()), e.what())
|
||||||
|
<< std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in the parser information now that we derived from the ASTs.
|
||||||
|
auto find_parser = [](const std::string& analyzer, const std::string& parser,
|
||||||
|
const std::string& linker_scope) -> const ::spicy::rt::Parser* {
|
||||||
|
if ( parser.empty() )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
for ( auto p : ::spicy::rt::parsers() ) {
|
||||||
|
if ( p->name == parser && p->linker_scope == linker_scope )
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
reporter->InternalError("Unknown Spicy parser '%s' requested by analyzer '%s'", parser.c_str(),
|
||||||
|
analyzer.c_str());
|
||||||
|
|
||||||
|
return nullptr; // cannot be reached
|
||||||
|
};
|
||||||
|
|
||||||
|
for ( auto& p : _protocol_analyzers_by_type ) {
|
||||||
|
if ( p.type == 0 )
|
||||||
|
// vector element not set
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Registering %s protocol analyzer %s with Zeek", p.protocol, p.name_analyzer));
|
||||||
|
|
||||||
|
p.parser_orig = find_parser(p.name_analyzer, p.name_parser_orig, p.linker_scope);
|
||||||
|
p.parser_resp = find_parser(p.name_analyzer, p.name_parser_resp, p.linker_scope);
|
||||||
|
|
||||||
|
// Register analyzer for its well-known ports.
|
||||||
|
auto tag = analyzer_mgr->GetAnalyzerTag(p.name_zeek.c_str());
|
||||||
|
if ( ! tag )
|
||||||
|
reporter->InternalError("cannot get analyzer tag for '%s'", p.name_analyzer.c_str());
|
||||||
|
|
||||||
|
for ( auto port : p.ports ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt(" Scheduling analyzer for port %s", port));
|
||||||
|
analyzer_mgr->RegisterAnalyzerForPort(tag, transport_protocol(port), port.port());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( p.parser_resp ) {
|
||||||
|
for ( auto port : p.parser_resp->ports ) {
|
||||||
|
if ( port.direction != ::spicy::rt::Direction::Both &&
|
||||||
|
port.direction != ::spicy::rt::Direction::Responder )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt(" Scheduling analyzer for port %s", port.port));
|
||||||
|
analyzer_mgr->RegisterAnalyzerForPort(tag, transport_protocol(port.port), port.port.port());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( auto& p : _file_analyzers_by_type ) {
|
||||||
|
if ( p.type == 0 )
|
||||||
|
// vector element not set
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Registering file analyzer %s with Zeek", p.name_analyzer.c_str()));
|
||||||
|
|
||||||
|
p.parser = find_parser(p.name_analyzer, p.name_parser, p.linker_scope);
|
||||||
|
|
||||||
|
// Register analyzer for its MIME types.
|
||||||
|
auto tag = file_mgr->GetComponentTag(p.name_zeek.c_str());
|
||||||
|
if ( ! tag )
|
||||||
|
reporter->InternalError("cannot get analyzer tag for '%s'", p.name_analyzer.c_str());
|
||||||
|
|
||||||
|
auto register_analyzer_for_mime_type = [&](auto tag, const std::string& mt) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt(" Scheduling analyzer for MIME type %s", mt));
|
||||||
|
|
||||||
|
// MIME types are registered in scriptland, so we'll raise an
|
||||||
|
// event that will do it for us through a predefined handler.
|
||||||
|
zeek::Args vals = Args();
|
||||||
|
vals.emplace_back(tag.AsVal());
|
||||||
|
vals.emplace_back(make_intrusive<StringVal>(mt));
|
||||||
|
EventHandlerPtr handler = event_registry->Register("spicy_analyzer_for_mime_type");
|
||||||
|
event_mgr.Enqueue(handler, vals);
|
||||||
|
};
|
||||||
|
|
||||||
|
for ( const auto& mt : p.mime_types )
|
||||||
|
register_analyzer_for_mime_type(tag, mt);
|
||||||
|
|
||||||
|
if ( p.parser ) {
|
||||||
|
for ( const auto& mt : p.parser->mime_types )
|
||||||
|
register_analyzer_for_mime_type(tag, mt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( auto& p : _packet_analyzers_by_type ) {
|
||||||
|
if ( p.type == 0 )
|
||||||
|
// vector element not set
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Registering packet analyzer %s with Zeek", p.name_analyzer.c_str()));
|
||||||
|
p.parser = find_parser(p.name_analyzer, p.name_parser, p.linker_scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPICY_DEBUG("Done with post-script initialization");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::Done() {
|
||||||
|
SPICY_DEBUG("Shutting down Spicy runtime");
|
||||||
|
::spicy::rt::done();
|
||||||
|
hilti::rt::done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::loadModule(const hilti::rt::filesystem::path& path) {
|
||||||
|
try {
|
||||||
|
// If our auto discovery ends up finding the same module multiple times,
|
||||||
|
// we ignore subsequent requests.
|
||||||
|
std::error_code ec;
|
||||||
|
auto canonical_path = hilti::rt::filesystem::canonical(path, ec);
|
||||||
|
if ( ec )
|
||||||
|
hilti::rt::fatalError(hilti::rt::fmt("could not compute canonical path for %s: %s", path, ec.message()));
|
||||||
|
|
||||||
|
if ( auto [library, inserted] = _libraries.insert({canonical_path, hilti::rt::Library(canonical_path)});
|
||||||
|
inserted ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Loading %s", canonical_path.native()));
|
||||||
|
if ( auto load = library->second.open(); ! load )
|
||||||
|
hilti::rt::fatalError(
|
||||||
|
hilti::rt::fmt("could not open library path %s: %s", canonical_path, load.error()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Ignoring duplicate loading request for %s", canonical_path.native()));
|
||||||
|
}
|
||||||
|
#if SPICY_VERSION_NUMBER >= 10700
|
||||||
|
} catch ( const ::hilti::rt::UsageError& e ) {
|
||||||
|
#else
|
||||||
|
} catch ( const ::hilti::rt::UserException& e ) {
|
||||||
|
#endif
|
||||||
|
hilti::rt::fatalError(e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Manager::HookLoadFile(const LoadType type, const std::string& file, const std::string& resolved) {
|
||||||
|
auto ext = hilti::rt::filesystem::path(file).extension();
|
||||||
|
|
||||||
|
if ( ext == ".hlto" ) {
|
||||||
|
loadModule(file);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ext == ".spicy" || ext == ".evt" || ext == ".hlt" )
|
||||||
|
reporter->FatalError("cannot load '%s': analyzers need to be precompiled with 'spicyz' ", file.c_str());
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::searchModules(const std::string& paths) {
|
||||||
|
for ( const auto& dir : hilti::rt::split(paths, ":") ) {
|
||||||
|
auto trimmed_dir = hilti::rt::trim(dir);
|
||||||
|
if ( trimmed_dir.empty() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::error_code ec;
|
||||||
|
if ( auto is_directory = hilti::rt::filesystem::is_directory(trimmed_dir, ec); ec || ! is_directory ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Module directory %s cannot be read, skipping", trimmed_dir));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("Searching %s for *.hlto", trimmed_dir));
|
||||||
|
|
||||||
|
auto it = hilti::rt::filesystem::recursive_directory_iterator(trimmed_dir, ec);
|
||||||
|
if ( ! ec ) {
|
||||||
|
while ( it != hilti::rt::filesystem::recursive_directory_iterator() ) {
|
||||||
|
if ( it->is_regular_file() && it->path().extension() == ".hlto" )
|
||||||
|
loadModule(it->path());
|
||||||
|
|
||||||
|
if ( it.increment(ec); ec ) {
|
||||||
|
hilti::rt::warning(hilti::rt::fmt("Error iterating over %s, skipping any remaining files: %s",
|
||||||
|
trimmed_dir, ec.message()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
hilti::rt::warning(hilti::rt::fmt("Cannot iterate over %s, skipping: %s", trimmed_dir, ec.message()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
detail::Location Manager::makeLocation(const std::string& fname) {
|
||||||
|
auto x = _locations.insert(fname);
|
||||||
|
return detail::Location(x.first->c_str(), 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::autoDiscoverModules() {
|
||||||
|
// Always search Zeek's plugin path for modules, that's where zkg puts
|
||||||
|
// them.
|
||||||
|
searchModules(util::zeek_plugin_path());
|
||||||
|
|
||||||
|
if ( auto search_paths = hilti::rt::getenv("ZEEK_SPICY_MODULE_PATH"); search_paths && search_paths->size() )
|
||||||
|
// This overrides all other paths.
|
||||||
|
searchModules(*search_paths);
|
||||||
|
else
|
||||||
|
searchModules(ZEEK_SPICY_MODULE_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::disableReplacedAnalyzers() {
|
||||||
|
for ( auto& info : _protocol_analyzers_by_type ) {
|
||||||
|
if ( info.name_replaces.empty() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto replaces = info.name_replaces.c_str();
|
||||||
|
|
||||||
|
if ( file_mgr->Lookup(replaces) || packet_mgr->Lookup(replaces) )
|
||||||
|
reporter->FatalError("cannot replace '%s' analyzer with a protocol analyzer", replaces);
|
||||||
|
|
||||||
|
auto tag = analyzer_mgr->GetAnalyzerTag(replaces);
|
||||||
|
if ( ! tag ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("%s is supposed to replace protocol analyzer %s, but that does not exist",
|
||||||
|
info.name_analyzer, replaces));
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("%s replaces existing protocol analyzer %s", info.name_analyzer, replaces));
|
||||||
|
info.replaces = tag;
|
||||||
|
analyzer_mgr->DisableAnalyzer(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( auto& info : _file_analyzers_by_type ) {
|
||||||
|
if ( info.name_replaces.empty() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto replaces = info.name_replaces.c_str();
|
||||||
|
|
||||||
|
if ( analyzer_mgr->Lookup(replaces) || packet_mgr->Lookup(replaces) )
|
||||||
|
reporter->FatalError("cannot replace '%s' analyzer with a file analyzer", replaces);
|
||||||
|
|
||||||
|
auto component = file_mgr->Lookup(replaces);
|
||||||
|
if ( ! component ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("%s is supposed to replace file analyzer %s, but that does not exist",
|
||||||
|
info.name_analyzer, replaces));
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("%s replaces existing file analyzer %s", info.name_analyzer, replaces));
|
||||||
|
info.replaces = component->Tag();
|
||||||
|
component->SetEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( auto& info : _packet_analyzers_by_type ) {
|
||||||
|
if ( info.name_replaces.empty() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto replaces = info.name_replaces.c_str();
|
||||||
|
|
||||||
|
auto component = packet_mgr->Lookup(replaces);
|
||||||
|
if ( ! component ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("%s is supposed to replace packet analyzer %s, but that does not exist",
|
||||||
|
info.name_analyzer, replaces));
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("%s replaces existing packet analyzer %s", info.name_analyzer, replaces));
|
||||||
|
info.replaces = component->Tag();
|
||||||
|
component->SetEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::trackComponent(plugin::Component* c, int32_t tag_type) {
|
||||||
|
auto i = _analyzer_name_to_tag_type.insert({c->Name(), tag_type});
|
||||||
|
if ( ! i.second )
|
||||||
|
// We enforce on our end that an analyzer name can appear only once
|
||||||
|
// across all types of analyzers. Makes things easier and avoids
|
||||||
|
// confusion.
|
||||||
|
reporter->FatalError("duplicate analyzer name '%s'", c->Name().c_str());
|
||||||
|
}
|
414
src/spicy/manager.h
Normal file
414
src/spicy/manager.h
Normal file
|
@ -0,0 +1,414 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <hilti/rt/library.h>
|
||||||
|
#include <hilti/rt/logging.h>
|
||||||
|
#include <hilti/rt/types/port.h>
|
||||||
|
|
||||||
|
#include "zeek/Scope.h"
|
||||||
|
#include "zeek/Tag.h"
|
||||||
|
#include "zeek/plugin/Component.h"
|
||||||
|
#include "zeek/plugin/Plugin.h"
|
||||||
|
#include "zeek/spicy/spicyz/config.h" // include for Spicy version
|
||||||
|
|
||||||
|
// Macro helper to report Spicy debug messages. This forwards to
|
||||||
|
// to both the Zeek logger and the Spicy runtime logger.
|
||||||
|
#define SPICY_DEBUG(msg) ::zeek::spicy::log(msg);
|
||||||
|
|
||||||
|
namespace hilti::rt {
|
||||||
|
class Port;
|
||||||
|
struct Protocol;
|
||||||
|
} // namespace hilti::rt
|
||||||
|
|
||||||
|
namespace spicy::rt {
|
||||||
|
struct Parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace zeek {
|
||||||
|
|
||||||
|
namespace analyzer {
|
||||||
|
class Analyzer;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace file_analysis {
|
||||||
|
class Analyzer;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace packet_analysis {
|
||||||
|
class Analyzer;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace spicy {
|
||||||
|
|
||||||
|
// Backend to log debug messages.
|
||||||
|
inline void log(const std::string& msg) {
|
||||||
|
DBG_LOG(DBG_SPICY, "%s", msg.c_str());
|
||||||
|
|
||||||
|
if ( hilti::rt::isInitialized() )
|
||||||
|
HILTI_RT_DEBUG("zeek", msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Top-level entry point for Spicy functionality. */
|
||||||
|
class Manager : public zeek::plugin::Plugin {
|
||||||
|
public:
|
||||||
|
Manager() {}
|
||||||
|
virtual ~Manager();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime method to register a protocol analyzer with its Zeek-side
|
||||||
|
* configuration. This is called at startup by generated Spicy code for
|
||||||
|
* each protocol analyzer defined in an EVT file.
|
||||||
|
*
|
||||||
|
* @param name name of the analyzer as defined in its EVT file
|
||||||
|
* @param proto analyzer's transport-layer protocol
|
||||||
|
* @param prts well-known ports for the analyzer; it'll be activated automatically for these
|
||||||
|
* @param parser_orig name of the Spicy parser for the originator side; must match the name that
|
||||||
|
* Spicy registers the unit's parser with
|
||||||
|
* @param parser_resp name of the Spicy parser for the originator side; must match the name that
|
||||||
|
* Spicy registers the unit's parser with
|
||||||
|
* @param replaces optional name of existing Zeek analyzer that this one replaces; the Zeek
|
||||||
|
* analyzer will automatically be disabled
|
||||||
|
* @param linker_scope scope of current HLTO file, which will restrict visibility of the
|
||||||
|
* registration
|
||||||
|
*/
|
||||||
|
void registerProtocolAnalyzer(const std::string& name, hilti::rt::Protocol proto,
|
||||||
|
const hilti::rt::Vector<hilti::rt::Port>& ports, const std::string& parser_orig,
|
||||||
|
const std::string& parser_resp, const std::string& replaces,
|
||||||
|
const std::string& linker_scope);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime method to register a file analyzer with its Zeek-side
|
||||||
|
* configuration. This is called at startup by generated Spicy code for
|
||||||
|
* each file analyzer defined in an EVT file
|
||||||
|
*
|
||||||
|
* @param name name of the analyzer as defined in its EVT file
|
||||||
|
* @param mime_types list of MIME types the analyzer handles; it'll be automatically used for
|
||||||
|
* all files of matching types
|
||||||
|
* @param parser name of the Spicy parser for parsing the file; must match the name that Spicy
|
||||||
|
* registers the unit's parser with
|
||||||
|
* @param replaces optional name of existing Zeek analyzer that this one replaces; the Zeek
|
||||||
|
* analyzer will automatically be disabled
|
||||||
|
* @param linker_scope scope of current HLTO file, which will restrict visibility of the
|
||||||
|
* registration
|
||||||
|
*/
|
||||||
|
void registerFileAnalyzer(const std::string& name, const hilti::rt::Vector<std::string>& mime_types,
|
||||||
|
const std::string& parser, const std::string& replaces, const std::string& linker_scope);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime method to register a packet analyzer with its Zeek-side
|
||||||
|
* configuration. This is called at startup by generated Spicy code for
|
||||||
|
* each packet analyzer defined in an EVT file.
|
||||||
|
*
|
||||||
|
* @param name name of the analyzer as defined in its EVT file
|
||||||
|
* @param parser name of the Spicy parser for parsing the packet; must
|
||||||
|
* match the name that Spicy registers the unit's
|
||||||
|
* parser with.
|
||||||
|
* @param replaces optional name of existing Zeek analyzer that this one
|
||||||
|
* replaces; the Zeek analyzer will automatically be disabled
|
||||||
|
* @param linker_scope scope of current HLTO file, which will restrict visibility of the
|
||||||
|
* registration
|
||||||
|
*/
|
||||||
|
void registerPacketAnalyzer(const std::string& name, const std::string& parser, const std::string& replaces,
|
||||||
|
const std::string& linker_scope);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime method to register a Spicy-generated type with Zeek. The type
|
||||||
|
* must have been encountered during AST traversal already, so that its ID
|
||||||
|
* is known. The corresponding Zeek type will be created and registered with Zeek.
|
||||||
|
*
|
||||||
|
* @param id fully-qualified ID of the type
|
||||||
|
* @return error if the type could not be registered
|
||||||
|
*/
|
||||||
|
hilti::rt::Result<hilti::rt::Nothing> registerType(const std::string& id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime method to register an already converted Spicy-generated type
|
||||||
|
* with Zeek.
|
||||||
|
*
|
||||||
|
* @param id fully-qualified ID of the type
|
||||||
|
* @param type Zeek-side type to register
|
||||||
|
*/
|
||||||
|
void registerType(const std::string& id, const TypePtr& type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks up a global type by its ID with Zeek.
|
||||||
|
*
|
||||||
|
* @param id fully-qualified Zeek-side ID of the type
|
||||||
|
* @return Zeek-side type, or null if not found
|
||||||
|
*/
|
||||||
|
TypePtr findType(const std::string& id) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime method to register a Spicy-generated event. The installs the ID
|
||||||
|
* Zeek-side and is called at startup by generated Spicy code for each
|
||||||
|
* event defined in an EVT file.
|
||||||
|
*
|
||||||
|
* @param name fully scoped name of the event
|
||||||
|
*/
|
||||||
|
void registerEvent(const std::string& name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime method to retrieve the Spicy parser for a given Zeek protocol analyzer tag.
|
||||||
|
*
|
||||||
|
* @param analyzer requested protocol analyzer
|
||||||
|
* @param is_orig true if requesting the parser parser for a sessions' originator side, false
|
||||||
|
* for the responder
|
||||||
|
* @return parser, or null if we don't have one for this tag. The pointer will remain valid for
|
||||||
|
* the life-time of the process.
|
||||||
|
*/
|
||||||
|
const ::spicy::rt::Parser* parserForProtocolAnalyzer(const Tag& tag, bool is_orig);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime method to retrieve the Spicy parser for a given Zeek file analyzer tag.
|
||||||
|
*
|
||||||
|
* @param analyzer requested file analyzer.
|
||||||
|
* @return parser, or null if we don't have one for this tag. The pointer will remain valid for
|
||||||
|
* the life-time of the process.
|
||||||
|
*/
|
||||||
|
const ::spicy::rt::Parser* parserForFileAnalyzer(const Tag& tag);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime method to retrieve the Spicy parser for a given Zeek packet analyzer tag.
|
||||||
|
*
|
||||||
|
* @param analyzer requested packet analyzer.
|
||||||
|
* @return parser, or null if we don't have one for this tag. The pointer will remain
|
||||||
|
* valid for the life-time of the process.
|
||||||
|
*/
|
||||||
|
const ::spicy::rt::Parser* parserForPacketAnalyzer(const Tag& tag);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime method to retrieve the analyzer tag that should be passed to
|
||||||
|
* script-land when talking about a protocol analyzer. This is normally
|
||||||
|
* the analyzer's standard tag, but may be replaced with something else
|
||||||
|
* if the analyzer substitutes for an existing one.
|
||||||
|
*
|
||||||
|
* @param tag original tag we query for how to pass it to script-land.
|
||||||
|
* @return desired tag for passing to script-land.
|
||||||
|
*/
|
||||||
|
Tag tagForProtocolAnalyzer(const Tag& tag);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime method to retrieve the analyzer tag that should be passed to
|
||||||
|
* script-land when talking about a file analyzer. This is normally the
|
||||||
|
* analyzer's standard tag, but may be replaced with something else if
|
||||||
|
* the analyzer substitutes for an existing one.
|
||||||
|
*
|
||||||
|
* @param tag original tag we query for how to pass it to script-land.
|
||||||
|
* @return desired tag for passing to script-land.
|
||||||
|
*/
|
||||||
|
Tag tagForFileAnalyzer(const Tag& tag);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime method to retrieve the analyzer tag that should be passed to
|
||||||
|
* script-land when talking about a packet analyzer. This is normally the
|
||||||
|
* analyzer's standard tag, but may be replaced with something else if
|
||||||
|
* the analyzer substitutes for an existing one.
|
||||||
|
*
|
||||||
|
* @param tag original tag we query for how to pass it to script-land.
|
||||||
|
* @return desired tag for passing to script-land.
|
||||||
|
*/
|
||||||
|
Tag tagForPacketAnalyzer(const Tag& tag);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Explicitly enable/disable a protocol analyzer. By default, all analyzers
|
||||||
|
* loaded will also be activated. By calling this method, an analyzer can
|
||||||
|
* toggled.
|
||||||
|
*
|
||||||
|
* @param analyzer tag of analyzer
|
||||||
|
* @param enable true to enable, false to disable
|
||||||
|
*/
|
||||||
|
bool toggleProtocolAnalyzer(const Tag& tag, bool enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Explicitly enable/disable a file analyzer. By default, all analyzers
|
||||||
|
* loaded will also be activated. By calling this method, an analyzer can
|
||||||
|
* toggled.
|
||||||
|
*
|
||||||
|
* @param analyzer tag of analyzer
|
||||||
|
* @param enable true to enable, false to disable
|
||||||
|
*/
|
||||||
|
bool toggleFileAnalyzer(const Tag& tag, bool enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Explicitly enable/disable a packet analyzer. By default, all analyzers
|
||||||
|
* loaded will also be activated. By calling this method, an analyzer can
|
||||||
|
* toggled.
|
||||||
|
*
|
||||||
|
* @note This is currently not supported because Zeek does not provide the
|
||||||
|
* necessary API.
|
||||||
|
*
|
||||||
|
* @param analyzer tag of analyzer
|
||||||
|
* @param enable true to enable, false to disable
|
||||||
|
*/
|
||||||
|
bool togglePacketAnalyzer(const Tag& tag, bool enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Explicitly enable/disable an analyzer. By default, all analyzers
|
||||||
|
* loaded will also be activated. By calling this method, an analyzer can
|
||||||
|
* toggled.
|
||||||
|
*
|
||||||
|
* This method is frontend for the versions specific to
|
||||||
|
* protocol/file/packet analyzers. It takes an enum corresponding to either
|
||||||
|
* kind and branches out accordingly.
|
||||||
|
*
|
||||||
|
* @param analyzer tag of analyzer
|
||||||
|
* @param enable true to enable, false to disable
|
||||||
|
*/
|
||||||
|
bool toggleAnalyzer(EnumVal* tag, bool enable);
|
||||||
|
|
||||||
|
/** Report an error and disable a protocol analyzer's input processing */
|
||||||
|
void analyzerError(analyzer::Analyzer* a, const std::string& msg, const std::string& location);
|
||||||
|
|
||||||
|
/** Report an error and disable a file analyzer's input processing */
|
||||||
|
void analyzerError(file_analysis::Analyzer* a, const std::string& msg, const std::string& location);
|
||||||
|
|
||||||
|
/** Report an error and disable a packet analyzer's input processing. */
|
||||||
|
void analyzerError(packet_analysis::Analyzer* a, const std::string& msg, const std::string& location);
|
||||||
|
|
||||||
|
/** Returns the number of errors recorded by the Zeek reporter. */
|
||||||
|
int numberErrors();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Overriding method from Zeek's plugin API.
|
||||||
|
zeek::plugin::Configuration Configure() override;
|
||||||
|
|
||||||
|
// Overriding method from Zeek's plugin API.
|
||||||
|
void InitPreScript() override;
|
||||||
|
|
||||||
|
// Overriding method from Zeek's plugin API.
|
||||||
|
void InitPostScript() override;
|
||||||
|
|
||||||
|
// Overriding method from Zeek's plugin API.
|
||||||
|
void Done() override;
|
||||||
|
|
||||||
|
// Overriding method from Zeek's plugin API.
|
||||||
|
int HookLoadFile(const LoadType type, const std::string& file, const std::string& resolved) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Load one *.hlto module.
|
||||||
|
void loadModule(const hilti::rt::filesystem::path& path);
|
||||||
|
|
||||||
|
// Search ZEEK_SPICY_MODULE_PATH for pre-compiled *.hlto modules and load them.
|
||||||
|
void autoDiscoverModules();
|
||||||
|
|
||||||
|
// Recursively search pre-compiled *.hlto in colon-separated paths.
|
||||||
|
void searchModules(const std::string& paths);
|
||||||
|
|
||||||
|
// Return a Zeek location object for the given file name that will stay valid.
|
||||||
|
detail::Location makeLocation(const std::string& fname);
|
||||||
|
|
||||||
|
// Disable any Zeek-side analyzers that are replaced by one of ours.
|
||||||
|
void disableReplacedAnalyzers();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal callback that records the component-to-tag-type mapping for plugin's analyzer.
|
||||||
|
*
|
||||||
|
* @param c component to track
|
||||||
|
* @param tag_type tag type to associate with component
|
||||||
|
*/
|
||||||
|
void trackComponent(plugin::Component* c, int32_t tag_type);
|
||||||
|
|
||||||
|
/** Captures a registered protocol analyzer. */
|
||||||
|
struct ProtocolAnalyzerInfo {
|
||||||
|
// Provided when registering the analyzer.
|
||||||
|
std::string name_analyzer;
|
||||||
|
std::string name_parser_orig;
|
||||||
|
std::string name_parser_resp;
|
||||||
|
std::string name_replaces;
|
||||||
|
hilti::rt::Protocol protocol = hilti::rt::Protocol::Undef;
|
||||||
|
hilti::rt::Vector<hilti::rt::Port> ports;
|
||||||
|
std::string linker_scope;
|
||||||
|
|
||||||
|
// Computed and available once the analyzer has been registered.
|
||||||
|
std::string name_zeek;
|
||||||
|
std::string name_zeekygen;
|
||||||
|
Tag::type_t type;
|
||||||
|
const ::spicy::rt::Parser* parser_orig;
|
||||||
|
const ::spicy::rt::Parser* parser_resp;
|
||||||
|
Tag replaces;
|
||||||
|
|
||||||
|
bool operator==(const ProtocolAnalyzerInfo& other) const {
|
||||||
|
return name_analyzer == other.name_analyzer && name_parser_orig == other.name_parser_orig &&
|
||||||
|
name_parser_resp == other.name_parser_resp && name_replaces == other.name_replaces &&
|
||||||
|
protocol == other.protocol && ports == other.ports && linker_scope == other.linker_scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const ProtocolAnalyzerInfo& other) const { return ! (*this == other); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Captures a registered file analyzer. */
|
||||||
|
struct FileAnalyzerInfo {
|
||||||
|
// Provided when registering the analyzer.
|
||||||
|
std::string name_analyzer;
|
||||||
|
std::string name_parser;
|
||||||
|
std::string name_replaces;
|
||||||
|
hilti::rt::Vector<std::string> mime_types;
|
||||||
|
std::string linker_scope;
|
||||||
|
|
||||||
|
// Computed and available once the analyzer has been registered.
|
||||||
|
std::string name_zeek;
|
||||||
|
std::string name_zeekygen;
|
||||||
|
Tag::type_t type;
|
||||||
|
const ::spicy::rt::Parser* parser;
|
||||||
|
Tag replaces;
|
||||||
|
|
||||||
|
bool operator==(const FileAnalyzerInfo& other) const {
|
||||||
|
return name_analyzer == other.name_analyzer && name_parser == other.name_parser &&
|
||||||
|
name_replaces == other.name_replaces && mime_types == other.mime_types &&
|
||||||
|
linker_scope == other.linker_scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const FileAnalyzerInfo& other) const { return ! (*this == other); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Captures a registered file analyzer. */
|
||||||
|
struct PacketAnalyzerInfo {
|
||||||
|
// Provided when registering the analyzer.
|
||||||
|
std::string name_analyzer;
|
||||||
|
std::string name_parser;
|
||||||
|
std::string name_replaces;
|
||||||
|
std::string linker_scope;
|
||||||
|
|
||||||
|
// Computed and available once the analyzer has been registered.
|
||||||
|
std::string name_zeek;
|
||||||
|
std::string name_zeekygen;
|
||||||
|
Tag::type_t type;
|
||||||
|
const ::spicy::rt::Parser* parser;
|
||||||
|
Tag replaces;
|
||||||
|
|
||||||
|
// Compares only the provided attributes, as that's what defines us.
|
||||||
|
bool operator==(const PacketAnalyzerInfo& other) const {
|
||||||
|
return name_analyzer == other.name_analyzer && name_parser == other.name_parser &&
|
||||||
|
name_replaces == other.name_replaces && linker_scope == other.linker_scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const PacketAnalyzerInfo& other) const { return ! (*this == other); }
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string _spicy_version;
|
||||||
|
|
||||||
|
std::vector<ProtocolAnalyzerInfo> _protocol_analyzers_by_type;
|
||||||
|
std::vector<FileAnalyzerInfo> _file_analyzers_by_type;
|
||||||
|
std::vector<PacketAnalyzerInfo> _packet_analyzers_by_type;
|
||||||
|
std::unordered_map<std::string, hilti::rt::Library> _libraries;
|
||||||
|
std::set<std::string> _locations;
|
||||||
|
std::unordered_map<std::string, detail::IDPtr> _events;
|
||||||
|
|
||||||
|
// Mapping of component names to tag types. We use this to ensure analyzer uniqueness.
|
||||||
|
std::unordered_map<std::string, int32_t> _analyzer_name_to_tag_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace spicy
|
||||||
|
|
||||||
|
extern spicy::Manager* spicy_mgr;
|
||||||
|
|
||||||
|
} // namespace zeek
|
73
src/spicy/packet-analyzer.cc
Normal file
73
src/spicy/packet-analyzer.cc
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#include "zeek/spicy/packet-analyzer.h"
|
||||||
|
|
||||||
|
#include "zeek/spicy/manager.h"
|
||||||
|
#include "zeek/spicy/runtime-support.h"
|
||||||
|
|
||||||
|
using namespace zeek;
|
||||||
|
using namespace zeek::spicy;
|
||||||
|
using namespace zeek::spicy::rt;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define STATE_DEBUG_MSG(...) DebugMsg(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define STATE_DEBUG_MSG(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void PacketState::debug(const std::string& msg) { spicy::rt::debug(_cookie, msg); }
|
||||||
|
|
||||||
|
static auto create_packet_state(PacketAnalyzer* analyzer) {
|
||||||
|
cookie::PacketAnalyzer cookie;
|
||||||
|
cookie.analyzer = analyzer;
|
||||||
|
return PacketState(std::move(cookie));
|
||||||
|
}
|
||||||
|
|
||||||
|
PacketAnalyzer::PacketAnalyzer(std::string name)
|
||||||
|
: packet_analysis::Analyzer(std::move(name)), _state(create_packet_state(this)) {}
|
||||||
|
|
||||||
|
PacketAnalyzer::~PacketAnalyzer() = default;
|
||||||
|
|
||||||
|
bool PacketAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) {
|
||||||
|
if ( auto parser = spicy_mgr->parserForPacketAnalyzer(_state.packet().analyzer->GetAnalyzerTag()) )
|
||||||
|
_state.setParser(parser);
|
||||||
|
else
|
||||||
|
reporter->FatalError("no valid unit specified for parsing");
|
||||||
|
|
||||||
|
try {
|
||||||
|
hilti::rt::context::CookieSetter _(_state.cookie());
|
||||||
|
_state.packet().next_analyzer.reset();
|
||||||
|
_state.packet().packet = packet;
|
||||||
|
_state.process(len, reinterpret_cast<const char*>(data));
|
||||||
|
auto offset = _state.finish();
|
||||||
|
assert(offset);
|
||||||
|
_state.packet().packet = nullptr;
|
||||||
|
_state.packet().packet_val = nullptr;
|
||||||
|
_state.reset();
|
||||||
|
auto num_processed = offset->Ref();
|
||||||
|
const auto& next_analyzer = _state.packet().next_analyzer;
|
||||||
|
STATE_DEBUG_MSG(hilti::rt::fmt("processed %" PRIu64 " out of %" PRIu64 " bytes, %s", num_processed, len,
|
||||||
|
(next_analyzer ? hilti::rt::fmt("next analyzer is 0x%" PRIx32, *next_analyzer) :
|
||||||
|
std::string("no next analyzer"))));
|
||||||
|
if ( next_analyzer )
|
||||||
|
return ForwardPacket(len - num_processed, data + num_processed, packet, *next_analyzer);
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
} catch ( const hilti::rt::RuntimeError& e ) {
|
||||||
|
STATE_DEBUG_MSG(hilti::rt::fmt("error during parsing, triggering analyzer violation: %s", e.what()));
|
||||||
|
auto tag = _state.packet().analyzer->GetAnalyzerTag();
|
||||||
|
|
||||||
|
if ( auto* session = packet->session )
|
||||||
|
_state.packet().analyzer->AnalyzerViolation(e.what(), session, reinterpret_cast<const char*>(data), len,
|
||||||
|
tag);
|
||||||
|
|
||||||
|
_state.reset();
|
||||||
|
return false;
|
||||||
|
} catch ( const hilti::rt::Exception& e ) {
|
||||||
|
STATE_DEBUG_MSG(e.what());
|
||||||
|
spicy_mgr->analyzerError(_state.packet().analyzer, e.description(),
|
||||||
|
e.location()); // this sets Zeek to skip sending any further input
|
||||||
|
_state.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
75
src/spicy/packet-analyzer.h
Normal file
75
src/spicy/packet-analyzer.h
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <hilti/rt/types/stream.h>
|
||||||
|
|
||||||
|
#include <spicy/rt/driver.h>
|
||||||
|
#include <spicy/rt/parser.h>
|
||||||
|
|
||||||
|
#include "zeek/spicy/cookie.h"
|
||||||
|
|
||||||
|
namespace zeek::spicy::rt {
|
||||||
|
|
||||||
|
/** Parsing state for a packet. */
|
||||||
|
class PacketState : public ::spicy::rt::driver::ParsingState {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param cookie cookie to associated with the packet
|
||||||
|
*/
|
||||||
|
PacketState(Cookie cookie) : ParsingState(::spicy::rt::driver::ParsingType::Block), _cookie(std::move(cookie)) {}
|
||||||
|
|
||||||
|
/** Returns the cookie pointer to use with the runtime library during analysis. */
|
||||||
|
auto* cookie() { return &_cookie; }
|
||||||
|
|
||||||
|
/** Returns the packet-specific cookie state associated with the endpoint. */
|
||||||
|
auto& packet() {
|
||||||
|
assert(_cookie.packet);
|
||||||
|
return *_cookie.packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Records a debug message pertaining to the specific file.
|
||||||
|
*
|
||||||
|
* @param msg message to record
|
||||||
|
*/
|
||||||
|
void DebugMsg(const std::string& msg) { debug(msg); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Overridden from driver::ParsingState.
|
||||||
|
void debug(const std::string& msg) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Cookie _cookie;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A Spicy file analyzer. */
|
||||||
|
class PacketAnalyzer : public packet_analysis::Analyzer {
|
||||||
|
public:
|
||||||
|
PacketAnalyzer(std::string name);
|
||||||
|
virtual ~PacketAnalyzer();
|
||||||
|
|
||||||
|
/** Records a debug message. */
|
||||||
|
void DebugMsg(const std::string& msg) { _state.DebugMsg(msg); }
|
||||||
|
|
||||||
|
static packet_analysis::AnalyzerPtr Instantiate(std::string name) {
|
||||||
|
name = util::canonify_name(name);
|
||||||
|
return std::make_shared<PacketAnalyzer>(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Overridden from Zeek's packet analyzer.
|
||||||
|
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PacketState _state;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace zeek::spicy::rt
|
236
src/spicy/protocol-analyzer.cc
Normal file
236
src/spicy/protocol-analyzer.cc
Normal file
|
@ -0,0 +1,236 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#include "zeek/spicy/protocol-analyzer.h"
|
||||||
|
|
||||||
|
#include "zeek/spicy/manager.h"
|
||||||
|
#include "zeek/spicy/runtime-support.h"
|
||||||
|
|
||||||
|
using namespace zeek;
|
||||||
|
using namespace zeek::spicy;
|
||||||
|
using namespace zeek::spicy::rt;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define STATE_DEBUG_MSG(...) DebugMsg(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define STATE_DEBUG_MSG(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void EndpointState::debug(const std::string& msg) { spicy::rt::debug(_cookie, msg); }
|
||||||
|
|
||||||
|
static auto create_endpoint(bool is_orig, analyzer::Analyzer* analyzer, ::spicy::rt::driver::ParsingType type) {
|
||||||
|
static uint64_t id_counter = 0;
|
||||||
|
|
||||||
|
++id_counter;
|
||||||
|
|
||||||
|
cookie::ProtocolAnalyzer cookie{.analyzer = analyzer,
|
||||||
|
.is_orig = is_orig,
|
||||||
|
.fstate_orig =
|
||||||
|
cookie::FileStateStack(hilti::rt::fmt("%" PRIx64 ".orig", id_counter)),
|
||||||
|
.fstate_resp =
|
||||||
|
cookie::FileStateStack(hilti::rt::fmt("%" PRIx64 ".resp", id_counter))};
|
||||||
|
|
||||||
|
// Cannot get parser here yet, analyzer may not have been fully set up.
|
||||||
|
return EndpointState(std::move(cookie), type);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtocolAnalyzer::ProtocolAnalyzer(analyzer::Analyzer* analyzer, ::spicy::rt::driver::ParsingType type)
|
||||||
|
: _originator(create_endpoint(true, analyzer, type)), _responder(create_endpoint(false, analyzer, type)) {}
|
||||||
|
|
||||||
|
ProtocolAnalyzer::~ProtocolAnalyzer() {}
|
||||||
|
|
||||||
|
void ProtocolAnalyzer::Init() {}
|
||||||
|
|
||||||
|
void ProtocolAnalyzer::Done() {
|
||||||
|
Finish(true);
|
||||||
|
Finish(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolAnalyzer::Process(bool is_orig, int len, const u_char* data) {
|
||||||
|
auto* endp = is_orig ? &_originator : &_responder;
|
||||||
|
|
||||||
|
if ( endp->protocol().analyzer->Skipping() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( ! endp->hasParser() && ! endp->isSkipping() ) {
|
||||||
|
auto parser = spicy_mgr->parserForProtocolAnalyzer(endp->protocol().analyzer->GetAnalyzerTag(), is_orig);
|
||||||
|
if ( parser ) {
|
||||||
|
if ( ! _context )
|
||||||
|
_context = parser->createContext();
|
||||||
|
|
||||||
|
endp->setParser(parser, _context);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
STATE_DEBUG_MSG(is_orig, "no unit specified for parsing");
|
||||||
|
endp->skipRemaining();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
hilti::rt::context::CookieSetter _(endp->cookie());
|
||||||
|
endp->process(len, reinterpret_cast<const char*>(data));
|
||||||
|
} catch ( const hilti::rt::RuntimeError& e ) {
|
||||||
|
STATE_DEBUG_MSG(is_orig, hilti::rt::fmt("error during parsing, triggering analyzer violation: %s", e.what()));
|
||||||
|
auto tag = spicy_mgr->tagForProtocolAnalyzer(endp->protocol().analyzer->GetAnalyzerTag());
|
||||||
|
endp->protocol().analyzer->AnalyzerViolation(e.what(), reinterpret_cast<const char*>(data), len, tag);
|
||||||
|
originator().skipRemaining();
|
||||||
|
responder().skipRemaining();
|
||||||
|
endp->protocol().analyzer->SetSkip(true);
|
||||||
|
} catch ( const hilti::rt::Exception& e ) {
|
||||||
|
spicy_mgr->analyzerError(endp->protocol().analyzer, e.description(),
|
||||||
|
e.location()); // this sets Zeek to skip sending any further input
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolAnalyzer::Finish(bool is_orig) {
|
||||||
|
auto* endp = is_orig ? &_originator : &_responder;
|
||||||
|
|
||||||
|
if ( endp->protocol().analyzer->Skipping() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
hilti::rt::context::CookieSetter _(endp->cookie());
|
||||||
|
endp->finish();
|
||||||
|
} catch ( const hilti::rt::RuntimeError& e ) {
|
||||||
|
STATE_DEBUG_MSG(is_orig, hilti::rt::fmt("error during parsing, triggering analyzer violation: %s", e.what()));
|
||||||
|
auto tag = spicy_mgr->tagForProtocolAnalyzer(endp->protocol().analyzer->GetAnalyzerTag());
|
||||||
|
endp->protocol().analyzer->AnalyzerViolation(e.what(), nullptr, 0, tag);
|
||||||
|
endp->skipRemaining();
|
||||||
|
} catch ( const hilti::rt::Exception& e ) {
|
||||||
|
spicy_mgr->analyzerError(endp->protocol().analyzer, e.description(),
|
||||||
|
e.location()); // this sets Zeek to skip sending any further input
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cookie::ProtocolAnalyzer& ProtocolAnalyzer::cookie(bool is_orig) {
|
||||||
|
if ( is_orig )
|
||||||
|
return _originator.protocol();
|
||||||
|
else
|
||||||
|
return _responder.protocol();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolAnalyzer::DebugMsg(bool is_orig, const std::string& msg) {
|
||||||
|
if ( is_orig )
|
||||||
|
_originator.DebugMsg(msg);
|
||||||
|
else
|
||||||
|
_responder.DebugMsg(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolAnalyzer::FlipRoles() { std::swap(_originator, _responder); }
|
||||||
|
|
||||||
|
analyzer::Analyzer* TCP_Analyzer::InstantiateAnalyzer(Connection* conn) { return new TCP_Analyzer(conn); }
|
||||||
|
|
||||||
|
TCP_Analyzer::TCP_Analyzer(Connection* conn)
|
||||||
|
: ProtocolAnalyzer(this, ::spicy::rt::driver::ParsingType::Stream), analyzer::tcp::TCP_ApplicationAnalyzer(conn) {}
|
||||||
|
|
||||||
|
TCP_Analyzer::~TCP_Analyzer() {}
|
||||||
|
|
||||||
|
void TCP_Analyzer::Init() {
|
||||||
|
analyzer::tcp::TCP_ApplicationAnalyzer::Init();
|
||||||
|
ProtocolAnalyzer::Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCP_Analyzer::Done() {
|
||||||
|
analyzer::tcp::TCP_ApplicationAnalyzer::Done();
|
||||||
|
ProtocolAnalyzer::Done();
|
||||||
|
|
||||||
|
EndOfData(true);
|
||||||
|
EndOfData(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCP_Analyzer::DeliverStream(int len, const u_char* data, bool is_orig) {
|
||||||
|
analyzer::tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, is_orig);
|
||||||
|
|
||||||
|
Process(is_orig, len, data);
|
||||||
|
|
||||||
|
if ( originator().isFinished() && responder().isFinished() &&
|
||||||
|
(! originator().isSkipping() || ! responder().isSkipping()) ) {
|
||||||
|
STATE_DEBUG_MSG(is_orig, "both endpoints finished, skipping all further TCP processing");
|
||||||
|
originator().skipRemaining();
|
||||||
|
responder().skipRemaining();
|
||||||
|
|
||||||
|
if ( is_orig ) // doesn't really matter which endpoint here.
|
||||||
|
originator().protocol().analyzer->SetSkip(true);
|
||||||
|
else
|
||||||
|
responder().protocol().analyzer->SetSkip(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCP_Analyzer::Undelivered(uint64_t seq, int len, bool is_orig) {
|
||||||
|
analyzer::tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, is_orig);
|
||||||
|
|
||||||
|
Process(is_orig, len, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCP_Analyzer::EndOfData(bool is_orig) {
|
||||||
|
analyzer::tcp::TCP_ApplicationAnalyzer::EndOfData(is_orig);
|
||||||
|
|
||||||
|
if ( TCP() && TCP()->IsPartial() ) {
|
||||||
|
STATE_DEBUG_MSG(is_orig, "skipping end-of-data delivery on partial TCP connection");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Finish(is_orig);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCP_Analyzer::FlipRoles() {
|
||||||
|
analyzer::tcp::TCP_ApplicationAnalyzer::FlipRoles();
|
||||||
|
ProtocolAnalyzer::FlipRoles();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCP_Analyzer::EndpointEOF(bool is_orig) {
|
||||||
|
analyzer::tcp::TCP_ApplicationAnalyzer::EndpointEOF(is_orig);
|
||||||
|
Finish(is_orig);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCP_Analyzer::ConnectionClosed(analyzer::tcp::TCP_Endpoint* endpoint, analyzer::tcp::TCP_Endpoint* peer,
|
||||||
|
bool gen_event) {
|
||||||
|
analyzer::tcp::TCP_ApplicationAnalyzer::ConnectionClosed(endpoint, peer, gen_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCP_Analyzer::ConnectionFinished(bool half_finished) {
|
||||||
|
analyzer::tcp::TCP_ApplicationAnalyzer::ConnectionFinished(half_finished);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCP_Analyzer::ConnectionReset() { analyzer::tcp::TCP_ApplicationAnalyzer::ConnectionReset(); }
|
||||||
|
|
||||||
|
void TCP_Analyzer::PacketWithRST() { analyzer::tcp::TCP_ApplicationAnalyzer::PacketWithRST(); }
|
||||||
|
|
||||||
|
analyzer::Analyzer* UDP_Analyzer::InstantiateAnalyzer(Connection* conn) { return new UDP_Analyzer(conn); }
|
||||||
|
|
||||||
|
UDP_Analyzer::UDP_Analyzer(Connection* conn)
|
||||||
|
: ProtocolAnalyzer(this, ::spicy::rt::driver::ParsingType::Block), analyzer::Analyzer(conn) {}
|
||||||
|
|
||||||
|
UDP_Analyzer::~UDP_Analyzer() {}
|
||||||
|
|
||||||
|
void UDP_Analyzer::Init() {
|
||||||
|
analyzer::Analyzer::Init();
|
||||||
|
ProtocolAnalyzer::Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDP_Analyzer::Done() {
|
||||||
|
analyzer::Analyzer::Done();
|
||||||
|
ProtocolAnalyzer::Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, uint64_t seq, const IP_Hdr* ip,
|
||||||
|
int caplen) {
|
||||||
|
analyzer::Analyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen);
|
||||||
|
|
||||||
|
++cookie(is_orig).num_packets;
|
||||||
|
Process(is_orig, len, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDP_Analyzer::Undelivered(uint64_t seq, int len, bool is_orig) {
|
||||||
|
analyzer::Analyzer::Undelivered(seq, len, is_orig);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDP_Analyzer::EndOfData(bool is_orig) {
|
||||||
|
analyzer::Analyzer::EndOfData(is_orig);
|
||||||
|
Finish(is_orig);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDP_Analyzer::FlipRoles() {
|
||||||
|
analyzer::Analyzer::FlipRoles();
|
||||||
|
ProtocolAnalyzer::FlipRoles();
|
||||||
|
}
|
166
src/spicy/protocol-analyzer.h
Normal file
166
src/spicy/protocol-analyzer.h
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <hilti/rt/types/stream.h>
|
||||||
|
|
||||||
|
#include <spicy/rt/driver.h>
|
||||||
|
#include <spicy/rt/parser.h>
|
||||||
|
|
||||||
|
#include "zeek/spicy/cookie.h"
|
||||||
|
|
||||||
|
namespace zeek::spicy::rt {
|
||||||
|
|
||||||
|
/** Parsing state for one endpoint of the connection. */
|
||||||
|
class EndpointState : public ::spicy::rt::driver::ParsingState {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param cookie cookie to associated with the endpoint
|
||||||
|
* @param type type of parsing, depending on whether it's a stream- or
|
||||||
|
* packet-based protocol
|
||||||
|
*/
|
||||||
|
EndpointState(Cookie cookie, ::spicy::rt::driver::ParsingType type)
|
||||||
|
: ParsingState(type), _cookie(std::move(cookie)) {}
|
||||||
|
|
||||||
|
/** Returns the protocol-specific cookie state associated with the endpoint. */
|
||||||
|
auto& protocol() {
|
||||||
|
assert(_cookie.protocol);
|
||||||
|
return *_cookie.protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the cookie pointer to use with the runtime library during analysis. */
|
||||||
|
auto* cookie() { return &_cookie; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Records a debug message pertaining to this specific endpoint.
|
||||||
|
*
|
||||||
|
* @param msg message to record
|
||||||
|
*/
|
||||||
|
void DebugMsg(const std::string& msg) { debug(msg); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Overridden from driver::ParsingState.
|
||||||
|
void debug(const std::string& msg) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Cookie _cookie;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Base clase for Spicy protocol analyzers. */
|
||||||
|
class ProtocolAnalyzer {
|
||||||
|
public:
|
||||||
|
ProtocolAnalyzer(analyzer::Analyzer* analyzer, ::spicy::rt::driver::ParsingType type);
|
||||||
|
virtual ~ProtocolAnalyzer();
|
||||||
|
|
||||||
|
/** Returns the originator-side parsing state. */
|
||||||
|
auto& originator() { return _originator; }
|
||||||
|
|
||||||
|
/** Returns the responder-side parsing state. */
|
||||||
|
auto& responder() { return _responder; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** Initialize analyzer. */
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
/** Shutdown analyzer. */
|
||||||
|
void Done();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal that Zeek has flipped the direction of the connection, meaning
|
||||||
|
* that originator and responder state need to be swapped.
|
||||||
|
*/
|
||||||
|
void FlipRoles();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Feeds a chunk of data into one side's parsing.
|
||||||
|
*
|
||||||
|
* @param is_orig true to use originator-side endpoint state, false for responder
|
||||||
|
* @param len number of bytes valid in *data*
|
||||||
|
* @param data pointer to data
|
||||||
|
*/
|
||||||
|
void Process(bool is_orig, int len, const u_char* data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalizes parsing. After calling this, no more data must be passed
|
||||||
|
* into Process() for the corresponding side.
|
||||||
|
*
|
||||||
|
* @param is_orig true to finish originator-side parsing, false for responder
|
||||||
|
*/
|
||||||
|
void Finish(bool is_orig);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper returning the protocol analyzer cookie for the requested side.
|
||||||
|
*
|
||||||
|
* @param is_orig tru to return the originator's state, false for the
|
||||||
|
* responder.
|
||||||
|
* @return protocol analyzer cookie for the requested side
|
||||||
|
*/
|
||||||
|
cookie::ProtocolAnalyzer& cookie(bool is_orig);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Records a debug message. This forwards to `DebugMsg()` for the
|
||||||
|
* corresponding `EndpointState`.
|
||||||
|
*/
|
||||||
|
void DebugMsg(bool is_orig, const std::string& msg);
|
||||||
|
|
||||||
|
private:
|
||||||
|
EndpointState _originator; /**< Originator-side state. */
|
||||||
|
EndpointState _responder; /**< Responder-side state. */
|
||||||
|
std::optional<::spicy::rt::UnitContext> _context;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spicy analyzer for TCP application-layer protocols. Implements the
|
||||||
|
* standard Zeek API.
|
||||||
|
*/
|
||||||
|
class TCP_Analyzer : public ProtocolAnalyzer, public analyzer::tcp::TCP_ApplicationAnalyzer {
|
||||||
|
public:
|
||||||
|
TCP_Analyzer(Connection* conn);
|
||||||
|
virtual ~TCP_Analyzer();
|
||||||
|
|
||||||
|
// Overridden from Spicy's Analyzer.
|
||||||
|
void Init() override;
|
||||||
|
void Done() override;
|
||||||
|
void DeliverStream(int len, const u_char* data, bool orig) override;
|
||||||
|
void Undelivered(uint64_t seq, int len, bool orig) override;
|
||||||
|
void EndOfData(bool is_orig) override;
|
||||||
|
void FlipRoles() override;
|
||||||
|
|
||||||
|
// Overridden from Zeek's TCP_ApplicationAnalyzer.
|
||||||
|
void EndpointEOF(bool is_orig) override;
|
||||||
|
void ConnectionClosed(analyzer::tcp::TCP_Endpoint* endpoint, analyzer::tcp::TCP_Endpoint* peer,
|
||||||
|
bool gen_event) override;
|
||||||
|
void ConnectionFinished(bool half_finished) override;
|
||||||
|
void ConnectionReset() override;
|
||||||
|
void PacketWithRST() override;
|
||||||
|
|
||||||
|
static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spicy analyzer for UDP application-layer protocols. Implements the
|
||||||
|
* standard Zeek API.
|
||||||
|
*/
|
||||||
|
class UDP_Analyzer : public ProtocolAnalyzer, public analyzer::Analyzer {
|
||||||
|
public:
|
||||||
|
UDP_Analyzer(Connection* conn);
|
||||||
|
virtual ~UDP_Analyzer();
|
||||||
|
|
||||||
|
// Overridden from Spicy's Analyzer.
|
||||||
|
void Init() override;
|
||||||
|
void Done() override;
|
||||||
|
void DeliverPacket(int len, const u_char* data, bool orig, uint64_t seq, const IP_Hdr* ip, int caplen) override;
|
||||||
|
void Undelivered(uint64_t seq, int len, bool orig) override;
|
||||||
|
void EndOfData(bool is_orig) override;
|
||||||
|
void FlipRoles() override;
|
||||||
|
|
||||||
|
static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace zeek::spicy::rt
|
842
src/spicy/runtime-support.cc
Normal file
842
src/spicy/runtime-support.cc
Normal file
|
@ -0,0 +1,842 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#include "zeek/spicy/runtime-support.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <hilti/rt/exception.h>
|
||||||
|
#include <hilti/rt/profiler.h>
|
||||||
|
#include <hilti/rt/types/port.h>
|
||||||
|
#include <hilti/rt/util.h>
|
||||||
|
|
||||||
|
#include "zeek/Event.h"
|
||||||
|
#include "zeek/analyzer/Manager.h"
|
||||||
|
#include "zeek/analyzer/protocol/pia/PIA.h"
|
||||||
|
#include "zeek/file_analysis/File.h"
|
||||||
|
#include "zeek/file_analysis/Manager.h"
|
||||||
|
#include "zeek/spicy/manager.h"
|
||||||
|
|
||||||
|
using namespace zeek;
|
||||||
|
using namespace zeek::spicy;
|
||||||
|
|
||||||
|
void rt::register_protocol_analyzer(const std::string& name, hilti::rt::Protocol proto,
|
||||||
|
const hilti::rt::Vector<hilti::rt::Port>& ports, const std::string& parser_orig,
|
||||||
|
const std::string& parser_resp, const std::string& replaces,
|
||||||
|
const std::string& linker_scope) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/register_protocol_analyzer");
|
||||||
|
spicy_mgr->registerProtocolAnalyzer(name, proto, ports, parser_orig, parser_resp, replaces, linker_scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::register_file_analyzer(const std::string& name, const hilti::rt::Vector<std::string>& mime_types,
|
||||||
|
const std::string& parser, const std::string& replaces,
|
||||||
|
const std::string& linker_scope) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/register_file_analyzer");
|
||||||
|
spicy_mgr->registerFileAnalyzer(name, mime_types, parser, replaces, linker_scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::register_packet_analyzer(const std::string& name, const std::string& parser, const std::string& replaces,
|
||||||
|
const std::string& linker_scope) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/register_packet_analyzer");
|
||||||
|
spicy_mgr->registerPacketAnalyzer(name, parser, replaces, linker_scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::register_type(const std::string& ns, const std::string& id, const TypePtr& type) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/register_type");
|
||||||
|
spicy_mgr->registerType(hilti::rt::fmt("%s::%s", (! ns.empty() ? ns : std::string("GLOBAL")), id), type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to look up a global Zeek-side type, enforcing that it's of the expected type.
|
||||||
|
static TypePtr findType(TypeTag tag, const std::string& ns, const std::string& id) {
|
||||||
|
auto id_ = hilti::rt::fmt("%s::%s", ns, id);
|
||||||
|
auto type = spicy_mgr->findType(id_);
|
||||||
|
|
||||||
|
if ( ! type )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if ( type->Tag() != tag )
|
||||||
|
reporter->FatalError("ID %s is not of expected type %s", id_.c_str(), type_name(tag));
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
TypePtr rt::create_base_type(ZeekTypeTag tag) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/create_base_type");
|
||||||
|
TypeTag ztag;
|
||||||
|
|
||||||
|
switch ( tag ) {
|
||||||
|
case ZeekTypeTag::Addr: ztag = TYPE_ADDR; break;
|
||||||
|
case ZeekTypeTag::Any: ztag = TYPE_ANY; break;
|
||||||
|
case ZeekTypeTag::Bool: ztag = TYPE_BOOL; break;
|
||||||
|
case ZeekTypeTag::Count: ztag = TYPE_COUNT; break;
|
||||||
|
case ZeekTypeTag::Double: ztag = TYPE_DOUBLE; break;
|
||||||
|
case ZeekTypeTag::Enum: ztag = TYPE_ENUM; break;
|
||||||
|
case ZeekTypeTag::Error: ztag = TYPE_ERROR; break;
|
||||||
|
case ZeekTypeTag::File: ztag = TYPE_FILE; break;
|
||||||
|
case ZeekTypeTag::Func: ztag = TYPE_FUNC; break;
|
||||||
|
case ZeekTypeTag::List: ztag = TYPE_LIST; break;
|
||||||
|
case ZeekTypeTag::Int: ztag = TYPE_INT; break;
|
||||||
|
case ZeekTypeTag::Interval: ztag = TYPE_INTERVAL; break;
|
||||||
|
case ZeekTypeTag::Opaque: ztag = TYPE_OPAQUE; break;
|
||||||
|
case ZeekTypeTag::Pattern: ztag = TYPE_PATTERN; break;
|
||||||
|
case ZeekTypeTag::Port: ztag = TYPE_PORT; break;
|
||||||
|
case ZeekTypeTag::Record: ztag = TYPE_RECORD; break;
|
||||||
|
case ZeekTypeTag::String: ztag = TYPE_STRING; break;
|
||||||
|
case ZeekTypeTag::Subnet: ztag = TYPE_SUBNET; break;
|
||||||
|
case ZeekTypeTag::Table: ztag = TYPE_TABLE; break;
|
||||||
|
case ZeekTypeTag::Time: ztag = TYPE_TIME; break;
|
||||||
|
case ZeekTypeTag::Type: ztag = TYPE_TYPE; break;
|
||||||
|
case ZeekTypeTag::Vector: ztag = TYPE_VECTOR; break;
|
||||||
|
case ZeekTypeTag::Void: ztag = TYPE_VOID; break;
|
||||||
|
default: hilti::rt::cannot_be_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
return base_type(ztag);
|
||||||
|
}
|
||||||
|
|
||||||
|
TypePtr rt::create_enum_type(
|
||||||
|
const std::string& ns, const std::string& id,
|
||||||
|
const hilti::rt::Vector<std::tuple<std::string, hilti::rt::integer::safe<int64_t>>>& labels) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/create_enum_type");
|
||||||
|
|
||||||
|
if ( auto t = findType(TYPE_ENUM, ns, id) )
|
||||||
|
return t;
|
||||||
|
|
||||||
|
auto etype = make_intrusive<EnumType>(ns + "::" + id);
|
||||||
|
|
||||||
|
for ( auto [lid, lval] : labels ) {
|
||||||
|
auto name = ::hilti::rt::fmt("%s_%s", id, lid);
|
||||||
|
|
||||||
|
if ( lval == -1 )
|
||||||
|
// Zeek's enum can't be negative, so swap in max_int for our Undef.
|
||||||
|
lval = std::numeric_limits<::zeek_int_t>::max();
|
||||||
|
|
||||||
|
etype->AddName(ns, name.c_str(), lval, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return etype;
|
||||||
|
}
|
||||||
|
|
||||||
|
TypePtr rt::create_record_type(const std::string& ns, const std::string& id,
|
||||||
|
const hilti::rt::Vector<RecordField>& fields) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/create_record_type");
|
||||||
|
|
||||||
|
if ( auto t = findType(TYPE_RECORD, ns, id) )
|
||||||
|
return t;
|
||||||
|
|
||||||
|
auto decls = std::make_unique<type_decl_list>();
|
||||||
|
|
||||||
|
for ( const auto& [id, type, optional] : fields ) {
|
||||||
|
auto attrs = make_intrusive<detail::Attributes>(nullptr, true, false);
|
||||||
|
|
||||||
|
if ( optional ) {
|
||||||
|
auto optional_ = make_intrusive<detail::Attr>(detail::ATTR_OPTIONAL);
|
||||||
|
attrs->AddAttr(optional_);
|
||||||
|
}
|
||||||
|
|
||||||
|
decls->append(new TypeDecl(util::copy_string(id.c_str()), type, std::move(attrs)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return make_intrusive<RecordType>(decls.release());
|
||||||
|
}
|
||||||
|
|
||||||
|
TypePtr rt::create_table_type(TypePtr key, std::optional<TypePtr> value) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/create_table_type");
|
||||||
|
auto idx = make_intrusive<TypeList>();
|
||||||
|
idx->Append(std::move(key));
|
||||||
|
return make_intrusive<TableType>(std::move(idx), value ? *value : nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TypePtr rt::create_vector_type(const TypePtr& elem) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/create_vector_type");
|
||||||
|
return make_intrusive<VectorType>(elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::install_handler(const std::string& name) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/install_handler");
|
||||||
|
spicy_mgr->registerEvent(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
EventHandlerPtr rt::internal_handler(const std::string& name) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/internal_handler");
|
||||||
|
auto handler = event_registry->Lookup(name);
|
||||||
|
|
||||||
|
if ( ! handler )
|
||||||
|
reporter->InternalError("Spicy event %s was not installed", name.c_str());
|
||||||
|
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::raise_event(const EventHandlerPtr& handler, const hilti::rt::Vector<ValPtr>& args) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/raise_event");
|
||||||
|
|
||||||
|
// Caller must have checked already that there's a handler available.
|
||||||
|
assert(handler);
|
||||||
|
|
||||||
|
const auto& zeek_args = const_cast<EventHandlerPtr&>(handler)->GetType()->ParamList()->GetTypes();
|
||||||
|
if ( args.size() != static_cast<uint64_t>(zeek_args.size()) )
|
||||||
|
throw TypeMismatch(hilti::rt::fmt("expected %" PRIu64 " parameters, but got %zu",
|
||||||
|
static_cast<uint64_t>(zeek_args.size()), args.size()));
|
||||||
|
|
||||||
|
Args vl = Args();
|
||||||
|
vl.reserve(args.size());
|
||||||
|
for ( const auto& v : args ) {
|
||||||
|
if ( v )
|
||||||
|
vl.emplace_back(v);
|
||||||
|
else
|
||||||
|
// Shouldn't happen here, but we have to_vals() that
|
||||||
|
// (legitimately) return null in certain contexts.
|
||||||
|
throw InvalidValue("null value encountered after conversion");
|
||||||
|
}
|
||||||
|
|
||||||
|
event_mgr.Enqueue(handler, std::move(vl));
|
||||||
|
}
|
||||||
|
|
||||||
|
TypePtr rt::event_arg_type(const EventHandlerPtr& handler, const hilti::rt::integer::safe<uint64_t>& idx) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/event_arg_type");
|
||||||
|
assert(handler);
|
||||||
|
|
||||||
|
const auto& zeek_args = const_cast<EventHandlerPtr&>(handler)->GetType()->ParamList()->GetTypes();
|
||||||
|
if ( idx >= static_cast<uint64_t>(zeek_args.size()) )
|
||||||
|
throw TypeMismatch(hilti::rt::fmt("more parameters given than the %" PRIu64 " that the Zeek event expects",
|
||||||
|
static_cast<uint64_t>(zeek_args.size())));
|
||||||
|
|
||||||
|
return zeek_args[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
ValPtr& rt::current_conn() {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/current_conn");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
if ( cookie->cache.conn )
|
||||||
|
return cookie->cache.conn;
|
||||||
|
|
||||||
|
if ( auto x = cookie->protocol ) {
|
||||||
|
cookie->cache.conn = x->analyzer->Conn()->GetVal();
|
||||||
|
return cookie->cache.conn;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw ValueUnavailable("$conn not available");
|
||||||
|
}
|
||||||
|
|
||||||
|
ValPtr& rt::current_is_orig() {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/current_is_orig");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
if ( cookie->cache.is_orig )
|
||||||
|
return cookie->cache.is_orig;
|
||||||
|
|
||||||
|
if ( auto x = cookie->protocol ) {
|
||||||
|
cookie->cache.is_orig = val_mgr->Bool(x->is_orig);
|
||||||
|
return cookie->cache.is_orig;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw ValueUnavailable("$is_orig not available");
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::debug(const std::string& msg) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/debug");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
rt::debug(*cookie, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::debug(const Cookie& cookie, const std::string& msg) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/debug");
|
||||||
|
std::string name;
|
||||||
|
std::string id;
|
||||||
|
|
||||||
|
if ( const auto p = cookie.protocol ) {
|
||||||
|
auto name = p->analyzer->GetAnalyzerName();
|
||||||
|
SPICY_DEBUG(
|
||||||
|
hilti::rt::fmt("[%s/%" PRIu32 "/%s] %s", name, p->analyzer->GetID(), (p->is_orig ? "orig" : "resp"), msg));
|
||||||
|
}
|
||||||
|
else if ( const auto f = cookie.file ) {
|
||||||
|
auto name = file_mgr->GetComponentName(f->analyzer->Tag());
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("[%s/%" PRIu32 "] %s", name, f->analyzer->GetID(), msg));
|
||||||
|
}
|
||||||
|
else if ( const auto f = cookie.packet ) {
|
||||||
|
auto name = packet_mgr->GetComponentName(f->analyzer->GetAnalyzerTag());
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("[%s] %s", name, msg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw ValueUnavailable("neither $conn nor $file nor packet analyzer available for debug logging");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline rt::cookie::FileStateStack* _file_state_stack(rt::Cookie* cookie) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/file_state_stack");
|
||||||
|
|
||||||
|
if ( auto c = cookie->protocol )
|
||||||
|
return c->is_orig ? &c->fstate_orig : &c->fstate_resp;
|
||||||
|
else if ( auto f = cookie->file )
|
||||||
|
return &f->fstate;
|
||||||
|
else
|
||||||
|
throw rt::ValueUnavailable("no current connection or file available");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const rt::cookie::FileState* _file_state(rt::Cookie* cookie, std::optional<std::string> fid) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/file_state");
|
||||||
|
|
||||||
|
auto* stack = _file_state_stack(cookie);
|
||||||
|
if ( fid ) {
|
||||||
|
if ( auto* fstate = stack->find(*fid) )
|
||||||
|
return fstate;
|
||||||
|
else
|
||||||
|
throw rt::ValueUnavailable(hilti::rt::fmt("no file analysis currently in flight for file ID %s", fid));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( stack->isEmpty() )
|
||||||
|
throw rt::ValueUnavailable("no file analysis currently in flight");
|
||||||
|
|
||||||
|
return stack->current();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ValPtr rt::current_file() {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/current_file");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
if ( auto x = cookie->file )
|
||||||
|
return x->analyzer->GetFile()->ToVal();
|
||||||
|
else if ( auto* fstate = _file_state(cookie, {}) ) {
|
||||||
|
if ( auto* f = file_mgr->LookupFile(fstate->fid) )
|
||||||
|
return f->ToVal();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw ValueUnavailable("$file not available");
|
||||||
|
}
|
||||||
|
|
||||||
|
ValPtr rt::current_packet() {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/current_packet");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
if ( auto c = cookie->packet ) {
|
||||||
|
if ( ! c->packet_val )
|
||||||
|
// We cache the built value in case we need it multiple times.
|
||||||
|
c->packet_val = c->packet->ToRawPktHdrVal();
|
||||||
|
|
||||||
|
return c->packet_val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw ValueUnavailable("$packet not available");
|
||||||
|
}
|
||||||
|
|
||||||
|
hilti::rt::Bool rt::is_orig() {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/is_orig");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
if ( auto x = cookie->protocol )
|
||||||
|
return x->is_orig;
|
||||||
|
else
|
||||||
|
throw ValueUnavailable("is_orig() not available in current context");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string rt::uid() {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/uid");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
if ( auto c = cookie->protocol ) {
|
||||||
|
// Retrieve the ConnVal() so that we ensure the UID has been set.
|
||||||
|
c->analyzer->ConnVal();
|
||||||
|
return c->analyzer->Conn()->GetUID().Base62("C");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw ValueUnavailable("uid() not available in current context");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<hilti::rt::Address, hilti::rt::Port, hilti::rt::Address, hilti::rt::Port> rt::conn_id() {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/conn_id");
|
||||||
|
|
||||||
|
static auto convert_address = [](const IPAddr& zaddr) -> hilti::rt::Address {
|
||||||
|
const uint32_t* bytes = nullptr;
|
||||||
|
if ( auto n = zaddr.GetBytes(&bytes); n == 1 )
|
||||||
|
// IPv4
|
||||||
|
return hilti::rt::Address(*reinterpret_cast<const struct in_addr*>(bytes));
|
||||||
|
else if ( n == 4 )
|
||||||
|
// IPv6
|
||||||
|
return hilti::rt::Address(*reinterpret_cast<const struct in6_addr*>(bytes));
|
||||||
|
else
|
||||||
|
throw ValueUnavailable("unexpected IP address side from Zeek"); // shouldn't really be able to happen
|
||||||
|
};
|
||||||
|
|
||||||
|
static auto convert_port = [](uint32_t port, TransportProto proto) -> hilti::rt::Port {
|
||||||
|
auto p = ntohs(static_cast<uint16_t>(port));
|
||||||
|
|
||||||
|
switch ( proto ) {
|
||||||
|
case TransportProto::TRANSPORT_ICMP: return {p, hilti::rt::Protocol::ICMP};
|
||||||
|
case TransportProto::TRANSPORT_TCP: return {p, hilti::rt::Protocol::TCP};
|
||||||
|
case TransportProto::TRANSPORT_UDP: return {p, hilti::rt::Protocol::UDP};
|
||||||
|
case TransportProto::TRANSPORT_UNKNOWN: return {p, hilti::rt::Protocol::Undef};
|
||||||
|
}
|
||||||
|
|
||||||
|
hilti::rt::cannot_be_reached();
|
||||||
|
};
|
||||||
|
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
if ( auto c = cookie->protocol ) {
|
||||||
|
const auto* conn = c->analyzer->Conn();
|
||||||
|
return std::make_tuple(convert_address(conn->OrigAddr()), convert_port(conn->OrigPort(), conn->ConnTransport()),
|
||||||
|
convert_address(conn->RespAddr()),
|
||||||
|
convert_port(conn->RespPort(), conn->ConnTransport()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw ValueUnavailable("conn_id() not available in current context");
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::flip_roles() {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/flip_roles");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
rt::debug(*cookie, "flipping roles");
|
||||||
|
|
||||||
|
if ( auto x = cookie->protocol )
|
||||||
|
x->analyzer->Conn()->FlipRoles();
|
||||||
|
else
|
||||||
|
throw ValueUnavailable("flip_roles() not available in current context");
|
||||||
|
}
|
||||||
|
|
||||||
|
hilti::rt::integer::safe<uint64_t> rt::number_packets() {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/number_packets");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
if ( auto x = cookie->protocol ) {
|
||||||
|
return x->num_packets;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw ValueUnavailable("number_packets() not available in current context");
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::confirm_protocol() {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/confirm_protocol");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
if ( cookie->cache.confirmed )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( auto x = cookie->protocol ) {
|
||||||
|
auto tag = spicy_mgr->tagForProtocolAnalyzer(x->analyzer->GetAnalyzerTag());
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("confirming protocol %s", tag.AsString()));
|
||||||
|
cookie->cache.confirmed = true;
|
||||||
|
return x->analyzer->AnalyzerConfirmation(tag);
|
||||||
|
}
|
||||||
|
throw ValueUnavailable("no current connection available");
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::reject_protocol(const std::string& reason) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/reject_protocol");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
if ( auto x = cookie->protocol ) {
|
||||||
|
auto tag = spicy_mgr->tagForProtocolAnalyzer(x->analyzer->GetAnalyzerTag());
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt("rejecting protocol %s", tag.AsString()));
|
||||||
|
return x->analyzer->AnalyzerViolation("protocol rejected", nullptr, 0, tag);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw ValueUnavailable("no current connection available");
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::weird(const std::string& id, const std::string& addl) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/weird");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
if ( const auto x = cookie->protocol )
|
||||||
|
x->analyzer->Weird(id.c_str(), addl.data());
|
||||||
|
else if ( const auto x = cookie->file )
|
||||||
|
zeek::reporter->Weird(x->analyzer->GetFile(), id.c_str(), addl.data());
|
||||||
|
else if ( const auto x = cookie->packet ) {
|
||||||
|
x->analyzer->Weird(id.c_str(), x->packet, addl.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw ValueUnavailable("none of $conn, $file, or $packet available for weird reporting");
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::protocol_begin(const std::optional<std::string>& analyzer) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/protocol_begin");
|
||||||
|
|
||||||
|
if ( analyzer ) {
|
||||||
|
protocol_handle_get_or_create(*analyzer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instantiate a DPD analyzer.
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
auto c = cookie->protocol;
|
||||||
|
if ( ! c )
|
||||||
|
throw ValueUnavailable("no current connection available");
|
||||||
|
|
||||||
|
// Use a Zeek PIA stream analyzer performing DPD.
|
||||||
|
auto pia_tcp = std::make_unique<analyzer::pia::PIA_TCP>(c->analyzer->Conn());
|
||||||
|
|
||||||
|
// Forward empty payload to trigger lifecycle management in this analyzer tree.
|
||||||
|
c->analyzer->ForwardStream(0, reinterpret_cast<const u_char*>(c->analyzer), true);
|
||||||
|
c->analyzer->ForwardStream(0, reinterpret_cast<const u_char*>(c->analyzer), false);
|
||||||
|
|
||||||
|
// Direct child of this type already exists. We ignore this silently
|
||||||
|
// because that makes usage nicer if either side of the connection
|
||||||
|
// might end up creating the analyzer; this way the user doesn't
|
||||||
|
// need to track what the other side already did.
|
||||||
|
//
|
||||||
|
// We inspect the children directly to work around zeek/zeek#2899.
|
||||||
|
const auto& children = c->analyzer->GetChildren();
|
||||||
|
if ( auto it = std::find_if(children.begin(), children.end(),
|
||||||
|
[&](const auto& it) {
|
||||||
|
return ! it->Removing() && ! it->IsFinished() &&
|
||||||
|
it->GetAnalyzerTag() == pia_tcp->GetAnalyzerTag();
|
||||||
|
});
|
||||||
|
it != children.end() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto child = pia_tcp.release();
|
||||||
|
c->analyzer->AddChildAnalyzer(child);
|
||||||
|
|
||||||
|
child->FirstPacket(true, nullptr);
|
||||||
|
child->FirstPacket(false, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
rt::ProtocolHandle rt::protocol_handle_get_or_create(const std::string& analyzer) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/protocol_handle_get_or_create");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
auto c = cookie->protocol;
|
||||||
|
if ( ! c )
|
||||||
|
throw ValueUnavailable("no current connection available");
|
||||||
|
|
||||||
|
// Forward empty payload to trigger lifecycle management in this analyzer tree.
|
||||||
|
c->analyzer->ForwardStream(0, reinterpret_cast<const u_char*>(c->analyzer), true);
|
||||||
|
c->analyzer->ForwardStream(0, reinterpret_cast<const u_char*>(c->analyzer), false);
|
||||||
|
|
||||||
|
// If the child already exists, do not add it again so this function is idempotent.
|
||||||
|
//
|
||||||
|
// We inspect the children directly to work around zeek/zeek#2899.
|
||||||
|
const auto& children = c->analyzer->GetChildren();
|
||||||
|
if ( auto it = std::find_if(children.begin(), children.end(),
|
||||||
|
[&](const auto& it) {
|
||||||
|
return ! it->Removing() && ! it->IsFinished() && it->GetAnalyzerName() == analyzer;
|
||||||
|
});
|
||||||
|
it != children.end() )
|
||||||
|
return rt::ProtocolHandle((*it)->GetID());
|
||||||
|
|
||||||
|
auto child = analyzer_mgr->InstantiateAnalyzer(analyzer.c_str(), c->analyzer->Conn());
|
||||||
|
if ( ! child )
|
||||||
|
throw ZeekError(::hilti::rt::fmt("unknown analyzer '%s' requested", analyzer));
|
||||||
|
|
||||||
|
// If we had no such child before but cannot add it the analyzer was prevented.
|
||||||
|
//
|
||||||
|
// NOTE: We make this a hard error since returning e.g., an empty optional
|
||||||
|
// here would make it easy to incorrectly use the return value with e.g.,
|
||||||
|
// `protocol_data_in` or `protocol_gap`.
|
||||||
|
if ( ! c->analyzer->AddChildAnalyzer(child) )
|
||||||
|
throw ZeekError(::hilti::rt::fmt("creation of child analyzer %s was prevented", analyzer));
|
||||||
|
|
||||||
|
if ( c->analyzer->Conn()->ConnTransport() != TRANSPORT_TCP ) {
|
||||||
|
// Some TCP application analyzer may expect to have access to a TCP
|
||||||
|
// analyzer. To make that work, we'll create a fake TCP analyzer,
|
||||||
|
// just so that they have something to access. It won't
|
||||||
|
// semantically have any "TCP" to analyze obviously.
|
||||||
|
c->fake_tcp = std::make_shared<packet_analysis::TCP::TCPSessionAdapter>(c->analyzer->Conn());
|
||||||
|
static_cast<analyzer::Analyzer*>(c->fake_tcp.get())
|
||||||
|
->Done(); // will never see packets; cast to get around protected inheritance
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* child_as_tcp = dynamic_cast<analyzer::tcp::TCP_ApplicationAnalyzer*>(child);
|
||||||
|
if ( ! child_as_tcp )
|
||||||
|
throw ZeekError(
|
||||||
|
::hilti::rt::fmt("could not add analyzer '%s' to connection; not a TCP-based analyzer", analyzer));
|
||||||
|
|
||||||
|
if ( c->fake_tcp )
|
||||||
|
child_as_tcp->SetTCP(c->fake_tcp.get());
|
||||||
|
|
||||||
|
return rt::ProtocolHandle(child->GetID());
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::protocol_data_in(const hilti::rt::Bool& is_orig, const hilti::rt::Bytes& data,
|
||||||
|
const std::optional<rt::ProtocolHandle>& h) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/protocol_data_in");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
auto c = cookie->protocol;
|
||||||
|
if ( ! c )
|
||||||
|
throw ValueUnavailable("no current connection available");
|
||||||
|
|
||||||
|
auto len = data.size();
|
||||||
|
auto* data_ = reinterpret_cast<const u_char*>(data.data());
|
||||||
|
|
||||||
|
if ( h ) {
|
||||||
|
if ( auto* output_handler = c->analyzer->GetOutputHandler() )
|
||||||
|
output_handler->DeliverStream(len, data_, is_orig);
|
||||||
|
|
||||||
|
auto* child = c->analyzer->FindChild(h->id());
|
||||||
|
if ( ! child )
|
||||||
|
throw ValueUnavailable(hilti::rt::fmt("unknown child analyzer %s", *h));
|
||||||
|
|
||||||
|
if ( child->IsFinished() || child->Removing() )
|
||||||
|
throw ValueUnavailable(hilti::rt::fmt("child analyzer %s no longer exist", *h));
|
||||||
|
|
||||||
|
child->NextStream(len, data_, is_orig);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
c->analyzer->ForwardStream(len, data_, is_orig);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::protocol_gap(const hilti::rt::Bool& is_orig, const hilti::rt::integer::safe<uint64_t>& offset,
|
||||||
|
const hilti::rt::integer::safe<uint64_t>& len, const std::optional<rt::ProtocolHandle>& h) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/protocol_gap");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
auto c = cookie->protocol;
|
||||||
|
if ( ! c )
|
||||||
|
throw ValueUnavailable("no current connection available");
|
||||||
|
|
||||||
|
if ( h ) {
|
||||||
|
if ( auto* output_handler = c->analyzer->GetOutputHandler() )
|
||||||
|
output_handler->Undelivered(offset, len, is_orig);
|
||||||
|
|
||||||
|
auto* child = c->analyzer->FindChild(h->id());
|
||||||
|
if ( ! child )
|
||||||
|
throw ValueUnavailable(hilti::rt::fmt("unknown child analyzer %s", *h));
|
||||||
|
|
||||||
|
if ( child->IsFinished() || child->Removing() )
|
||||||
|
throw ValueUnavailable(hilti::rt::fmt("child analyzer %s no longer exist", *h));
|
||||||
|
|
||||||
|
child->NextUndelivered(offset, len, is_orig);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
c->analyzer->ForwardUndelivered(offset, len, is_orig);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::protocol_end() {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/protocol_end");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
auto c = cookie->protocol;
|
||||||
|
if ( ! c )
|
||||||
|
throw ValueUnavailable("no current connection available");
|
||||||
|
|
||||||
|
for ( const auto& i : c->analyzer->GetChildren() )
|
||||||
|
c->analyzer->RemoveChildAnalyzer(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::protocol_handle_close(const ProtocolHandle& handle) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/protocol_handle_close");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
auto c = cookie->protocol;
|
||||||
|
if ( ! c )
|
||||||
|
throw ValueUnavailable("no current connection available");
|
||||||
|
|
||||||
|
auto child = c->analyzer->FindChild(handle.id());
|
||||||
|
if ( ! child )
|
||||||
|
throw ValueUnavailable(hilti::rt::fmt("unknown child analyzer %s", handle));
|
||||||
|
|
||||||
|
if ( child->IsFinished() || child->Removing() )
|
||||||
|
throw ValueUnavailable(hilti::rt::fmt("child analyzer %s no longer exist", handle));
|
||||||
|
|
||||||
|
child->NextEndOfData(true);
|
||||||
|
child->NextEndOfData(false);
|
||||||
|
|
||||||
|
c->analyzer->RemoveChildAnalyzer(handle.id());
|
||||||
|
}
|
||||||
|
|
||||||
|
rt::cookie::FileState* rt::cookie::FileStateStack::push() {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/file-stack-push");
|
||||||
|
auto fid = file_mgr->HashHandle(hilti::rt::fmt("%s.%d", _analyzer_id, ++_id_counter));
|
||||||
|
_stack.emplace_back(fid);
|
||||||
|
return &_stack.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
const rt::cookie::FileState* rt::cookie::FileStateStack::find(const std::string& fid) const {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/file-stack-find");
|
||||||
|
|
||||||
|
// Reverse search as the default state would be on top of the stack.
|
||||||
|
for ( auto i = _stack.rbegin(); i != _stack.rend(); i++ ) {
|
||||||
|
if ( i->fid == fid )
|
||||||
|
return &*i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::cookie::FileStateStack::remove(const std::string& fid) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/file-stack-remove");
|
||||||
|
|
||||||
|
// Reverse search as the default state would be on top of the stack.
|
||||||
|
for ( auto i = _stack.rbegin(); i != _stack.rend(); i++ ) {
|
||||||
|
if ( i->fid == fid ) {
|
||||||
|
_stack.erase((i + 1).base()); // https://stackoverflow.com/a/1830240
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _data_in(const char* data, uint64_t len, std::optional<uint64_t> offset,
|
||||||
|
const std::optional<std::string>& fid) {
|
||||||
|
auto cookie = static_cast<rt::Cookie*>(hilti::rt::context::cookie());
|
||||||
|
auto* fstate = _file_state(cookie, fid);
|
||||||
|
auto data_ = reinterpret_cast<const unsigned char*>(data);
|
||||||
|
auto mime_type = (fstate->mime_type ? *fstate->mime_type : std::string());
|
||||||
|
|
||||||
|
if ( auto c = cookie->protocol ) {
|
||||||
|
auto tag = spicy_mgr->tagForProtocolAnalyzer(c->analyzer->GetAnalyzerTag());
|
||||||
|
|
||||||
|
if ( offset )
|
||||||
|
file_mgr->DataIn(data_, len, *offset, tag, c->analyzer->Conn(), c->is_orig, fstate->fid, mime_type);
|
||||||
|
else
|
||||||
|
file_mgr->DataIn(data_, len, tag, c->analyzer->Conn(), c->is_orig, fstate->fid, mime_type);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( offset )
|
||||||
|
file_mgr->DataIn(data_, len, *offset, Tag(), nullptr, false, fstate->fid, mime_type);
|
||||||
|
else
|
||||||
|
file_mgr->DataIn(data_, len, Tag(), nullptr, false, fstate->fid, mime_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::terminate_session() {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/terminate_session");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
if ( auto c = cookie->protocol ) {
|
||||||
|
assert(session_mgr);
|
||||||
|
session_mgr->Remove(c->analyzer->Conn());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw spicy::rt::ValueUnavailable("terminate_session() not available in the current context");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string rt::fuid() {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/fuid");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
if ( auto f = cookie->file ) {
|
||||||
|
if ( auto file = f->analyzer->GetFile() )
|
||||||
|
return file->GetID();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw ValueUnavailable("fuid() not available in current context");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string rt::file_begin(const std::optional<std::string>& mime_type) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/file_begin");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
auto* fstate = _file_state_stack(cookie)->push();
|
||||||
|
fstate->mime_type = mime_type;
|
||||||
|
|
||||||
|
// Feed an empty chunk into the analysis to force creating the file state inside Zeek.
|
||||||
|
_data_in("", 0, {}, {});
|
||||||
|
|
||||||
|
auto file = file_mgr->LookupFile(fstate->fid);
|
||||||
|
assert(file); // passing in empty data ensures that this is now available
|
||||||
|
|
||||||
|
if ( auto f = cookie->file ) {
|
||||||
|
// We need to initialize some fa_info fields ourselves that would
|
||||||
|
// normally be inferred from the connection.
|
||||||
|
|
||||||
|
// Set the source to the current file analyzer.
|
||||||
|
file->SetSource(file_mgr->GetComponentName(f->analyzer->Tag()));
|
||||||
|
|
||||||
|
// There are some fields inside the new fa_info record that we want to
|
||||||
|
// set, but don't have a Zeek API for. Hence, we need to play some
|
||||||
|
// tricks: we can get to the fa_info value, but read-only; const_cast
|
||||||
|
// comes to our rescue. And then we just write directly into the
|
||||||
|
// record fields.
|
||||||
|
auto rval = file->ToVal()->AsRecordVal();
|
||||||
|
auto current = f->analyzer->GetFile()->ToVal()->AsRecordVal();
|
||||||
|
rval->Assign(id::fa_file->FieldOffset("parent_id"),
|
||||||
|
current->GetField("id")); // set to parent
|
||||||
|
rval->Assign(id::fa_file->FieldOffset("conns"),
|
||||||
|
current->GetField("conns")); // copy from parent
|
||||||
|
rval->Assign(id::fa_file->FieldOffset("is_orig"),
|
||||||
|
current->GetField("is_orig")); // copy from parent
|
||||||
|
}
|
||||||
|
|
||||||
|
// Double check everybody agrees on the file ID.
|
||||||
|
assert(fstate->fid == file->GetID());
|
||||||
|
return fstate->fid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::file_set_size(const hilti::rt::integer::safe<uint64_t>& size, const std::optional<std::string>& fid) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/file_set_size");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
auto* fstate = _file_state(cookie, fid);
|
||||||
|
|
||||||
|
if ( auto c = cookie->protocol ) {
|
||||||
|
auto tag = spicy_mgr->tagForProtocolAnalyzer(c->analyzer->GetAnalyzerTag());
|
||||||
|
file_mgr->SetSize(size, tag, c->analyzer->Conn(), c->is_orig, fstate->fid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
file_mgr->SetSize(size, Tag(), nullptr, false, fstate->fid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::file_data_in(const hilti::rt::Bytes& data, const std::optional<std::string>& fid) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/file_data_in");
|
||||||
|
_data_in(data.data(), data.size(), {}, fid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::file_data_in_at_offset(const hilti::rt::Bytes& data, const hilti::rt::integer::safe<uint64_t>& offset,
|
||||||
|
const std::optional<std::string>& fid) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/file_data_in_at_offset");
|
||||||
|
_data_in(data.data(), data.size(), offset, fid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::file_gap(const hilti::rt::integer::safe<uint64_t>& offset, const hilti::rt::integer::safe<uint64_t>& len,
|
||||||
|
const std::optional<std::string>& fid) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/file_gap");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
auto* fstate = _file_state(cookie, fid);
|
||||||
|
|
||||||
|
if ( auto c = cookie->protocol ) {
|
||||||
|
auto tag = spicy_mgr->tagForProtocolAnalyzer(c->analyzer->GetAnalyzerTag());
|
||||||
|
file_mgr->Gap(offset, len, tag, c->analyzer->Conn(), c->is_orig, fstate->fid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
file_mgr->Gap(offset, len, Tag(), nullptr, false, fstate->fid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::file_end(const std::optional<std::string>& fid) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/file_end");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
auto* fstate = _file_state(cookie, fid);
|
||||||
|
|
||||||
|
file_mgr->EndOfFile(fstate->fid);
|
||||||
|
_file_state_stack(cookie)->remove(fstate->fid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt::forward_packet(const hilti::rt::integer::safe<uint32_t>& identifier) {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/forward_packet");
|
||||||
|
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
|
||||||
|
assert(cookie);
|
||||||
|
|
||||||
|
if ( auto c = cookie->packet )
|
||||||
|
c->next_analyzer = identifier;
|
||||||
|
else
|
||||||
|
throw ValueUnavailable("no current packet analyzer available");
|
||||||
|
}
|
||||||
|
|
||||||
|
hilti::rt::Time rt::network_time() {
|
||||||
|
auto _ = hilti::rt::profiler::start("zeek/rt/network_time");
|
||||||
|
return hilti::rt::Time(run_state::network_time, hilti::rt::Time::SecondTag());
|
||||||
|
}
|
890
src/spicy/runtime-support.h
Normal file
890
src/spicy/runtime-support.h
Normal file
|
@ -0,0 +1,890 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functions and types available to generated Spicy/Zeek glue code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <ostream>
|
||||||
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <hilti/rt/deferred-expression.h>
|
||||||
|
#include <hilti/rt/exception.h>
|
||||||
|
#include <hilti/rt/extension-points.h>
|
||||||
|
#include <hilti/rt/fmt.h>
|
||||||
|
#include <hilti/rt/types/all.h>
|
||||||
|
|
||||||
|
#include "zeek/Desc.h"
|
||||||
|
#include "zeek/spicy/cookie.h"
|
||||||
|
#include "zeek/spicy/manager.h"
|
||||||
|
|
||||||
|
namespace zeek::spicy::rt {
|
||||||
|
|
||||||
|
// Adapt to rename of exception.
|
||||||
|
#if SPICY_VERSION_NUMBER >= 10700
|
||||||
|
using UsageError = ::hilti::rt::UsageError;
|
||||||
|
#else
|
||||||
|
using UsageError = ::hilti::rt::UserException;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown by event generation code if the value of an `$...`
|
||||||
|
* expression isn't available.
|
||||||
|
*/
|
||||||
|
class ValueUnavailable : public UsageError {
|
||||||
|
public:
|
||||||
|
using UsageError::UsageError;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown by event generation code if the values can't be converted
|
||||||
|
* to Zeek.
|
||||||
|
*/
|
||||||
|
class InvalidValue : public UsageError {
|
||||||
|
public:
|
||||||
|
using UsageError::UsageError;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown by event generation code if functionality is used
|
||||||
|
* that the current build does not support.
|
||||||
|
*/
|
||||||
|
class Unsupported : public UsageError {
|
||||||
|
public:
|
||||||
|
using UsageError::UsageError;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown by event generation code if there's a type mismatch
|
||||||
|
* between the Spicy-side value and what the Zeek event expects.
|
||||||
|
*/
|
||||||
|
class TypeMismatch : public UsageError {
|
||||||
|
public:
|
||||||
|
TypeMismatch(const std::string_view& msg, std::string_view location = "")
|
||||||
|
: UsageError(hilti::rt::fmt("Event parameter mismatch, %s", msg)) {}
|
||||||
|
TypeMismatch(const std::string_view& have, TypePtr want, std::string_view location = "")
|
||||||
|
: TypeMismatch(_fmt(have, want)) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string _fmt(const std::string_view& have, TypePtr want) {
|
||||||
|
ODesc d;
|
||||||
|
want->Describe(&d);
|
||||||
|
return hilti::rt::fmt("cannot convert Spicy value of type '%s' to Zeek value of type '%s'", have,
|
||||||
|
d.Description());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown by the runtime library when Zeek has flagged a problem.
|
||||||
|
*/
|
||||||
|
class ZeekError : public UsageError {
|
||||||
|
public:
|
||||||
|
using UsageError::UsageError;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a Spicy protocol analyzer with its EVT meta information with the
|
||||||
|
* plugin's runtime.
|
||||||
|
*/
|
||||||
|
void register_protocol_analyzer(const std::string& name, hilti::rt::Protocol proto,
|
||||||
|
const hilti::rt::Vector<hilti::rt::Port>& ports, const std::string& parser_orig,
|
||||||
|
const std::string& parser_resp, const std::string& replaces,
|
||||||
|
const std::string& linker_scope);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a Spicy file analyzer with its EVT meta information with the
|
||||||
|
* plugin's runtime.
|
||||||
|
*/
|
||||||
|
void register_file_analyzer(const std::string& name, const hilti::rt::Vector<std::string>& mime_types,
|
||||||
|
const std::string& parser, const std::string& replaces, const std::string& linker_scope);
|
||||||
|
|
||||||
|
/** Reports a Zeek-side "weird". */
|
||||||
|
void weird(const std::string& id, const std::string& addl);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a Spicy packet analyzer with its EVT meta information with the
|
||||||
|
* plugin's runtime.
|
||||||
|
*/
|
||||||
|
void register_packet_analyzer(const std::string& name, const std::string& parser, const std::string& replaces,
|
||||||
|
const std::string& linker_scope);
|
||||||
|
|
||||||
|
/** Registers a Spicy-generated type to make it available inside Zeek. */
|
||||||
|
void register_type(const std::string& ns, const std::string& id, const TypePtr& type);
|
||||||
|
|
||||||
|
/** Identifies a Zeek-side type. */
|
||||||
|
enum class ZeekTypeTag : uint64_t {
|
||||||
|
Addr,
|
||||||
|
Any,
|
||||||
|
Bool,
|
||||||
|
Count,
|
||||||
|
Double,
|
||||||
|
Enum,
|
||||||
|
Error,
|
||||||
|
File,
|
||||||
|
Func,
|
||||||
|
Int,
|
||||||
|
Interval,
|
||||||
|
List,
|
||||||
|
Opaque,
|
||||||
|
Pattern,
|
||||||
|
Port,
|
||||||
|
Record,
|
||||||
|
String,
|
||||||
|
Subnet,
|
||||||
|
Table,
|
||||||
|
Time,
|
||||||
|
Type,
|
||||||
|
Vector,
|
||||||
|
Void,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern TypePtr create_base_type(ZeekTypeTag tag);
|
||||||
|
|
||||||
|
extern TypePtr create_enum_type(
|
||||||
|
const std::string& ns, const std::string& id,
|
||||||
|
const hilti::rt::Vector<std::tuple<std::string, hilti::rt::integer::safe<int64_t>>>& labels);
|
||||||
|
|
||||||
|
using RecordField = std::tuple<std::string, TypePtr, hilti::rt::Bool>; // (ID, type, optional)
|
||||||
|
extern TypePtr create_record_type(const std::string& ns, const std::string& id,
|
||||||
|
const hilti::rt::Vector<RecordField>& fields);
|
||||||
|
|
||||||
|
extern TypePtr create_table_type(TypePtr key, std::optional<TypePtr> value);
|
||||||
|
extern TypePtr create_vector_type(const TypePtr& elem);
|
||||||
|
|
||||||
|
/** Returns true if an event has at least one handler defined. */
|
||||||
|
inline hilti::rt::Bool have_handler(const EventHandlerPtr& handler) { return static_cast<bool>(handler); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new event handler under the given name.
|
||||||
|
*/
|
||||||
|
void install_handler(const std::string& name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks up an event handler by name. The handler must have been installed
|
||||||
|
* before through `install_handler()`.
|
||||||
|
*/
|
||||||
|
EventHandlerPtr internal_handler(const std::string& name);
|
||||||
|
|
||||||
|
/** Raises a Zeek event, given the handler and arguments. */
|
||||||
|
void raise_event(const EventHandlerPtr& handler, const hilti::rt::Vector<ValPtr>& args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Zeek type of an event's i'th argument. The result's ref count
|
||||||
|
* is not increased.
|
||||||
|
*/
|
||||||
|
TypePtr event_arg_type(const EventHandlerPtr& handler, const hilti::rt::integer::safe<uint64_t>& idx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the connection ID for the currently processed Zeek connection.
|
||||||
|
* Assumes that the HILTI context's cookie value has been set accordingly.
|
||||||
|
*
|
||||||
|
* @return Zeek value of record type
|
||||||
|
*/
|
||||||
|
ValPtr& current_conn();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the direction of the currently processed Zeek connection.
|
||||||
|
* Assumes that the HILTI context's cookie value has been set accordingly.
|
||||||
|
*
|
||||||
|
* @return Zeek value of boolean type
|
||||||
|
*/
|
||||||
|
ValPtr& current_is_orig();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a string through the Spicy plugin's debug output.
|
||||||
|
*
|
||||||
|
* @param cookie refers to the connection or file that the message is associated with
|
||||||
|
* @param msg message to log
|
||||||
|
*/
|
||||||
|
void debug(const Cookie& cookie, const std::string& msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a string through the Spicy plugin's debug output. This version logs
|
||||||
|
* the information the currently processed connection or file.
|
||||||
|
*
|
||||||
|
* @param msg message to log
|
||||||
|
*/
|
||||||
|
void debug(const std::string& msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the fa_file instance for the currently processed Zeek file.
|
||||||
|
* Assumes that the HILTI context's cookie value has been set accordingly.
|
||||||
|
*
|
||||||
|
* @return Zeek value of record type
|
||||||
|
*/
|
||||||
|
ValPtr current_file();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a `raw_pkt_hdr` instance for the currently processed Zeek packet.
|
||||||
|
* Assumes that the HILTI context's cookie value has been set accordingly.
|
||||||
|
*
|
||||||
|
* @return Zeek value of record type
|
||||||
|
*/
|
||||||
|
ValPtr current_packet();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if we're currently parsing the originator side of a
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
hilti::rt::Bool is_orig();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current connection's UID.
|
||||||
|
*/
|
||||||
|
std::string uid();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current connection's ID tuple.
|
||||||
|
*/
|
||||||
|
std::tuple<hilti::rt::Address, hilti::rt::Port, hilti::rt::Address, hilti::rt::Port> conn_id();
|
||||||
|
|
||||||
|
/** Instructs to Zeek to flip the directionality of the current connecction. */
|
||||||
|
void flip_roles();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of packets seen so far on the current side of the
|
||||||
|
* current connection.
|
||||||
|
*/
|
||||||
|
hilti::rt::integer::safe<uint64_t> number_packets();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers a DPD protocol confirmation for the currently processed
|
||||||
|
* connection. Assumes that the HILTI context's cookie value has been set
|
||||||
|
* accordingly.
|
||||||
|
*/
|
||||||
|
void confirm_protocol();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers a DPD protocol violation for the currently processed connection.
|
||||||
|
* Assumes that the HILTI context's cookie value has been set accordingly.
|
||||||
|
*
|
||||||
|
* @param reason short description of what went wrong
|
||||||
|
*/
|
||||||
|
void reject_protocol(const std::string& reason);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opaque handle to a protocol analyzer.
|
||||||
|
*/
|
||||||
|
class ProtocolHandle {
|
||||||
|
public:
|
||||||
|
ProtocolHandle() {}
|
||||||
|
explicit ProtocolHandle(uint64_t id) : _id(id) {}
|
||||||
|
|
||||||
|
uint64_t id() const {
|
||||||
|
if ( ! _id )
|
||||||
|
throw ValueUnavailable("uninitialized protocol handle");
|
||||||
|
|
||||||
|
return *_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::string to_string(const ProtocolHandle& h, ::hilti::rt::detail::adl::tag) {
|
||||||
|
if ( ! h._id )
|
||||||
|
return "(uninitialized protocol handle)";
|
||||||
|
|
||||||
|
return std::to_string(*h._id);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::ostream& operator<<(std::ostream& stream, const ProtocolHandle& h) {
|
||||||
|
return stream << ::hilti::rt::to_string(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::optional<uint64_t> _id;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a Zeek-side child protocol analyzer to the current connection.
|
||||||
|
*
|
||||||
|
* @param analyzer if given, the Zeek-side name of the analyzer to instantiate;
|
||||||
|
* if not given, DPD will be used
|
||||||
|
*/
|
||||||
|
void protocol_begin(const std::optional<std::string>& analyzer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a handle to a child analyzer of a given type. If a child of that type
|
||||||
|
* does not yet exist it will be created.
|
||||||
|
*
|
||||||
|
* @param analyzer the Zeek-side name of the analyzer to get (e.g., `HTTP`)
|
||||||
|
*
|
||||||
|
* @return a handle to the child analyzer. When done, the handle should be
|
||||||
|
* closed, either explicitly with protocol_handle_close or implicitly with
|
||||||
|
* protocol_end.
|
||||||
|
*/
|
||||||
|
ProtocolHandle protocol_handle_get_or_create(const std::string& analyzer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forwards data to all previously instantiated Zeek-side child protocol
|
||||||
|
* analyzers.
|
||||||
|
*
|
||||||
|
* @param is_orig true to feed data to originator side, false for responder
|
||||||
|
* @param data next chunk of stream data for child analyzer to process
|
||||||
|
* @param h optional handle to the child analyzer to stream data into
|
||||||
|
*/
|
||||||
|
void protocol_data_in(const hilti::rt::Bool& is_orig, const hilti::rt::Bytes& data,
|
||||||
|
const std::optional<ProtocolHandle>& h = {});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals a gap in input data to all previously instantiated Zeek-side child
|
||||||
|
* protocol analyzers.
|
||||||
|
*
|
||||||
|
* @param is_orig true to signal gap to originator side, false for responder
|
||||||
|
* @param offset of the gap inside the protocol stream
|
||||||
|
* @param length of the gap
|
||||||
|
* @param h optional handle to the child analyzer to signal a gap to
|
||||||
|
*/
|
||||||
|
void protocol_gap(const hilti::rt::Bool& is_orig, const hilti::rt::integer::safe<uint64_t>& offset,
|
||||||
|
const hilti::rt::integer::safe<uint64_t>& len, const std::optional<ProtocolHandle>& h = {});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals EOD to all previously instantiated Zeek-side child protocol
|
||||||
|
* analyzers and removes them.
|
||||||
|
*/
|
||||||
|
void protocol_end();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes a protocol handle.
|
||||||
|
*
|
||||||
|
* @param handle handle of the protocol analyzer to close.
|
||||||
|
*/
|
||||||
|
void protocol_handle_close(const ProtocolHandle& handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals the beginning of a file to Zeek's file analysis, associating it
|
||||||
|
* with the current connection.
|
||||||
|
*
|
||||||
|
* param mime_type optional mime type passed to Zeek
|
||||||
|
* @returns Zeek-side file ID of the new file
|
||||||
|
*/
|
||||||
|
std::string file_begin(const std::optional<std::string>& mime_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current file's FUID.
|
||||||
|
*/
|
||||||
|
std::string fuid();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Terminates the currently active Zeek-side session, flushing all state. Any
|
||||||
|
* subsequent activity will start a new session from scratch.
|
||||||
|
*/
|
||||||
|
void terminate_session();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals the expected size of a file to Zeek's file analysis.
|
||||||
|
*
|
||||||
|
* @param size expected final size of the file
|
||||||
|
* @param fid ID of the file to operate on; if unset, the most recently begun file is used
|
||||||
|
*/
|
||||||
|
void file_set_size(const hilti::rt::integer::safe<uint64_t>& size, const std::optional<std::string>& fid = {});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Passes file content on to Zeek's file analysis.
|
||||||
|
*
|
||||||
|
* @param data next chunk of data
|
||||||
|
* @param fid ID of the file to operate on; if unset, the most recently begun file is used
|
||||||
|
*/
|
||||||
|
void file_data_in(const hilti::rt::Bytes& data, const std::optional<std::string>& fid = {});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Passes file content at a specific offset on to Zeek's file analysis.
|
||||||
|
*
|
||||||
|
* @param data next chunk of data
|
||||||
|
* @param offset file offset of the data geing passed in
|
||||||
|
* @param fid ID of the file to operate on; if unset, the most recently begun file is used
|
||||||
|
*/
|
||||||
|
void file_data_in_at_offset(const hilti::rt::Bytes& data, const hilti::rt::integer::safe<uint64_t>& offset,
|
||||||
|
const std::optional<std::string>& fid = {});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals a gap in a file to Zeek's file analysis.
|
||||||
|
*
|
||||||
|
* @param offset of the gap
|
||||||
|
* @param length of the gap
|
||||||
|
* @param fid ID of the file to operate on; if unset, the most recently begun file is used
|
||||||
|
*/
|
||||||
|
void file_gap(const hilti::rt::integer::safe<uint64_t>& offset, const hilti::rt::integer::safe<uint64_t>& len,
|
||||||
|
const std::optional<std::string>& fid = {});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals the end of a file to Zeek's file analysis.
|
||||||
|
*
|
||||||
|
* @param fid ID of the file to operate on; if unset, the most recently begun file is used
|
||||||
|
*/
|
||||||
|
void file_end(const std::optional<std::string>& fid = {});
|
||||||
|
|
||||||
|
/** Specifies the next-layer packet analyzer. */
|
||||||
|
void forward_packet(const hilti::rt::integer::safe<uint32_t>& identifier);
|
||||||
|
|
||||||
|
/** Gets the network time from Zeek. */
|
||||||
|
hilti::rt::Time network_time();
|
||||||
|
|
||||||
|
// Forward-declare to_val() functions.
|
||||||
|
template<typename T, typename std::enable_if_t<hilti::rt::is_tuple<T>::value>* = nullptr>
|
||||||
|
ValPtr to_val(const T& t, TypePtr target);
|
||||||
|
template<typename T, typename std::enable_if_t<std::is_base_of<::hilti::rt::trait::isStruct, T>::value>* = nullptr>
|
||||||
|
ValPtr to_val(const T& t, TypePtr target);
|
||||||
|
template<typename T, typename std::enable_if_t<std::is_enum<typename T::Value>::value>* = nullptr>
|
||||||
|
ValPtr to_val(const T& t, TypePtr target);
|
||||||
|
template<typename T, typename std::enable_if_t<std::is_enum<T>::value>* = nullptr>
|
||||||
|
ValPtr to_val(const T& t, TypePtr target);
|
||||||
|
template<typename K, typename V>
|
||||||
|
ValPtr to_val(const hilti::rt::Map<K, V>& s, TypePtr target);
|
||||||
|
template<typename T>
|
||||||
|
ValPtr to_val(const hilti::rt::Set<T>& s, TypePtr target);
|
||||||
|
template<typename T>
|
||||||
|
ValPtr to_val(const hilti::rt::Vector<T>& v, TypePtr target);
|
||||||
|
template<typename T>
|
||||||
|
ValPtr to_val(const std::optional<T>& t, TypePtr target);
|
||||||
|
template<typename T>
|
||||||
|
ValPtr to_val(const hilti::rt::DeferredExpression<T>& t, TypePtr target);
|
||||||
|
template<typename T>
|
||||||
|
ValPtr to_val(hilti::rt::integer::safe<T> i, TypePtr target);
|
||||||
|
template<typename T>
|
||||||
|
ValPtr to_val(const hilti::rt::ValueReference<T>& t, TypePtr target);
|
||||||
|
|
||||||
|
inline ValPtr to_val(const hilti::rt::Bool& b, TypePtr target);
|
||||||
|
inline ValPtr to_val(const hilti::rt::Address& d, TypePtr target);
|
||||||
|
inline ValPtr to_val(const hilti::rt::Bytes& b, TypePtr target);
|
||||||
|
inline ValPtr to_val(const hilti::rt::Interval& t, TypePtr target);
|
||||||
|
inline ValPtr to_val(const hilti::rt::Port& d, TypePtr target);
|
||||||
|
inline ValPtr to_val(const hilti::rt::Time& t, TypePtr target);
|
||||||
|
inline ValPtr to_val(const std::string& s, TypePtr target);
|
||||||
|
inline ValPtr to_val(double r, TypePtr target);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Spicy-side optional value to a Zeek value. This assumes the
|
||||||
|
* optional is set, and will throw an exception if not. The result is
|
||||||
|
* returned with ref count +1.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
inline ValPtr to_val(const std::optional<T>& t, TypePtr target) {
|
||||||
|
if ( t.has_value() )
|
||||||
|
return to_val(hilti::rt::optional::value(t), target);
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Spicy-side DeferredExpression<T> value to a Zeek value. Such
|
||||||
|
* result values are returned by the ``.?`` operator. If the result is not
|
||||||
|
* set, this will convert into nullptr (which the tuple-to-record to_val()
|
||||||
|
* picks up on).
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
inline ValPtr to_val(const hilti::rt::DeferredExpression<T>& t, TypePtr target) {
|
||||||
|
try {
|
||||||
|
return to_val(t(), target);
|
||||||
|
} catch ( const hilti::rt::AttributeNotSet& ) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Spicy-side string to a Zeek value. The result is returned with
|
||||||
|
* ref count +1.
|
||||||
|
*/
|
||||||
|
inline ValPtr to_val(const std::string& s, TypePtr target) {
|
||||||
|
if ( target->Tag() != TYPE_STRING )
|
||||||
|
throw TypeMismatch("string", target);
|
||||||
|
|
||||||
|
return make_intrusive<StringVal>(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Spicy-side bytes instance to a Zeek value. The result is returned with
|
||||||
|
* ref count +1.
|
||||||
|
*/
|
||||||
|
inline ValPtr to_val(const hilti::rt::Bytes& b, TypePtr target) {
|
||||||
|
if ( target->Tag() != TYPE_STRING )
|
||||||
|
throw TypeMismatch("string", target);
|
||||||
|
|
||||||
|
return make_intrusive<StringVal>(b.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Spicy-side integer to a Zeek value. The result is
|
||||||
|
* returned with ref count +1.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
inline ValPtr to_val(hilti::rt::integer::safe<T> i, TypePtr target) {
|
||||||
|
ValPtr v = nullptr;
|
||||||
|
if constexpr ( std::is_unsigned<T>::value ) {
|
||||||
|
if ( target->Tag() == TYPE_COUNT )
|
||||||
|
return val_mgr->Count(i);
|
||||||
|
|
||||||
|
if ( target->Tag() == TYPE_INT )
|
||||||
|
return val_mgr->Int(i);
|
||||||
|
|
||||||
|
throw TypeMismatch("uint64", target);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( target->Tag() == TYPE_INT )
|
||||||
|
return val_mgr->Int(i);
|
||||||
|
|
||||||
|
if ( target->Tag() == TYPE_COUNT ) {
|
||||||
|
if ( i >= 0 )
|
||||||
|
return val_mgr->Count(i);
|
||||||
|
else
|
||||||
|
throw TypeMismatch("negative int64", target);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw TypeMismatch("int64", target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
ValPtr to_val(const hilti::rt::ValueReference<T>& t, TypePtr target) {
|
||||||
|
if ( auto* x = t.get() )
|
||||||
|
return to_val(*x, target);
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Spicy-side signed bool to a Zeek value. The result is
|
||||||
|
* returned with ref count +1.
|
||||||
|
*/
|
||||||
|
inline ValPtr to_val(const hilti::rt::Bool& b, TypePtr target) {
|
||||||
|
if ( target->Tag() != TYPE_BOOL )
|
||||||
|
throw TypeMismatch("bool", target);
|
||||||
|
|
||||||
|
return val_mgr->Bool(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Spicy-side real to a Zeek value. The result is returned with
|
||||||
|
* ref count +1.
|
||||||
|
*/
|
||||||
|
inline ValPtr to_val(double r, TypePtr target) {
|
||||||
|
if ( target->Tag() != TYPE_DOUBLE )
|
||||||
|
throw TypeMismatch("double", target);
|
||||||
|
|
||||||
|
return make_intrusive<DoubleVal>(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Spicy-side address to a Zeek value. The result is returned with
|
||||||
|
* ref count +1.
|
||||||
|
*/
|
||||||
|
inline ValPtr to_val(const hilti::rt::Address& d, TypePtr target) {
|
||||||
|
if ( target->Tag() != TYPE_ADDR )
|
||||||
|
throw TypeMismatch("addr", target);
|
||||||
|
|
||||||
|
auto in_addr = d.asInAddr();
|
||||||
|
if ( auto v4 = std::get_if<struct in_addr>(&in_addr) )
|
||||||
|
return make_intrusive<AddrVal>(IPAddr(*v4));
|
||||||
|
else {
|
||||||
|
auto v6 = std::get<struct in6_addr>(in_addr);
|
||||||
|
return make_intrusive<AddrVal>(IPAddr(v6));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Spicy-side address to a Zeek value. The result is returned with
|
||||||
|
* ref count +1.
|
||||||
|
*/
|
||||||
|
inline ValPtr to_val(const hilti::rt::Port& p, TypePtr target) {
|
||||||
|
if ( target->Tag() != TYPE_PORT )
|
||||||
|
throw TypeMismatch("port", target);
|
||||||
|
|
||||||
|
#if SPICY_VERSION_NUMBER >= 10700
|
||||||
|
auto proto = p.protocol().value();
|
||||||
|
#else
|
||||||
|
auto proto = p.protocol();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch ( proto ) {
|
||||||
|
case hilti::rt::Protocol::TCP: return val_mgr->Port(p.port(), ::TransportProto::TRANSPORT_TCP);
|
||||||
|
|
||||||
|
case hilti::rt::Protocol::UDP: return val_mgr->Port(p.port(), ::TransportProto::TRANSPORT_UDP);
|
||||||
|
|
||||||
|
case hilti::rt::Protocol::ICMP: return val_mgr->Port(p.port(), ::TransportProto::TRANSPORT_ICMP);
|
||||||
|
|
||||||
|
default: throw InvalidValue("port value with undefined protocol");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Spicy-side time to a Zeek value. The result is returned with
|
||||||
|
* ref count +1.
|
||||||
|
*/
|
||||||
|
inline ValPtr to_val(const hilti::rt::Interval& i, TypePtr target) {
|
||||||
|
if ( target->Tag() != TYPE_INTERVAL )
|
||||||
|
throw TypeMismatch("interval", target);
|
||||||
|
|
||||||
|
return make_intrusive<IntervalVal>(i.seconds());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Spicy-side time to a Zeek value. The result is returned with
|
||||||
|
* ref count +1.
|
||||||
|
*/
|
||||||
|
inline ValPtr to_val(const hilti::rt::Time& t, TypePtr target) {
|
||||||
|
if ( target->Tag() != TYPE_TIME )
|
||||||
|
throw TypeMismatch("time", target);
|
||||||
|
|
||||||
|
return make_intrusive<TimeVal>(t.seconds());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Spicy-side vector to a Zeek value. The result is returned with
|
||||||
|
* ref count +1.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
inline ValPtr to_val(const hilti::rt::Vector<T>& v, TypePtr target) {
|
||||||
|
if ( target->Tag() != TYPE_VECTOR && target->Tag() != TYPE_LIST )
|
||||||
|
throw TypeMismatch("expected vector or list", target);
|
||||||
|
|
||||||
|
auto vt = cast_intrusive<VectorType>(target);
|
||||||
|
auto zv = make_intrusive<VectorVal>(vt);
|
||||||
|
for ( const auto& i : v )
|
||||||
|
zv->Assign(zv->Size(), to_val(i, vt->Yield()));
|
||||||
|
|
||||||
|
return zv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Spicy-side map to a Zeek value. The result is returned with
|
||||||
|
* ref count +1.
|
||||||
|
*/
|
||||||
|
template<typename K, typename V>
|
||||||
|
inline ValPtr to_val(const hilti::rt::Map<K, V>& m, TypePtr target) {
|
||||||
|
if constexpr ( hilti::rt::is_tuple<K>::value )
|
||||||
|
throw TypeMismatch("internal error: sets with tuples not yet supported in to_val()");
|
||||||
|
|
||||||
|
if ( target->Tag() != TYPE_TABLE )
|
||||||
|
throw TypeMismatch("map", target);
|
||||||
|
|
||||||
|
auto tt = cast_intrusive<TableType>(target);
|
||||||
|
if ( tt->IsSet() )
|
||||||
|
throw TypeMismatch("map", target);
|
||||||
|
|
||||||
|
if ( tt->GetIndexTypes().size() != 1 )
|
||||||
|
throw TypeMismatch("map with non-tuple elements", target);
|
||||||
|
|
||||||
|
auto zv = make_intrusive<TableVal>(tt);
|
||||||
|
|
||||||
|
for ( const auto& i : m ) {
|
||||||
|
auto k = to_val(i.first, tt->GetIndexTypes()[0]);
|
||||||
|
auto v = to_val(i.second, tt->Yield());
|
||||||
|
zv->Assign(std::move(k), std::move(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
return zv;
|
||||||
|
} // namespace spicy::rt
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Spicy-side set to a Zeek value. The result is returned with
|
||||||
|
* ref count +1.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
inline ValPtr to_val(const hilti::rt::Set<T>& s, TypePtr target) {
|
||||||
|
if ( target->Tag() != TYPE_TABLE )
|
||||||
|
throw TypeMismatch("set", target);
|
||||||
|
|
||||||
|
auto tt = cast_intrusive<TableType>(target);
|
||||||
|
if ( ! tt->IsSet() )
|
||||||
|
throw TypeMismatch("set", target);
|
||||||
|
|
||||||
|
auto zv = make_intrusive<TableVal>(tt);
|
||||||
|
|
||||||
|
for ( const auto& i : s ) {
|
||||||
|
if constexpr ( hilti::rt::is_tuple<T>::value )
|
||||||
|
throw TypeMismatch("internal error: sets with tuples not yet supported in to_val()");
|
||||||
|
else {
|
||||||
|
if ( tt->GetIndexTypes().size() != 1 )
|
||||||
|
throw TypeMismatch("set with non-tuple elements", target);
|
||||||
|
|
||||||
|
auto idx = to_val(i, tt->GetIndexTypes()[0]);
|
||||||
|
zv->Assign(std::move(idx), nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return zv;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
template<typename, template<typename...> typename>
|
||||||
|
struct is_instance_impl : std::false_type {};
|
||||||
|
|
||||||
|
template<template<typename...> typename U, typename... Ts>
|
||||||
|
struct is_instance_impl<U<Ts...>, U> : std::true_type {};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
template<typename T, template<typename...> typename U>
|
||||||
|
using is_instance = is_instance_impl<std::remove_cv_t<T>, U>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void set_record_field(RecordVal* rval, const IntrusivePtr<RecordType>& rtype, int idx, const T& x) {
|
||||||
|
using NoConversionNeeded = std::integral_constant<
|
||||||
|
bool, std::is_same_v<T, int8_t> || std::is_same_v<T, int16_t> || std::is_same_v<T, int32_t> ||
|
||||||
|
std::is_same_v<T, int64_t> || std::is_same_v<T, uint8_t> || std::is_same_v<T, uint16_t> ||
|
||||||
|
std::is_same_v<T, uint32_t> || std::is_same_v<T, uint64_t> || std::is_same_v<T, double> ||
|
||||||
|
std::is_same_v<T, std::string> || std::is_same_v<T, bool>>;
|
||||||
|
|
||||||
|
using IsSignedInteger = std::integral_constant<bool, std::is_same_v<T, hilti::rt::integer::safe<int8_t>> ||
|
||||||
|
std::is_same_v<T, hilti::rt::integer::safe<int16_t>> ||
|
||||||
|
std::is_same_v<T, hilti::rt::integer::safe<int32_t>> ||
|
||||||
|
std::is_same_v<T, hilti::rt::integer::safe<int64_t>>>;
|
||||||
|
|
||||||
|
using IsUnsignedInteger = std::integral_constant<bool, std::is_same_v<T, hilti::rt::integer::safe<uint8_t>> ||
|
||||||
|
std::is_same_v<T, hilti::rt::integer::safe<uint16_t>> ||
|
||||||
|
std::is_same_v<T, hilti::rt::integer::safe<uint32_t>> ||
|
||||||
|
std::is_same_v<T, hilti::rt::integer::safe<uint64_t>>>;
|
||||||
|
|
||||||
|
if constexpr ( NoConversionNeeded::value )
|
||||||
|
rval->Assign(idx, x);
|
||||||
|
else if constexpr ( IsSignedInteger::value )
|
||||||
|
#if ZEEK_VERSION_NUMBER >= 50200
|
||||||
|
rval->Assign(idx, static_cast<int64_t>(x.Ref()));
|
||||||
|
#else
|
||||||
|
rval->Assign(idx, static_cast<int>(x.Ref()));
|
||||||
|
#endif
|
||||||
|
else if constexpr ( IsUnsignedInteger::value )
|
||||||
|
rval->Assign(idx, static_cast<uint64_t>(x.Ref()));
|
||||||
|
else if constexpr ( std::is_same_v<T, hilti::rt::Bytes> )
|
||||||
|
rval->Assign(idx, x.str());
|
||||||
|
else if constexpr ( std::is_same_v<T, hilti::rt::Bool> )
|
||||||
|
rval->Assign(idx, static_cast<bool>(x));
|
||||||
|
else if constexpr ( std::is_same_v<T, std::string> )
|
||||||
|
rval->Assign(idx, x);
|
||||||
|
else if constexpr ( std::is_same_v<T, hilti::rt::Time> )
|
||||||
|
rval->AssignTime(idx, x.seconds());
|
||||||
|
else if constexpr ( std::is_same_v<T, hilti::rt::Interval> )
|
||||||
|
rval->AssignInterval(idx, x.seconds());
|
||||||
|
else if constexpr ( std::is_same_v<T, hilti::rt::Null> ) {
|
||||||
|
// "Null" turns into an unset optional record field.
|
||||||
|
}
|
||||||
|
else if constexpr ( is_instance<T, std::optional>::value ) {
|
||||||
|
if ( x.has_value() )
|
||||||
|
set_record_field(rval, rtype, idx, *x);
|
||||||
|
}
|
||||||
|
else if constexpr ( is_instance<T, hilti::rt::DeferredExpression>::value ) {
|
||||||
|
try {
|
||||||
|
set_record_field(rval, rtype, idx, x());
|
||||||
|
} catch ( const hilti::rt::AttributeNotSet& ) {
|
||||||
|
// leave unset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ValPtr v = nullptr;
|
||||||
|
|
||||||
|
// This may return a nullptr in cases where the field is to be left unset.
|
||||||
|
v = to_val(x, rtype->GetFieldType(idx));
|
||||||
|
|
||||||
|
if ( v )
|
||||||
|
rval->Assign(idx, v);
|
||||||
|
else {
|
||||||
|
// Field must be &optional or &default.
|
||||||
|
if ( auto attrs = rtype->FieldDecl(idx)->attrs;
|
||||||
|
! attrs || ! (attrs->Find(detail::ATTR_DEFAULT) || attrs->Find(detail::ATTR_OPTIONAL)) )
|
||||||
|
throw TypeMismatch(hilti::rt::fmt("missing initialization for field '%s'", rtype->FieldName(idx)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Spicy-side tuple to a Zeek record value. The result is returned
|
||||||
|
* with ref count +1.
|
||||||
|
*/
|
||||||
|
template<typename T, typename std::enable_if_t<hilti::rt::is_tuple<T>::value>*>
|
||||||
|
inline ValPtr to_val(const T& t, TypePtr target) {
|
||||||
|
if ( target->Tag() != TYPE_RECORD )
|
||||||
|
throw TypeMismatch("tuple", target);
|
||||||
|
|
||||||
|
auto rtype = cast_intrusive<RecordType>(target);
|
||||||
|
|
||||||
|
if ( std::tuple_size<T>::value != rtype->NumFields() )
|
||||||
|
throw TypeMismatch("tuple", target);
|
||||||
|
|
||||||
|
auto rval = make_intrusive<RecordVal>(rtype);
|
||||||
|
int idx = 0;
|
||||||
|
hilti::rt::tuple_for_each(t, [&](const auto& x) { set_record_field(rval.get(), rtype, idx++, x); });
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts Spicy-side struct to a Zeek record value. The result is returned
|
||||||
|
* with a ref count +1.
|
||||||
|
*/
|
||||||
|
template<typename T, typename std::enable_if_t<std::is_base_of<::hilti::rt::trait::isStruct, T>::value>*>
|
||||||
|
inline ValPtr to_val(const T& t, TypePtr target) {
|
||||||
|
if ( target->Tag() != TYPE_RECORD )
|
||||||
|
throw TypeMismatch("struct", target);
|
||||||
|
|
||||||
|
auto rtype = cast_intrusive<RecordType>(target);
|
||||||
|
|
||||||
|
auto rval = make_intrusive<RecordVal>(rtype);
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
auto num_fields = rtype->NumFields();
|
||||||
|
|
||||||
|
t.__visit([&](const auto& name, const auto& val) {
|
||||||
|
if ( idx >= num_fields )
|
||||||
|
throw TypeMismatch(hilti::rt::fmt("no matching record field for field '%s'", name));
|
||||||
|
|
||||||
|
auto field = rtype->GetFieldType(idx);
|
||||||
|
std::string field_name = rtype->FieldName(idx);
|
||||||
|
|
||||||
|
if ( field_name != name )
|
||||||
|
throw TypeMismatch(hilti::rt::fmt("mismatch in field name: expected '%s', found '%s'", name, field_name));
|
||||||
|
|
||||||
|
set_record_field(rval.get(), rtype, idx++, val);
|
||||||
|
});
|
||||||
|
|
||||||
|
// We already check above that all Spicy-side fields are mapped so we
|
||||||
|
// can only hit this if there are uninitialized Zeek-side fields left.
|
||||||
|
if ( idx != num_fields )
|
||||||
|
throw TypeMismatch(hilti::rt::fmt("missing initialization for field '%s'", rtype->FieldName(idx + 1)));
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Spicy-side enum to a Zeek record value. The result is returned
|
||||||
|
* with ref count +1.
|
||||||
|
*/
|
||||||
|
template<typename T, typename std::enable_if_t<std::is_enum<typename T::Value>::value>*>
|
||||||
|
inline ValPtr to_val(const T& t, TypePtr target) {
|
||||||
|
#if SPICY_VERSION_NUMBER >= 10700
|
||||||
|
auto proto = typename T::Value(t.value());
|
||||||
|
#else
|
||||||
|
auto proto = t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return to_val(proto, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a C++ Spicy-side enum to a Zeek record value. The result is returned
|
||||||
|
* with ref count +1. This specialization is provided for compatibility with <spicy-1.7.0.
|
||||||
|
*
|
||||||
|
* TODO(bbannier): remove this once we drop support for Spicy versions before 1.7.0.
|
||||||
|
*/
|
||||||
|
template<typename T, typename std::enable_if_t<std::is_enum<T>::value>*>
|
||||||
|
inline ValPtr to_val(const T& t, TypePtr target) {
|
||||||
|
if ( target->Tag() != TYPE_ENUM )
|
||||||
|
throw TypeMismatch("enum", target);
|
||||||
|
|
||||||
|
// We'll usually be getting an int64_t for T, but allow other signed ints
|
||||||
|
// as well.
|
||||||
|
static_assert(std::is_signed<std::underlying_type_t<T>>{});
|
||||||
|
auto it = static_cast<int64_t>(t);
|
||||||
|
|
||||||
|
// Zeek's enum can't be negative, so we swap in max_int for our Undef (-1).
|
||||||
|
if ( it == std::numeric_limits<int64_t>::max() )
|
||||||
|
// can't allow this ...
|
||||||
|
throw InvalidValue("enum values with value max_int not supported by Zeek integration");
|
||||||
|
|
||||||
|
zeek_int_t bt = (it >= 0 ? it : std::numeric_limits<::zeek_int_t>::max());
|
||||||
|
|
||||||
|
return target->AsEnumType()->GetEnumVal(bt);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace zeek::spicy::rt
|
62
src/spicy/spicy.bif
Normal file
62
src/spicy/spicy.bif
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
# See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
module Spicy;
|
||||||
|
|
||||||
|
%%{
|
||||||
|
#include "zeek/spicy/manager.h"
|
||||||
|
%%}
|
||||||
|
|
||||||
|
# Constant for testing if Spicy is available.
|
||||||
|
const available: bool;
|
||||||
|
|
||||||
|
# Show output of Spicy print statements.
|
||||||
|
const enable_print: bool;
|
||||||
|
|
||||||
|
# Record and display profiling information.
|
||||||
|
const enable_profiling: bool;
|
||||||
|
|
||||||
|
# abort() instead of throwing HILTI # exceptions.
|
||||||
|
const abort_on_exceptions: bool;
|
||||||
|
|
||||||
|
# Include backtraces when reporting unhandled exceptions.
|
||||||
|
const show_backtraces: bool;
|
||||||
|
|
||||||
|
# Maximum depth of recursive file analysis.
|
||||||
|
const max_file_depth: count;
|
||||||
|
|
||||||
|
event max_file_depth_exceeded%(f: fa_file, args: Files::AnalyzerArgs, limit: count%);
|
||||||
|
|
||||||
|
function Spicy::__toggle_analyzer%(tag: any, enable: bool%) : bool
|
||||||
|
%{
|
||||||
|
if ( tag->GetType()->Tag() != TYPE_ENUM ) {
|
||||||
|
zeek::reporter->Warning("Spicy::disable_analyzer() must receive an analyzer tag");
|
||||||
|
return val_mgr->Bool(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool result = spicy_mgr->toggleAnalyzer(tag->AsEnumVal(), enable);
|
||||||
|
if ( ! result )
|
||||||
|
zeek::reporter->Warning("could not toggle Spicy analyzer");
|
||||||
|
|
||||||
|
return val_mgr->Bool(result);
|
||||||
|
%}
|
||||||
|
|
||||||
|
type ResourceUsage: record;
|
||||||
|
|
||||||
|
function Spicy::__resource_usage%(%) : Spicy::ResourceUsage
|
||||||
|
%{
|
||||||
|
auto ru = hilti::rt::resource_usage();
|
||||||
|
|
||||||
|
auto r = zeek::make_intrusive<zeek::RecordVal>(BifType::Record::Spicy::ResourceUsage);
|
||||||
|
int n = 0;
|
||||||
|
r->Assign(n++, ru.user_time);
|
||||||
|
r->Assign(n++, ru.system_time);
|
||||||
|
r->Assign(n++, ru.memory_heap);
|
||||||
|
r->Assign(n++, ru.num_fibers);
|
||||||
|
r->Assign(n++, ru.max_fibers);
|
||||||
|
#if SPICY_VERSION_NUMBER >= 10800
|
||||||
|
r->Assign(n++, ru.max_fiber_stack_size);
|
||||||
|
#endif
|
||||||
|
r->Assign(n++, ru.cached_fibers);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
%}
|
10
src/spicy/spicyz/CMakeLists.txt
Normal file
10
src/spicy/spicyz/CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
configure_file(config.h.in config.h)
|
||||||
|
|
||||||
|
add_executable(spicyz driver.cc glue-compiler.cc main.cc)
|
||||||
|
target_compile_options(spicyz PRIVATE "-Wall")
|
||||||
|
target_include_directories(spicyz PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
target_link_libraries(spicyz PRIVATE hilti spicy)
|
||||||
|
|
||||||
|
install(TARGETS spicyz DESTINATION ${CMAKE_INSTALL_BINDIR})
|
67
src/spicy/spicyz/config.h.in
Normal file
67
src/spicy/spicyz/config.h.in
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "zeek/util-config.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <hilti/rt/filesystem.h>
|
||||||
|
|
||||||
|
namespace zeek::spicy::configuration {
|
||||||
|
|
||||||
|
using path = hilti::rt::filesystem::path;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// This mimics zeek-config to get the Zeek include directories.
|
||||||
|
static inline void add_path(std::string& old_path, const path& new_path) {
|
||||||
|
if ( new_path.empty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( ! old_path.empty() )
|
||||||
|
old_path += ":";
|
||||||
|
|
||||||
|
old_path += new_path.native();
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
inline const auto InstallBinDir() { return path("${CMAKE_INSTALL_PREFIX}") / "${CMAKE_INSTALL_BINDIR}"; }
|
||||||
|
|
||||||
|
inline const auto LibraryPath() {
|
||||||
|
path base;
|
||||||
|
|
||||||
|
if ( auto custom_base = getenv("ZEEK_SPICY_LIBRARY_PATH"); custom_base && *custom_base )
|
||||||
|
base = path(custom_base);
|
||||||
|
else
|
||||||
|
base = path("@ZEEK_SPICY_LIBRARY_PATH@");
|
||||||
|
|
||||||
|
return hilti::rt::filesystem::weakly_canonical(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const auto ModulePath() { return path("@ZEEK_SPICY_MODULE_PATH@"); }
|
||||||
|
inline const auto DataPath() { return path("@ZEEK_SPICY_DATA_PATH@"); }
|
||||||
|
|
||||||
|
inline const auto CxxZeekIncludesDirectories() {
|
||||||
|
std::string includes;
|
||||||
|
add_path(includes, path("${CMAKE_INSTALL_PREFIX}") / "${CMAKE_INSTALL_INCLUDEDIR}");
|
||||||
|
|
||||||
|
// When changing any of the following, also update "zeek-config.in".
|
||||||
|
add_path(includes, "${ZEEK_CONFIG_PCAP_INCLUDE_DIR}");
|
||||||
|
add_path(includes, "${ZEEK_CONFIG_ZLIB_INCLUDE_DIR}");
|
||||||
|
add_path(includes, "${ZEEK_CONFIG_OPENSSL_INCLUDE_DIR}");
|
||||||
|
add_path(includes, "${ZEEK_CONFIG_LibKrb5_INCLUDE_DIR}");
|
||||||
|
add_path(includes, "${ZEEK_CONFIG_GooglePerftools_INCLUDE_DIR}");
|
||||||
|
|
||||||
|
return includes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version of Spicy that we are compiling against.
|
||||||
|
#cmakedefine SPICY_VERSION_NUMBER ${SPICY_VERSION_NUMBER}
|
||||||
|
#cmakedefine ZEEK_VERSION_NUMBER ${ZEEK_VERSION_NUMBER}
|
||||||
|
|
||||||
|
inline const auto SpicyVersion = "${SPICY_VERSION}";
|
||||||
|
inline const auto ZeekVersion = "${VERSION}";
|
||||||
|
inline const auto InstallPrefix = path("${CMAKE_INSTALL_PREFIX}");
|
||||||
|
|
||||||
|
} // namespace zeek::spicy::configuration
|
301
src/spicy/spicyz/driver.cc
Normal file
301
src/spicy/spicyz/driver.cc
Normal file
|
@ -0,0 +1,301 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#include "driver.h"
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <spicy/rt/libspicy.h>
|
||||||
|
|
||||||
|
#include <hilti/ast/declarations/type.h>
|
||||||
|
#include <hilti/compiler/init.h>
|
||||||
|
|
||||||
|
#include <spicy/ast/detail/visitor.h>
|
||||||
|
#include <spicy/ast/types/unit.h>
|
||||||
|
#include <spicy/autogen/config.h>
|
||||||
|
#include <spicy/compiler/init.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "glue-compiler.h"
|
||||||
|
|
||||||
|
using namespace zeek::spicy;
|
||||||
|
using Driver = ::zeek::spicy::Driver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visitor to type information from a HILTI AST. This extracts user-visible
|
||||||
|
* types only, we skip any internal ones.
|
||||||
|
*/
|
||||||
|
struct VisitorTypes : public hilti::visitor::PreOrder<void, VisitorTypes> {
|
||||||
|
explicit VisitorTypes(Driver* driver, hilti::ID module, hilti::rt::filesystem::path path, bool is_resolved)
|
||||||
|
: driver(driver), module(std::move(module)), path(std::move(path)), is_resolved(is_resolved) {}
|
||||||
|
|
||||||
|
void operator()(const hilti::declaration::Type& t) {
|
||||||
|
assert(! t.type().typeID() || *t.type().typeID() == hilti::ID(module, t.id())); // ensure consistent IDs
|
||||||
|
|
||||||
|
if ( module == hilti::ID("hilti") || module == hilti::ID("spicy_rt") || module == hilti::ID("zeek_rt") )
|
||||||
|
return;
|
||||||
|
|
||||||
|
types.emplace_back(TypeInfo{
|
||||||
|
.id = hilti::ID(module, t.id()),
|
||||||
|
.type = t.type()._clone().as<hilti::Type>(),
|
||||||
|
.linkage = t.linkage(),
|
||||||
|
.is_resolved = is_resolved,
|
||||||
|
.module_id = module,
|
||||||
|
.module_path = path,
|
||||||
|
.location = t.meta().location(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Driver* driver;
|
||||||
|
hilti::ID module;
|
||||||
|
hilti::rt::filesystem::path path;
|
||||||
|
bool is_resolved;
|
||||||
|
std::vector<TypeInfo> types;
|
||||||
|
};
|
||||||
|
|
||||||
|
Driver::Driver(std::unique_ptr<GlueCompiler> glue, const char* argv0, hilti::rt::filesystem::path lib_path,
|
||||||
|
int zeek_version)
|
||||||
|
: ::spicy::Driver("<Spicy Plugin for Zeek>"), _glue(std::move(glue)) {
|
||||||
|
_glue->Init(this, zeek_version);
|
||||||
|
|
||||||
|
::spicy::Configuration::extendHiltiConfiguration();
|
||||||
|
auto options = hiltiOptions();
|
||||||
|
|
||||||
|
// Note that, different from Spicy's own SPICY_PATH, this extends the
|
||||||
|
// search path, it doesn't replace it.
|
||||||
|
if ( auto path = hilti::rt::getenv("ZEEK_SPICY_PATH") ) {
|
||||||
|
for ( const auto& dir : hilti::rt::split(*path, ":") ) {
|
||||||
|
if ( dir.size() )
|
||||||
|
options.library_paths.emplace_back(dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
lib_path = hilti::rt::filesystem::weakly_canonical(lib_path);
|
||||||
|
|
||||||
|
// We make our search paths relative to the plugin library, so that the
|
||||||
|
// plugin installation can move around.
|
||||||
|
options.library_paths.push_back(lib_path);
|
||||||
|
} catch ( const hilti::rt::filesystem::filesystem_error& e ) {
|
||||||
|
::hilti::logger().warning(
|
||||||
|
hilti::util::fmt("invalid plugin base directory %s: %s", lib_path.native(), e.what()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( const auto& i : hilti::util::split(configuration::CxxZeekIncludesDirectories(), ":") ) {
|
||||||
|
if ( i.size() )
|
||||||
|
options.cxx_include_paths.emplace_back(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
SPICY_DEBUG("Search paths:");
|
||||||
|
|
||||||
|
auto hilti_options = hiltiOptions();
|
||||||
|
for ( const auto& x : hilti_options.library_paths ) {
|
||||||
|
SPICY_DEBUG(hilti::rt::fmt(" %s", x.native()));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
setCompilerOptions(std::move(options));
|
||||||
|
|
||||||
|
auto& config = ::spicy::configuration();
|
||||||
|
config.preprocessor_constants["HAVE_ZEEK"] = 1;
|
||||||
|
config.preprocessor_constants["ZEEK_VERSION"] = zeek_version;
|
||||||
|
|
||||||
|
#if SPICY_VERSION_NUMBER >= 10500
|
||||||
|
::hilti::init();
|
||||||
|
::spicy::init();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Driver::~Driver() {}
|
||||||
|
|
||||||
|
hilti::Result<hilti::Nothing> Driver::loadFile(hilti::rt::filesystem::path file,
|
||||||
|
const hilti::rt::filesystem::path& relative_to) {
|
||||||
|
std::error_code ec;
|
||||||
|
if ( ! relative_to.empty() && file.is_relative() ) {
|
||||||
|
auto p = relative_to / file;
|
||||||
|
auto exists = hilti::rt::filesystem::exists(p, ec);
|
||||||
|
|
||||||
|
if ( ec )
|
||||||
|
return hilti::rt::result::Error(
|
||||||
|
hilti::util::fmt("error computing path of %s relative to %s: %s", file, relative_to, ec.message()));
|
||||||
|
|
||||||
|
if ( exists )
|
||||||
|
file = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto exists = hilti::rt::filesystem::exists(file, ec);
|
||||||
|
|
||||||
|
if ( ec )
|
||||||
|
return hilti::rt::result::Error(
|
||||||
|
hilti::util::fmt("cannot check whether file %s exists: %s", file, ec.message()));
|
||||||
|
|
||||||
|
if ( ! exists ) {
|
||||||
|
if ( auto path = hilti::util::findInPaths(file, hiltiOptions().library_paths) )
|
||||||
|
file = *path;
|
||||||
|
else
|
||||||
|
return hilti::result::Error(hilti::util::fmt("Spicy plugin cannot find file %s", file));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rpath = hilti::util::normalizePath(file);
|
||||||
|
auto ext = rpath.extension();
|
||||||
|
|
||||||
|
if ( ext == ".evt" ) {
|
||||||
|
SPICY_DEBUG(hilti::util::fmt("Loading EVT file %s", rpath));
|
||||||
|
if ( _glue->loadEvtFile(rpath) )
|
||||||
|
return hilti::Nothing();
|
||||||
|
else
|
||||||
|
return hilti::result::Error(hilti::util::fmt("error loading EVT file %s", rpath));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ext == ".spicy" ) {
|
||||||
|
SPICY_DEBUG(hilti::util::fmt("Loading Spicy file %s", rpath));
|
||||||
|
if ( auto rc = addInput(rpath); ! rc )
|
||||||
|
return rc.error();
|
||||||
|
|
||||||
|
return hilti::Nothing();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ext == ".hlt" ) {
|
||||||
|
SPICY_DEBUG(hilti::util::fmt("Loading HILTI file %s", rpath));
|
||||||
|
if ( auto rc = addInput(rpath) )
|
||||||
|
return hilti::Nothing();
|
||||||
|
else
|
||||||
|
return rc.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ext == ".hlto" ) {
|
||||||
|
SPICY_DEBUG(hilti::util::fmt("Loading precompiled HILTI code %s", rpath));
|
||||||
|
if ( auto rc = addInput(rpath) )
|
||||||
|
return hilti::Nothing();
|
||||||
|
else
|
||||||
|
return rc.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ext == ".cc" || ext == ".cxx" ) {
|
||||||
|
SPICY_DEBUG(hilti::util::fmt("Loading C++ code %s", rpath));
|
||||||
|
if ( auto rc = addInput(rpath) )
|
||||||
|
return hilti::Nothing();
|
||||||
|
else
|
||||||
|
return rc.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
return hilti::result::Error(hilti::util::fmt("unknown file type passed to Spicy loader: %s", rpath));
|
||||||
|
}
|
||||||
|
|
||||||
|
hilti::Result<hilti::Nothing> Driver::compile() {
|
||||||
|
if ( ! hasInputs() )
|
||||||
|
return hilti::Nothing();
|
||||||
|
|
||||||
|
SPICY_DEBUG("Running Spicy driver");
|
||||||
|
|
||||||
|
if ( auto x = ::spicy::Driver::compile(); ! x )
|
||||||
|
return x.error();
|
||||||
|
|
||||||
|
SPICY_DEBUG("Done with Spicy driver");
|
||||||
|
return hilti::Nothing();
|
||||||
|
}
|
||||||
|
|
||||||
|
hilti::Result<TypeInfo> Driver::lookupType(const hilti::ID& id) {
|
||||||
|
if ( auto x = _types.find(id); x != _types.end() )
|
||||||
|
return x->second;
|
||||||
|
else
|
||||||
|
return hilti::result::Error(hilti::util::fmt("unknown type '%s'", id));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<TypeInfo> Driver::types() const {
|
||||||
|
std::vector<TypeInfo> result;
|
||||||
|
result.reserve(_types.size());
|
||||||
|
|
||||||
|
for ( const auto& t : _types )
|
||||||
|
result.push_back(t.second);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<TypeInfo, hilti::ID>> Driver::exportedTypes() const {
|
||||||
|
std::vector<std::pair<TypeInfo, hilti::ID>> result;
|
||||||
|
|
||||||
|
for ( const auto& [spicy_id, zeek_id, _] : _glue->exportedIDs() ) {
|
||||||
|
if ( auto t = _types.find(spicy_id); t != _types.end() )
|
||||||
|
result.emplace_back(t->second, zeek_id);
|
||||||
|
else {
|
||||||
|
hilti::logger().error(hilti::rt::fmt("unknown type '%s' exported", spicy_id));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically export public enums for backwards compatibility.
|
||||||
|
for ( const auto& t : _public_enums )
|
||||||
|
result.emplace_back(t, t.id);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Driver::hookNewASTPreCompilation(std::shared_ptr<hilti::Unit> unit) {
|
||||||
|
if ( unit->extension() != ".spicy" )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( unit->path().empty() )
|
||||||
|
// Ignore modules constructed in memory.
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto v = VisitorTypes(this, unit->id(), unit->path(), false);
|
||||||
|
for ( auto i : v.walk(unit->module()) )
|
||||||
|
v.dispatch(i);
|
||||||
|
|
||||||
|
for ( const auto& ti : v.types ) {
|
||||||
|
SPICY_DEBUG(hilti::util::fmt(" Got type '%s' (pre-compile)", ti.id));
|
||||||
|
_types[ti.id] = ti;
|
||||||
|
|
||||||
|
if ( auto et = ti.type.tryAs<hilti::type::Enum>(); et && ti.linkage == hilti::declaration::Linkage::Public ) {
|
||||||
|
SPICY_DEBUG(" Automatically exporting public enum for backwards compatibility");
|
||||||
|
_public_enums.push_back(ti);
|
||||||
|
}
|
||||||
|
|
||||||
|
hookNewType(ti);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Driver::hookNewASTPostCompilation(std::shared_ptr<hilti::Unit> unit) {
|
||||||
|
if ( unit->extension() != ".spicy" )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( unit->path().empty() )
|
||||||
|
// Ignore modules constructed in memory.
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto v = VisitorTypes(this, unit->id(), unit->path(), true);
|
||||||
|
for ( auto i : v.walk(unit->module()) )
|
||||||
|
v.dispatch(i);
|
||||||
|
|
||||||
|
for ( auto&& t : v.types ) {
|
||||||
|
SPICY_DEBUG(hilti::util::fmt(" Got type '%s' (post-compile)", t.id));
|
||||||
|
_types[t.id] = t;
|
||||||
|
hookNewType(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
_glue->addSpicyModule(unit->id(), unit->path());
|
||||||
|
}
|
||||||
|
|
||||||
|
hilti::Result<hilti::Nothing> Driver::hookCompilationFinished(const hilti::Plugin& plugin) {
|
||||||
|
if ( ! _need_glue )
|
||||||
|
return hilti::Nothing();
|
||||||
|
|
||||||
|
_need_glue = false;
|
||||||
|
|
||||||
|
if ( _glue->compile() )
|
||||||
|
return hilti::Nothing();
|
||||||
|
else
|
||||||
|
return hilti::result::Error("glue compilation failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Driver::hookInitRuntime() { ::spicy::rt::init(); }
|
||||||
|
|
||||||
|
void Driver::hookFinishRuntime() { ::spicy::rt::done(); }
|
199
src/spicy/spicyz/driver.h
Normal file
199
src/spicy/spicyz/driver.h
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <hilti/rt/filesystem.h>
|
||||||
|
|
||||||
|
#include <spicy/rt/driver.h>
|
||||||
|
|
||||||
|
#include <hilti/ast/declaration.h>
|
||||||
|
#include <hilti/ast/id.h>
|
||||||
|
#include <hilti/ast/type.h>
|
||||||
|
#include <hilti/base/logger.h>
|
||||||
|
#include <hilti/compiler/driver.h>
|
||||||
|
|
||||||
|
#include <spicy/compiler/driver.h>
|
||||||
|
|
||||||
|
// Debug stream for compiler messages.
|
||||||
|
static const ::hilti::logging::DebugStream ZeekPlugin("zeek");
|
||||||
|
|
||||||
|
// Macro helper to report debug messages.
|
||||||
|
#define SPICY_DEBUG(msg) HILTI_DEBUG(ZeekPlugin, std::string(msg));
|
||||||
|
|
||||||
|
namespace zeek::spicy {
|
||||||
|
|
||||||
|
class GlueCompiler;
|
||||||
|
|
||||||
|
struct TypeInfo {
|
||||||
|
hilti::ID id; /**< fully-qualified name of the type */
|
||||||
|
hilti::Type type; /**< the type itself */
|
||||||
|
hilti::declaration::Linkage linkage; /**< linkage of of the type's declaration */
|
||||||
|
bool is_resolved = false; /**< true if we are far enough in processing that the type has been fully resolved */
|
||||||
|
hilti::ID module_id; /**< name of module type is defined in */
|
||||||
|
hilti::rt::filesystem::path module_path; /**< path of module that type is defined in */
|
||||||
|
hilti::Location location; /**< location of type's declaration */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Spicy compilation driver. */
|
||||||
|
class Driver : public ::spicy::Driver {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param argv0 path to current executable, or empty to determine automatically
|
||||||
|
* @param lib_path Path to library files the Spicy support needs
|
||||||
|
* @param zeek_version Version number of Zeek we're working with
|
||||||
|
*/
|
||||||
|
Driver(std::unique_ptr<GlueCompiler> glue, const char* argv0, hilti::rt::filesystem::path lib_path,
|
||||||
|
int zeek_version);
|
||||||
|
|
||||||
|
/** Destructor. */
|
||||||
|
~Driver();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules an *.spicy, *.evt, or *.hlt file for loading. Note that it
|
||||||
|
* won't necessarily load them all immediately, but may queue some for
|
||||||
|
* later processing.
|
||||||
|
*
|
||||||
|
* @param file file to load, which will be searched across all current search paths
|
||||||
|
* @param relative_to if given, relative paths will be interpreted as relative to this directory
|
||||||
|
*/
|
||||||
|
hilti::Result<hilti::Nothing> loadFile(hilti::rt::filesystem::path file,
|
||||||
|
const hilti::rt::filesystem::path& relative_to = {});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* After user scripts have been read, compiles and links all resulting
|
||||||
|
* Spicy code. Note that compiler and driver options must have been set
|
||||||
|
* before calling this.
|
||||||
|
*
|
||||||
|
* Must be called before any packet processing starts.
|
||||||
|
*
|
||||||
|
* @return False if an error occurred. It will have been reported already.
|
||||||
|
*/
|
||||||
|
hilti::Result<hilti::Nothing> compile();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns meta information for a type. The Spicy module defining the type
|
||||||
|
* must have been compiled already for it to be found.
|
||||||
|
*
|
||||||
|
* @param id fully qualified name of type to look up
|
||||||
|
* @return meta data, or an error if the type is not (yet) known
|
||||||
|
*/
|
||||||
|
hilti::Result<TypeInfo> lookupType(const hilti::ID& id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns meta information for a type, enforcing it to be a of a certain
|
||||||
|
* kind. The Spicy module defining the type must have been compiled already
|
||||||
|
* for it to be found.
|
||||||
|
*
|
||||||
|
* @tparam T type to enforce; method will return an error if type is not of this class
|
||||||
|
* @param id fully qualified name of type to look up
|
||||||
|
* @return meta data, or an error if the type is not (yet) known
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
hilti::Result<TypeInfo> lookupType(const hilti::ID& id) {
|
||||||
|
auto ti = lookupType(id);
|
||||||
|
if ( ! ti )
|
||||||
|
return ti.error();
|
||||||
|
|
||||||
|
if ( ! ti->type.isA<T>() )
|
||||||
|
return hilti::result::Error(hilti::util::fmt("'%s' is not of expected type", id));
|
||||||
|
|
||||||
|
return ti;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all types seen so far during processing of Spicy files.
|
||||||
|
* Depending on where we are at with processing, these may or may not be
|
||||||
|
* resolved yet (as indicated by their `is_resolved` field).
|
||||||
|
|
||||||
|
* @return list of types
|
||||||
|
*/
|
||||||
|
std::vector<TypeInfo> types() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all *exported* types seen so far during processing of Spicy
|
||||||
|
* files, including their desired Zeek-side names. Depending on where we
|
||||||
|
* are at with processing, these may or may not be resolved yet (as
|
||||||
|
* indicated by their `is_resolved` field).
|
||||||
|
*
|
||||||
|
* @return list of pairs of type and Zeek-side name
|
||||||
|
*/
|
||||||
|
std::vector<std::pair<TypeInfo, hilti::ID>> exportedTypes() const;
|
||||||
|
|
||||||
|
/** Returns true if we're running out of the plugin's build directory. */
|
||||||
|
bool usingBuildDirectory() const { return _using_build_directory; }
|
||||||
|
|
||||||
|
/** Returns the glue compiler in use by the driver. */
|
||||||
|
const auto* glueCompiler() const { return _glue.get(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses some options command-line style *before* Zeek-side scripts have
|
||||||
|
* been processed. Most of the option processing happens in
|
||||||
|
* `parseOptionsPostScript()` instead, except for things that must be in
|
||||||
|
* place already before script processing.
|
||||||
|
*
|
||||||
|
* @param options space-separated string of command line argument to parse
|
||||||
|
* @return success if all argument could be parsed, or a suitable error message
|
||||||
|
*/
|
||||||
|
static hilti::Result<hilti::Nothing> parseOptionsPreScript(const std::string& options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses options command-line style after Zeek-side scripts have been
|
||||||
|
* fully procssed. Most of the option processing happens here (vs. in
|
||||||
|
* `parseOptionsPreScript()`) except for things that must be in place
|
||||||
|
* already before script processing.
|
||||||
|
*
|
||||||
|
* @param options space-separated string of command line argument to parse
|
||||||
|
* @param driver_options instance of options to update per parsed arguments
|
||||||
|
* @param compiler_options instance of options to update per parsed arguments
|
||||||
|
* @return success if all argument could be parsed, or a suitable error message
|
||||||
|
*/
|
||||||
|
static hilti::Result<hilti::Nothing> parseOptionsPostScript(const std::string& options,
|
||||||
|
hilti::driver::Options* driver_options,
|
||||||
|
hilti::Options* compiler_options);
|
||||||
|
|
||||||
|
/** Prints a usage message for options supported by `parseOptions{Pre,Post}Script()`. */
|
||||||
|
static void usage(std::ostream& out);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* Hook executed for all type declarations encountered in a Spicy module.
|
||||||
|
* Derived classes may override this to add custom processing. This hooks
|
||||||
|
* executes twices for each declaration: once before we compile the AST
|
||||||
|
* (meaning types have not been resolved yet), and once after. The type
|
||||||
|
* info's `is_resolved` field indicates which of the two we're in.
|
||||||
|
*
|
||||||
|
* @param t type's meta information
|
||||||
|
*/
|
||||||
|
virtual void hookNewType(const TypeInfo& ti) {}
|
||||||
|
|
||||||
|
/** Overridden from HILTI driver. */
|
||||||
|
void hookNewASTPreCompilation(std::shared_ptr<hilti::Unit> unit) override;
|
||||||
|
|
||||||
|
/** Overridden from HILTI driver. */
|
||||||
|
void hookNewASTPostCompilation(std::shared_ptr<hilti::Unit> unit) override;
|
||||||
|
|
||||||
|
/** Overridden from HILTI driver. */
|
||||||
|
hilti::Result<hilti::Nothing> hookCompilationFinished(const hilti::Plugin& plugin) override;
|
||||||
|
|
||||||
|
/** Overridden from HILTI driver. */
|
||||||
|
void hookInitRuntime() override;
|
||||||
|
|
||||||
|
/** Overridden from HILTI driver. */
|
||||||
|
void hookFinishRuntime() override;
|
||||||
|
|
||||||
|
std::unique_ptr<GlueCompiler> _glue; // glue compiler in use
|
||||||
|
std::unordered_map<hilti::ID, TypeInfo> _types; // map of Spicy type declarations encountered so far
|
||||||
|
std::vector<TypeInfo> _public_enums; // tracks Spicy enum types declared public, for automatic export
|
||||||
|
bool _using_build_directory = false; // true if we're running out of the plugin's build directory
|
||||||
|
bool _need_glue = true; // true if glue code has not yet been generated
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace zeek::spicy
|
1383
src/spicy/spicyz/glue-compiler.cc
Normal file
1383
src/spicy/spicyz/glue-compiler.cc
Normal file
File diff suppressed because it is too large
Load diff
242
src/spicy/spicyz/glue-compiler.h
Normal file
242
src/spicy/spicyz/glue-compiler.h
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <hilti/rt/filesystem.h>
|
||||||
|
#include <hilti/rt/types/port.h>
|
||||||
|
#include <hilti/rt/util.h>
|
||||||
|
|
||||||
|
#include <spicy/rt/mime.h>
|
||||||
|
|
||||||
|
#include <hilti/ast/declarations/function.h>
|
||||||
|
#include <hilti/ast/expression.h>
|
||||||
|
#include <hilti/ast/module.h>
|
||||||
|
#include <hilti/ast/type.h>
|
||||||
|
#include <hilti/compiler/context.h>
|
||||||
|
#include <hilti/compiler/driver.h>
|
||||||
|
|
||||||
|
#include <spicy/ast/declarations/unit-hook.h>
|
||||||
|
#include <spicy/ast/types/unit.h>
|
||||||
|
|
||||||
|
#include "driver.h"
|
||||||
|
|
||||||
|
namespace spicy::rt {
|
||||||
|
struct Parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace zeek::spicy {
|
||||||
|
|
||||||
|
namespace glue {
|
||||||
|
|
||||||
|
/** Representation of a Spicy protocol analyzer, parsed from an EVT file. */
|
||||||
|
struct ProtocolAnalyzer {
|
||||||
|
// Information parsed directly from the *.evt file.
|
||||||
|
hilti::Location location; /**< Location where the analyzer was defined. */
|
||||||
|
hilti::ID name; /**< Name of the analyzer. */
|
||||||
|
hilti::rt::Protocol protocol = hilti::rt::Protocol::Undef; /**< The transport layer the analyzer uses. */
|
||||||
|
std::vector<hilti::rt::Port> ports; /**< The ports associated with the analyzer. */
|
||||||
|
hilti::ID unit_name_orig; /**< The fully-qualified name of the unit type to parse the originator
|
||||||
|
side. */
|
||||||
|
hilti::ID unit_name_resp; /**< The fully-qualified name of the unit type to parse the originator
|
||||||
|
side. */
|
||||||
|
std::string replaces; /**< Name of another analyzer this one replaces. */
|
||||||
|
|
||||||
|
// Computed information.
|
||||||
|
std::optional<TypeInfo> unit_orig; /**< The type of the unit to parse the originator side. */
|
||||||
|
std::optional<TypeInfo> unit_resp; /**< The type of the unit to parse the originator side. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Representation of a Spicy file analyzer, parsed from an EVT file. */
|
||||||
|
struct FileAnalyzer {
|
||||||
|
// Information parsed directly from the *.evt file.
|
||||||
|
hilti::Location location; /**< Location where the analyzer was defined. */
|
||||||
|
hilti::ID name; /**< Name of the analyzer. */
|
||||||
|
std::vector<std::string> mime_types; /**< The mime_types associated with the analyzer. */
|
||||||
|
hilti::ID unit_name; /**< The fully-qualified name of the unit type to parse with. */
|
||||||
|
std::string replaces; /**< Name of another analyzer this one replaces. */
|
||||||
|
|
||||||
|
// Computed information.
|
||||||
|
std::optional<TypeInfo> unit; /**< The type of the unit to parse the originator side. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Representation of a Spicy packet analyzer, parsed from an EVT file. */
|
||||||
|
struct PacketAnalyzer {
|
||||||
|
// Information parsed directly from the *.evt file.
|
||||||
|
hilti::Location location; /**< Location where the analyzer was defined. */
|
||||||
|
hilti::ID name; /**< Name of the analyzer. */
|
||||||
|
hilti::ID unit_name; /**< The fully-qualified name of the unit type to parse with. */
|
||||||
|
std::string replaces; /**< Name of another analyzer this one replaces. */
|
||||||
|
|
||||||
|
// Computed information.
|
||||||
|
std::optional<TypeInfo> unit; /**< The type of the unit to parse the originator side. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of an expression computing the value of a parameter passed
|
||||||
|
* to Spicy-generated events.
|
||||||
|
*/
|
||||||
|
struct ExpressionAccessor {
|
||||||
|
// Information parsed directly from the *.evt file.
|
||||||
|
int nr; /**< Position of this expression in argument list. */
|
||||||
|
std::string expression; /**< The original string representation of the expression. */
|
||||||
|
hilti::Location location; /**< Location where the expression was defined. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Representation of a compiled Spicy module. */
|
||||||
|
struct SpicyModule {
|
||||||
|
// Provided.
|
||||||
|
hilti::ID id; /**< Name of the module */
|
||||||
|
hilti::rt::filesystem::path file; /**< The path the module was read from. */
|
||||||
|
std::set<hilti::rt::filesystem::path> evts; /**< EVT files that refer to this module. */
|
||||||
|
|
||||||
|
// Generated code.
|
||||||
|
std::optional<hilti::Module> spicy_module; /**< the ``BroHooks_*.spicy`` module. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Representation of an event parsed from an EVT file. */
|
||||||
|
struct Event {
|
||||||
|
// Information parsed directly from the *.evt file.
|
||||||
|
hilti::rt::filesystem::path file; /**< The path of the *.evt file we parsed this from. */
|
||||||
|
hilti::ID name; /**< The name of the event. */
|
||||||
|
hilti::ID path; /**< The hook path as specified in the evt file. */
|
||||||
|
std::vector<hilti::type::function::Parameter> parameters; /**< Event parameters specified in the evt file. */
|
||||||
|
std::string condition; /**< Condition that must be true for the event to trigger. */
|
||||||
|
std::vector<std::string> exprs; /**< The argument expressions. */
|
||||||
|
int priority; /**< Event/hook priority. */
|
||||||
|
hilti::Location location; /**< Location where event is defined. */
|
||||||
|
|
||||||
|
// Computed information.
|
||||||
|
hilti::ID hook; /**< The name of the hook triggering the event. */
|
||||||
|
hilti::ID unit; /**< The fully qualified name of the unit type. */
|
||||||
|
std::optional<::spicy::type::Unit> unit_type; /**< The Spicy type of referenced unit. */
|
||||||
|
hilti::ID unit_module_id; /**< The name of the module the referenced unit is defined in. */
|
||||||
|
hilti::rt::filesystem::path unit_module_path; /**< The path of the module that the referenced unit is defined in. */
|
||||||
|
std::shared_ptr<glue::SpicyModule>
|
||||||
|
spicy_module; /**< State for the Spichy module the referenced unit is defined in. */
|
||||||
|
|
||||||
|
// TODO: The following aren't set yet.
|
||||||
|
|
||||||
|
// Code generation.
|
||||||
|
std::optional<::spicy::declaration::UnitHook> spicy_hook; /**< The generated Spicy hook. */
|
||||||
|
std::optional<hilti::declaration::Function> hilti_raise; /**< The generated HILTI raise() function. */
|
||||||
|
std::vector<ExpressionAccessor> expression_accessors; /**< One HILTI function per expression to access the value. */
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace glue
|
||||||
|
|
||||||
|
/** Generates the glue code between Zeek and Spicy based on *.evt files. */
|
||||||
|
class GlueCompiler {
|
||||||
|
public:
|
||||||
|
/** Constructor. */
|
||||||
|
GlueCompiler() {}
|
||||||
|
|
||||||
|
/** Destructor. */
|
||||||
|
virtual ~GlueCompiler();
|
||||||
|
|
||||||
|
/** Parses an `*.evt` file, without generating any code yet. */
|
||||||
|
bool loadEvtFile(hilti::rt::filesystem::path& path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a Spicy file to generate glue code for, without generating
|
||||||
|
* any code yet.
|
||||||
|
*
|
||||||
|
* @param id ID of the module
|
||||||
|
* @param file path the module is loaded from
|
||||||
|
*/
|
||||||
|
void addSpicyModule(const hilti::ID& id, const hilti::rt::filesystem::path& file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates all glue code based on previously registered `*.evt` and
|
||||||
|
* Spicy files.
|
||||||
|
*/
|
||||||
|
bool compile();
|
||||||
|
|
||||||
|
/** Returns all IDs that have been exported so far. */
|
||||||
|
const auto& exportedIDs() const { return _exports; }
|
||||||
|
|
||||||
|
/** Generates code to convert a HILTI type to a corresponding Zeek type at runtime. */
|
||||||
|
hilti::Result<hilti::Expression> createZeekType(const hilti::Type& t, const hilti::ID& id) const;
|
||||||
|
|
||||||
|
using RecordField = std::tuple<std::string, hilti::Type, bool>; /**< (ID, type, optional) */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to retrieve a list of Zeek-side record fields that converting a
|
||||||
|
* Spicy unit to a Zeek record will yield.
|
||||||
|
*
|
||||||
|
* @param unit the unit type to retrieve fields for
|
||||||
|
* @return list of fields
|
||||||
|
*/
|
||||||
|
static std::vector<RecordField> recordFields(const ::spicy::type::Unit& unit);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class Driver;
|
||||||
|
|
||||||
|
/** Called by driver to initialized a provided glue compiler. */
|
||||||
|
void Init(Driver* driver, int zeek_version);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Filters input EVT file by applying preprocessor directives.
|
||||||
|
*/
|
||||||
|
void preprocessEvtFile(hilti::rt::filesystem::path& path, std::istream& in, std::ostream& out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the next semicolon-terminated block from an input stream,
|
||||||
|
* accounting for special EVT constructs like strings and comments.
|
||||||
|
*
|
||||||
|
* @param in stream to read from
|
||||||
|
* @param lineno pointer to integer that will be increased with line breaks
|
||||||
|
* @return the read block of data, with comments removed, and empty if end of
|
||||||
|
* data has been reached; error will be set if parsing failed
|
||||||
|
*/
|
||||||
|
hilti::Result<std::string> getNextEvtBlock(std::istream& in, int* lineno) const;
|
||||||
|
|
||||||
|
// Parsers for parts from EVT files.
|
||||||
|
glue::ProtocolAnalyzer parseProtocolAnalyzer(const std::string& chunk);
|
||||||
|
glue::FileAnalyzer parseFileAnalyzer(const std::string& chunk);
|
||||||
|
glue::PacketAnalyzer parsePacketAnalyzer(const std::string& chunk);
|
||||||
|
glue::Event parseEvent(const std::string& chunk);
|
||||||
|
|
||||||
|
/** Computes the missing pieces for all `Event` instances. */
|
||||||
|
bool PopulateEvents();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the Spicy hook for an event that triggers a corresponding Zeek
|
||||||
|
* event.
|
||||||
|
*/
|
||||||
|
bool CreateSpicyHook(glue::Event* ev);
|
||||||
|
|
||||||
|
Driver* _driver = nullptr; /**< driver provided to Init() */
|
||||||
|
std::optional<int> _zeek_version; /**< Zeek version provided to Init() */
|
||||||
|
|
||||||
|
std::map<hilti::ID, std::shared_ptr<glue::SpicyModule>> _spicy_modules;
|
||||||
|
|
||||||
|
std::vector<std::pair<hilti::ID, std::optional<hilti::ID>>>
|
||||||
|
_imports; /**< imports from EVT files, with ID and optional scope */
|
||||||
|
std::vector<std::tuple<hilti::ID, hilti::ID, hilti::Location>> _exports; /**< exports from EVT files */
|
||||||
|
std::vector<glue::Event> _events; /**< events parsed from EVT files */
|
||||||
|
std::vector<glue::ProtocolAnalyzer> _protocol_analyzers; /**< protocol analyzers parsed from EVT files */
|
||||||
|
std::vector<glue::FileAnalyzer> _file_analyzers; /**< file analyzers parsed from EVT files */
|
||||||
|
std::vector<glue::PacketAnalyzer> _packet_analyzers; /**< file analyzers parsed from EVT files */
|
||||||
|
std::vector<hilti::Location> _locations; /**< location stack during parsing EVT files */
|
||||||
|
};
|
||||||
|
} // namespace zeek::spicy
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template<>
|
||||||
|
struct hash<zeek::spicy::glue::Event> {
|
||||||
|
std::size_t operator()(const zeek::spicy::glue::Event& e) {
|
||||||
|
// We only hash enough information here to unique identify the event.
|
||||||
|
return hilti::rt::hashCombine(std::hash<std::string>()(e.file), std::hash<std::string>()(e.name),
|
||||||
|
std::hash<std::string>()(e.path), std::hash<std::string>()(e.location));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace std
|
282
src/spicy/spicyz/main.cc
Normal file
282
src/spicy/spicyz/main.cc
Normal file
|
@ -0,0 +1,282 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
#include <hilti/base/result.h>
|
||||||
|
#include <hilti/base/util.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "driver.h"
|
||||||
|
#include "glue-compiler.h"
|
||||||
|
|
||||||
|
using namespace zeek::spicy;
|
||||||
|
|
||||||
|
constexpr int OPT_CXX_LINK = 1000;
|
||||||
|
|
||||||
|
static struct option long_driver_options[] = {{"abort-on-exceptions", required_argument, nullptr, 'A'},
|
||||||
|
{"show-backtraces", required_argument, nullptr, 'B'},
|
||||||
|
{"compiler-debug", required_argument, nullptr, 'D'},
|
||||||
|
{"cxx-link", required_argument, nullptr, OPT_CXX_LINK},
|
||||||
|
{"debug", no_argument, nullptr, 'd'},
|
||||||
|
{"debug-addl", required_argument, nullptr, 'X'},
|
||||||
|
{"disable-optimizations", no_argument, nullptr, 'g'},
|
||||||
|
{"dump-code", no_argument, nullptr, 'C'},
|
||||||
|
{"enable-profiling", no_argument, nullptr, 'Z'},
|
||||||
|
{"help", no_argument, nullptr, 'h'},
|
||||||
|
{"keep-tmps", no_argument, nullptr, 'T'},
|
||||||
|
{"library-path", required_argument, nullptr, 'L'},
|
||||||
|
{"output", required_argument, nullptr, 'o'},
|
||||||
|
{"output-c++", required_argument, nullptr, 'c'},
|
||||||
|
{"output-c++-files", no_argument, nullptr, 'x'},
|
||||||
|
{"print-module-path", no_argument, nullptr, 'M'},
|
||||||
|
{"print-plugin-path", no_argument, nullptr,
|
||||||
|
'P'}, // for backwards compatiblity
|
||||||
|
{"print-prefix-path", no_argument, nullptr, 'p'},
|
||||||
|
{"print-zeek-config", no_argument, nullptr, 'z'},
|
||||||
|
{"report-times", required_argument, nullptr, 'R'},
|
||||||
|
{"print-scripts-path", no_argument, nullptr, 'S'},
|
||||||
|
{"skip-validation", no_argument, nullptr, '!'},
|
||||||
|
{"version", no_argument, nullptr, 'v'},
|
||||||
|
{"version-number", no_argument, nullptr, 'V'},
|
||||||
|
{nullptr, 0, nullptr, 0}};
|
||||||
|
|
||||||
|
static void usage() {
|
||||||
|
std::cerr << "Usage: spicyz [options] <inputs>\n"
|
||||||
|
"\n"
|
||||||
|
" -c | --output-c++ <prefix> Output generated C++ code.\n"
|
||||||
|
" -d | --debug Include debug instrumentation into generated code.\n"
|
||||||
|
" -g | --disable-optimizations Disable HILTI-side optimizations of the generated "
|
||||||
|
"code.\n"
|
||||||
|
" -o | --output-to <path> Path for saving output.\n"
|
||||||
|
" -v | --version Print version information.\n"
|
||||||
|
" -x | --output-c++ <prefix> Output generated C++ code into set of files.\n"
|
||||||
|
" -z | --print-zeek-config Print path to zeek-config.\n"
|
||||||
|
" -A | --abort-on-exceptions When executing compiled code, abort() instead of "
|
||||||
|
"throwing HILTI "
|
||||||
|
"exceptions.\n"
|
||||||
|
" -B | --show-backtraces Include backtraces when reporting unhandled "
|
||||||
|
"exceptions.\n"
|
||||||
|
" -C | --dump-code Dump all generated code to disk for debugging.\n"
|
||||||
|
" -D | --compiler-debug <streams> Activate compile-time debugging output for given "
|
||||||
|
"debug streams "
|
||||||
|
"(comma-separated; 'help' for list).\n"
|
||||||
|
" -L | --library-path <path> Add path to list of directories to search when "
|
||||||
|
"importing modules.\n"
|
||||||
|
" -M | --print-module-path Print the Zeek's search path for compiled Spicy modules.\n"
|
||||||
|
" -p | --print-prefix-path Print installation prefix path.\n"
|
||||||
|
" -R | --report-times Report a break-down of compiler's execution time.\n"
|
||||||
|
" -T | --keep-tmps Do not delete any temporary files created.\n"
|
||||||
|
" --skip-validation Don't validate ASTs (for debugging only).\n"
|
||||||
|
" -X | --debug-addl <addl> Implies -d and adds selected additional "
|
||||||
|
"instrumentation."
|
||||||
|
"(comma-separated; see 'help' for list).\n"
|
||||||
|
" --cxx-link <lib> Link specified static archive or shared library "
|
||||||
|
"during JIT or to "
|
||||||
|
" -Z | --enable-profiling Report profiling statistics after execution.\n"
|
||||||
|
"\n"
|
||||||
|
"Inputs can be *.spicy, *.evt, *.hlt, .cc/.cxx\n"
|
||||||
|
"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
using hilti::Nothing;
|
||||||
|
|
||||||
|
static hilti::Result<Nothing> parseOptions(int argc, char** argv, hilti::driver::Options* driver_options,
|
||||||
|
hilti::Options* compiler_options) {
|
||||||
|
while ( true ) {
|
||||||
|
int c = getopt_long(argc, argv, "ABc:Cdgx:X:D:L:Mo:pPRSTvhzZ", long_driver_options, nullptr);
|
||||||
|
|
||||||
|
if ( c == -1 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch ( c ) {
|
||||||
|
case 'A': driver_options->abort_on_exceptions = true; break;
|
||||||
|
|
||||||
|
case 'B': driver_options->show_backtraces = true; break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
driver_options->output_cxx = true;
|
||||||
|
driver_options->output_cxx_prefix = optarg;
|
||||||
|
driver_options->execute_code = false;
|
||||||
|
compiler_options->cxx_namespace_extern =
|
||||||
|
hilti::util::fmt("hlt_%s", hilti::rt::filesystem::path(optarg).stem().string());
|
||||||
|
compiler_options->cxx_namespace_intern =
|
||||||
|
hilti::util::fmt("__hlt_%s", hilti::rt::filesystem::path(optarg).stem().string());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'C': {
|
||||||
|
driver_options->dump_code = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'd': {
|
||||||
|
compiler_options->debug = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'g': {
|
||||||
|
driver_options->global_optimizations = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'p': std::cout << configuration::InstallPrefix.native() << std::endl; return Nothing();
|
||||||
|
|
||||||
|
case 'P':
|
||||||
|
// For backwards compatibility with older plugins, print
|
||||||
|
// the path where the `cmake/` folder is located.
|
||||||
|
std::cout << configuration::DataPath().native() << std::endl;
|
||||||
|
return Nothing();
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
driver_options->output_cxx = true;
|
||||||
|
driver_options->output_cxx_prefix = optarg;
|
||||||
|
driver_options->execute_code = false;
|
||||||
|
driver_options->include_linker = true;
|
||||||
|
compiler_options->cxx_namespace_extern =
|
||||||
|
hilti::util::fmt("hlt_%s", hilti::rt::filesystem::path(optarg).stem().string());
|
||||||
|
compiler_options->cxx_namespace_intern =
|
||||||
|
hilti::util::fmt("__hlt_%s", hilti::rt::filesystem::path(optarg).stem().string());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'X': {
|
||||||
|
auto arg = std::string(optarg);
|
||||||
|
|
||||||
|
if ( arg == "help" ) {
|
||||||
|
std::cerr << "Additional debug instrumentation:\n";
|
||||||
|
std::cerr << " flow: log function calls to debug stream \"hilti-flow\"\n";
|
||||||
|
std::cerr << " location: track current source code location for error reporting\n";
|
||||||
|
std::cerr << " trace: log statements to debug stream \"hilti-trace\"\n";
|
||||||
|
std::cerr << "\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
compiler_options->debug = true;
|
||||||
|
|
||||||
|
if ( auto r = compiler_options->parseDebugAddl(arg); ! r )
|
||||||
|
return hilti::result::Error("nothing to do");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'D': {
|
||||||
|
auto arg = std::string(optarg);
|
||||||
|
|
||||||
|
if ( arg == "help" ) {
|
||||||
|
std::cerr << "Debug streams:\n";
|
||||||
|
|
||||||
|
for ( const auto& s : hilti::logging::DebugStream::all() )
|
||||||
|
std::cerr << " " << s << "\n";
|
||||||
|
|
||||||
|
std::cerr << "\n";
|
||||||
|
return Nothing();
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( const auto& s : hilti::util::split(arg, ",") ) {
|
||||||
|
if ( ! driver_options->logger->debugEnable(s) )
|
||||||
|
return hilti::result::Error(
|
||||||
|
hilti::util::fmt("Unknown debug stream '%s', use 'help' for list", arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'L': compiler_options->library_paths.emplace_back(std::string(optarg)); break;
|
||||||
|
|
||||||
|
case 'M': std::cout << configuration::ModulePath().native() << std::endl; return Nothing();
|
||||||
|
|
||||||
|
case 'o': driver_options->output_path = std::string(optarg); break;
|
||||||
|
|
||||||
|
case 'R': driver_options->report_times = true; break;
|
||||||
|
|
||||||
|
case 'S': std::cout << "" << std::endl; return Nothing(); // No longer needed, but left for compatibility.
|
||||||
|
|
||||||
|
case 'T':
|
||||||
|
driver_options->keep_tmps = true;
|
||||||
|
compiler_options->keep_tmps = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'v': std::cout << configuration::ZeekVersion << std::endl; return Nothing();
|
||||||
|
|
||||||
|
case 'V': std::cout << ZEEK_VERSION_NUMBER << std::endl; return Nothing();
|
||||||
|
|
||||||
|
case 'z': {
|
||||||
|
if ( auto zcfg = getenv("ZEEK_CONFIG"); zcfg && *zcfg )
|
||||||
|
std::cout << zcfg << std::endl;
|
||||||
|
else
|
||||||
|
std::cout << configuration::InstallBinDir().native() << std::endl;
|
||||||
|
|
||||||
|
return Nothing();
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'Z':
|
||||||
|
#if SPICY_VERSION_NUMBER >= 10800
|
||||||
|
driver_options->enable_profiling = true;
|
||||||
|
compiler_options->enable_profiling = true;
|
||||||
|
#else
|
||||||
|
std::cerr << "Profiling is not supported with this version of Spicy, ignoring '-Z'\n";
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPT_CXX_LINK:
|
||||||
|
#if SPICY_VERSION_NUMBER >= 10600
|
||||||
|
compiler_options->cxx_link.emplace_back(optarg);
|
||||||
|
#else
|
||||||
|
return hilti::result::Error("option '--cxx-link' is only supported for Spicy 1.6 or newer");
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h': usage(); return Nothing();
|
||||||
|
|
||||||
|
case '!': compiler_options->skip_validation = true; break;
|
||||||
|
|
||||||
|
default: usage(); return hilti::result::Error("could not parse options");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( optind < argc )
|
||||||
|
driver_options->inputs.emplace_back(argv[optind++]);
|
||||||
|
|
||||||
|
if ( driver_options->inputs.empty() )
|
||||||
|
return hilti::result::Error("no input file given");
|
||||||
|
|
||||||
|
if ( driver_options->output_path.empty() && ! driver_options->output_cxx )
|
||||||
|
return hilti::result::Error("no output file for object code given, use -o <file>.hlto");
|
||||||
|
|
||||||
|
return Nothing();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
Driver driver(std::make_unique<GlueCompiler>(), "", configuration::LibraryPath(), ZEEK_VERSION_NUMBER);
|
||||||
|
|
||||||
|
hilti::driver::Options driver_options;
|
||||||
|
driver_options.execute_code = true;
|
||||||
|
driver_options.include_linker = true;
|
||||||
|
|
||||||
|
auto compiler_options = driver.hiltiOptions();
|
||||||
|
|
||||||
|
if ( auto rc = parseOptions(argc, argv, &driver_options, &compiler_options); ! rc ) {
|
||||||
|
hilti::logger().error(rc.error().description());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
driver.setDriverOptions(std::move(driver_options));
|
||||||
|
driver.setCompilerOptions(std::move(compiler_options));
|
||||||
|
driver.initialize();
|
||||||
|
|
||||||
|
for ( const auto& p : driver.driverOptions().inputs ) {
|
||||||
|
if ( auto rc = driver.loadFile(p); ! rc ) {
|
||||||
|
hilti::logger().error(rc.error().description());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( auto rc = driver.compile(); ! rc ) {
|
||||||
|
hilti::logger().error(rc.error().description());
|
||||||
|
|
||||||
|
if ( rc.error().context().size() )
|
||||||
|
hilti::logger().error(rc.error().context());
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -1,3 +1,7 @@
|
||||||
#define ZEEK_SCRIPT_INSTALL_PATH "@ZEEK_SCRIPT_INSTALL_PATH@"
|
#define ZEEK_SCRIPT_INSTALL_PATH "@ZEEK_SCRIPT_INSTALL_PATH@"
|
||||||
#define BRO_PLUGIN_INSTALL_PATH "@ZEEK_PLUGIN_DIR@"
|
#define BRO_PLUGIN_INSTALL_PATH "@ZEEK_PLUGIN_DIR@"
|
||||||
|
#define ZEEK_PLUGIN_INSTALL_PATH "@ZEEK_PLUGIN_DIR@"
|
||||||
#define DEFAULT_ZEEKPATH "@DEFAULT_ZEEKPATH@"
|
#define DEFAULT_ZEEKPATH "@DEFAULT_ZEEKPATH@"
|
||||||
|
#define ZEEK_SPICY_MODULE_PATH "@ZEEK_SPICY_MODULE_PATH@"
|
||||||
|
#define ZEEK_SPICY_LIBRARY_PATH "@ZEEK_SPICY_LIBRARY_PATH@"
|
||||||
|
#define ZEEK_SPICY_DATA_PATH "@ZEEK_SPICY_DATA_PATH@"
|
||||||
|
|
|
@ -65,6 +65,9 @@
|
||||||
#include "zeek/plugin/Manager.h"
|
#include "zeek/plugin/Manager.h"
|
||||||
#include "zeek/script_opt/ScriptOpt.h"
|
#include "zeek/script_opt/ScriptOpt.h"
|
||||||
#include "zeek/session/Manager.h"
|
#include "zeek/session/Manager.h"
|
||||||
|
#ifdef HAVE_SPICY
|
||||||
|
#include "zeek/spicy/manager.h"
|
||||||
|
#endif
|
||||||
#include "zeek/supervisor/Supervisor.h"
|
#include "zeek/supervisor/Supervisor.h"
|
||||||
#include "zeek/telemetry/Manager.h"
|
#include "zeek/telemetry/Manager.h"
|
||||||
#include "zeek/threading/Manager.h"
|
#include "zeek/threading/Manager.h"
|
||||||
|
@ -191,6 +194,9 @@ zeek::Broker::Manager* zeek::broker_mgr = nullptr;
|
||||||
zeek::telemetry::Manager* zeek::telemetry_mgr = nullptr;
|
zeek::telemetry::Manager* zeek::telemetry_mgr = nullptr;
|
||||||
zeek::Supervisor* zeek::supervisor_mgr = nullptr;
|
zeek::Supervisor* zeek::supervisor_mgr = nullptr;
|
||||||
zeek::detail::trigger::Manager* zeek::detail::trigger_mgr = nullptr;
|
zeek::detail::trigger::Manager* zeek::detail::trigger_mgr = nullptr;
|
||||||
|
#ifdef HAVE_SPICY
|
||||||
|
zeek::spicy::Manager* zeek::spicy_mgr = nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
std::vector<std::string> zeek::detail::zeek_script_prefixes;
|
std::vector<std::string> zeek::detail::zeek_script_prefixes;
|
||||||
zeek::detail::Stmt* zeek::detail::stmts = nullptr;
|
zeek::detail::Stmt* zeek::detail::stmts = nullptr;
|
||||||
|
@ -437,6 +443,9 @@ static void terminate_zeek()
|
||||||
delete session_mgr;
|
delete session_mgr;
|
||||||
delete fragment_mgr;
|
delete fragment_mgr;
|
||||||
delete telemetry_mgr;
|
delete telemetry_mgr;
|
||||||
|
#ifdef HAVE_SPICY
|
||||||
|
delete spicy_mgr;
|
||||||
|
#endif
|
||||||
|
|
||||||
// free the global scope
|
// free the global scope
|
||||||
pop_scope();
|
pop_scope();
|
||||||
|
@ -719,6 +728,9 @@ SetupResult setup(int argc, char** argv, Options* zopts)
|
||||||
auto broker_real_time = ! options.pcap_file && ! options.deterministic_mode;
|
auto broker_real_time = ! options.pcap_file && ! options.deterministic_mode;
|
||||||
broker_mgr = new Broker::Manager(broker_real_time);
|
broker_mgr = new Broker::Manager(broker_real_time);
|
||||||
trigger_mgr = new trigger::Manager();
|
trigger_mgr = new trigger::Manager();
|
||||||
|
#ifdef HAVE_SPICY
|
||||||
|
spicy_mgr = new spicy::Manager(); // registers as plugin with the plugin manager
|
||||||
|
#endif
|
||||||
|
|
||||||
plugin_mgr->InitPreScript();
|
plugin_mgr->InitPreScript();
|
||||||
file_mgr->InitPreScript();
|
file_mgr->InitPreScript();
|
||||||
|
|
13
src/zeek.bif
13
src/zeek.bif
|
@ -5811,8 +5811,19 @@ function has_module_events%(group: string%) : bool
|
||||||
group->CheckString()));
|
group->CheckString()));
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
## Returns true if Zeek was built with support for using Spicy analyzers (which
|
||||||
|
# is the default).
|
||||||
|
function have_spicy%(%) : bool
|
||||||
|
%{
|
||||||
|
#ifdef HAVE_SPICY
|
||||||
|
return zeek::val_mgr->Bool(true);
|
||||||
|
#else
|
||||||
|
return zeek::val_mgr->Bool(false);
|
||||||
|
#endif
|
||||||
|
%}
|
||||||
|
|
||||||
## Returns true if Zeek was built with support for its in-tree Spicy analyzers
|
## Returns true if Zeek was built with support for its in-tree Spicy analyzers
|
||||||
## (which is the default).
|
## (which is the default if Spicy support is available).
|
||||||
function have_spicy_analyzers%(%) : bool
|
function have_spicy_analyzers%(%) : bool
|
||||||
%{
|
%{
|
||||||
return zeek::val_mgr->Bool(USE_SPICY_ANALYZERS);
|
return zeek::val_mgr->Bool(USE_SPICY_ANALYZERS);
|
||||||
|
|
|
@ -8,3 +8,14 @@ install(FILES btest/random.seed DESTINATION ${ZEEK_CONFIG_BTEST_TOOLS_DIR}/data)
|
||||||
if (INSTALL_BTEST_PCAPS)
|
if (INSTALL_BTEST_PCAPS)
|
||||||
install(DIRECTORY btest/Traces/ DESTINATION ${ZEEK_CONFIG_BTEST_TOOLS_DIR}/data/pcaps)
|
install(DIRECTORY btest/Traces/ DESTINATION ${ZEEK_CONFIG_BTEST_TOOLS_DIR}/data/pcaps)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
# The remainder is for backwards-compatability with existing Spicy zkg packages.
|
||||||
|
install(
|
||||||
|
CODE "execute_process( \
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E create_symlink \
|
||||||
|
${ZEEK_CONFIG_BTEST_TOOLS_DIR}/data \
|
||||||
|
${CMAKE_INSTALL_PREFIX}/share/zeek/tests \
|
||||||
|
)")
|
||||||
|
|
||||||
|
install(DIRECTORY scripts/spicy/ DESTINATION ${ZEEK_CONFIG_BTEST_TOOLS_DIR}/data/Scripts
|
||||||
|
USE_SOURCE_PERMISSIONS)
|
||||||
|
|
|
@ -91,8 +91,8 @@ scripts/base/init-bare.zeek
|
||||||
scripts/base/packet-protocols/gtpv1/__load__.zeek
|
scripts/base/packet-protocols/gtpv1/__load__.zeek
|
||||||
scripts/base/packet-protocols/gtpv1/main.zeek
|
scripts/base/packet-protocols/gtpv1/main.zeek
|
||||||
build/scripts/base/bif/plugins/Zeek_GTPv1.functions.bif.zeek
|
build/scripts/base/bif/plugins/Zeek_GTPv1.functions.bif.zeek
|
||||||
|
scripts/base/frameworks/spicy/init-bare.zeek
|
||||||
build/scripts/builtin-plugins/__preload__.zeek
|
build/scripts/builtin-plugins/__preload__.zeek
|
||||||
build/scripts/builtin-plugins/Zeek_Spicy/__preload__.zeek
|
|
||||||
scripts/base/init-frameworks-and-bifs.zeek
|
scripts/base/init-frameworks-and-bifs.zeek
|
||||||
scripts/base/frameworks/logging/__load__.zeek
|
scripts/base/frameworks/logging/__load__.zeek
|
||||||
scripts/base/frameworks/logging/main.zeek
|
scripts/base/frameworks/logging/main.zeek
|
||||||
|
@ -148,6 +148,7 @@ scripts/base/init-frameworks-and-bifs.zeek
|
||||||
build/scripts/base/bif/bloom-filter.bif.zeek
|
build/scripts/base/bif/bloom-filter.bif.zeek
|
||||||
build/scripts/base/bif/cardinality-counter.bif.zeek
|
build/scripts/base/bif/cardinality-counter.bif.zeek
|
||||||
build/scripts/base/bif/top-k.bif.zeek
|
build/scripts/base/bif/top-k.bif.zeek
|
||||||
|
build/scripts/base/bif/spicy.bif.zeek
|
||||||
build/scripts/base/bif/plugins/__load__.zeek
|
build/scripts/base/bif/plugins/__load__.zeek
|
||||||
build/scripts/base/bif/plugins/Zeek_BitTorrent.events.bif.zeek
|
build/scripts/base/bif/plugins/Zeek_BitTorrent.events.bif.zeek
|
||||||
build/scripts/base/bif/plugins/Zeek_ConnSize.events.bif.zeek
|
build/scripts/base/bif/plugins/Zeek_ConnSize.events.bif.zeek
|
||||||
|
@ -264,16 +265,12 @@ scripts/base/init-frameworks-and-bifs.zeek
|
||||||
build/scripts/base/bif/plugins/Zeek_AsciiWriter.ascii.bif.zeek
|
build/scripts/base/bif/plugins/Zeek_AsciiWriter.ascii.bif.zeek
|
||||||
build/scripts/base/bif/plugins/Zeek_NoneWriter.none.bif.zeek
|
build/scripts/base/bif/plugins/Zeek_NoneWriter.none.bif.zeek
|
||||||
build/scripts/base/bif/plugins/Zeek_SQLiteWriter.sqlite.bif.zeek
|
build/scripts/base/bif/plugins/Zeek_SQLiteWriter.sqlite.bif.zeek
|
||||||
build/scripts/base/bif/plugins/Zeek_Spicy.consts.bif.zeek
|
scripts/base/frameworks/spicy/init-framework.zeek
|
||||||
build/scripts/base/bif/plugins/Zeek_Spicy.events.bif.zeek
|
scripts/base/misc/version.zeek
|
||||||
build/scripts/base/bif/plugins/Zeek_Spicy.functions.bif.zeek
|
scripts/base/frameworks/reporter/__load__.zeek
|
||||||
|
scripts/base/frameworks/reporter/main.zeek
|
||||||
|
scripts/base/utils/strings.zeek
|
||||||
build/scripts/builtin-plugins/__load__.zeek
|
build/scripts/builtin-plugins/__load__.zeek
|
||||||
build/scripts/builtin-plugins/Zeek_Spicy/__load__.zeek
|
|
||||||
build/scripts/builtin-plugins/Zeek_Spicy/Zeek/Spicy/bare.zeek
|
|
||||||
scripts/base/misc/version.zeek
|
|
||||||
scripts/base/frameworks/reporter/__load__.zeek
|
|
||||||
scripts/base/frameworks/reporter/main.zeek
|
|
||||||
scripts/base/utils/strings.zeek
|
|
||||||
scripts/policy/misc/loaded-scripts.zeek
|
scripts/policy/misc/loaded-scripts.zeek
|
||||||
scripts/base/utils/paths.zeek
|
scripts/base/utils/paths.zeek
|
||||||
#close XXXX-XX-XX-XX-XX-XX
|
#close XXXX-XX-XX-XX-XX-XX
|
||||||
|
|
|
@ -91,8 +91,8 @@ scripts/base/init-bare.zeek
|
||||||
scripts/base/packet-protocols/gtpv1/__load__.zeek
|
scripts/base/packet-protocols/gtpv1/__load__.zeek
|
||||||
scripts/base/packet-protocols/gtpv1/main.zeek
|
scripts/base/packet-protocols/gtpv1/main.zeek
|
||||||
build/scripts/base/bif/plugins/Zeek_GTPv1.functions.bif.zeek
|
build/scripts/base/bif/plugins/Zeek_GTPv1.functions.bif.zeek
|
||||||
|
scripts/base/frameworks/spicy/init-bare.zeek
|
||||||
build/scripts/builtin-plugins/__preload__.zeek
|
build/scripts/builtin-plugins/__preload__.zeek
|
||||||
build/scripts/builtin-plugins/Zeek_Spicy/__preload__.zeek
|
|
||||||
scripts/base/init-frameworks-and-bifs.zeek
|
scripts/base/init-frameworks-and-bifs.zeek
|
||||||
scripts/base/frameworks/logging/__load__.zeek
|
scripts/base/frameworks/logging/__load__.zeek
|
||||||
scripts/base/frameworks/logging/main.zeek
|
scripts/base/frameworks/logging/main.zeek
|
||||||
|
@ -148,6 +148,7 @@ scripts/base/init-frameworks-and-bifs.zeek
|
||||||
build/scripts/base/bif/bloom-filter.bif.zeek
|
build/scripts/base/bif/bloom-filter.bif.zeek
|
||||||
build/scripts/base/bif/cardinality-counter.bif.zeek
|
build/scripts/base/bif/cardinality-counter.bif.zeek
|
||||||
build/scripts/base/bif/top-k.bif.zeek
|
build/scripts/base/bif/top-k.bif.zeek
|
||||||
|
build/scripts/base/bif/spicy.bif.zeek
|
||||||
build/scripts/base/bif/plugins/__load__.zeek
|
build/scripts/base/bif/plugins/__load__.zeek
|
||||||
build/scripts/base/bif/plugins/Zeek_BitTorrent.events.bif.zeek
|
build/scripts/base/bif/plugins/Zeek_BitTorrent.events.bif.zeek
|
||||||
build/scripts/base/bif/plugins/Zeek_ConnSize.events.bif.zeek
|
build/scripts/base/bif/plugins/Zeek_ConnSize.events.bif.zeek
|
||||||
|
@ -264,9 +265,11 @@ scripts/base/init-frameworks-and-bifs.zeek
|
||||||
build/scripts/base/bif/plugins/Zeek_AsciiWriter.ascii.bif.zeek
|
build/scripts/base/bif/plugins/Zeek_AsciiWriter.ascii.bif.zeek
|
||||||
build/scripts/base/bif/plugins/Zeek_NoneWriter.none.bif.zeek
|
build/scripts/base/bif/plugins/Zeek_NoneWriter.none.bif.zeek
|
||||||
build/scripts/base/bif/plugins/Zeek_SQLiteWriter.sqlite.bif.zeek
|
build/scripts/base/bif/plugins/Zeek_SQLiteWriter.sqlite.bif.zeek
|
||||||
build/scripts/base/bif/plugins/Zeek_Spicy.consts.bif.zeek
|
scripts/base/frameworks/spicy/init-framework.zeek
|
||||||
build/scripts/base/bif/plugins/Zeek_Spicy.events.bif.zeek
|
scripts/base/misc/version.zeek
|
||||||
build/scripts/base/bif/plugins/Zeek_Spicy.functions.bif.zeek
|
scripts/base/frameworks/reporter/__load__.zeek
|
||||||
|
scripts/base/frameworks/reporter/main.zeek
|
||||||
|
scripts/base/utils/strings.zeek
|
||||||
scripts/base/init-default.zeek
|
scripts/base/init-default.zeek
|
||||||
scripts/base/utils/active-http.zeek
|
scripts/base/utils/active-http.zeek
|
||||||
scripts/base/utils/exec.zeek
|
scripts/base/utils/exec.zeek
|
||||||
|
@ -274,8 +277,6 @@ scripts/base/init-default.zeek
|
||||||
scripts/base/utils/backtrace.zeek
|
scripts/base/utils/backtrace.zeek
|
||||||
scripts/base/utils/conn-ids.zeek
|
scripts/base/utils/conn-ids.zeek
|
||||||
scripts/base/utils/dir.zeek
|
scripts/base/utils/dir.zeek
|
||||||
scripts/base/frameworks/reporter/__load__.zeek
|
|
||||||
scripts/base/frameworks/reporter/main.zeek
|
|
||||||
scripts/base/utils/paths.zeek
|
scripts/base/utils/paths.zeek
|
||||||
scripts/base/utils/directions-and-hosts.zeek
|
scripts/base/utils/directions-and-hosts.zeek
|
||||||
scripts/base/utils/email.zeek
|
scripts/base/utils/email.zeek
|
||||||
|
@ -283,7 +284,6 @@ scripts/base/init-default.zeek
|
||||||
scripts/base/utils/geoip-distance.zeek
|
scripts/base/utils/geoip-distance.zeek
|
||||||
scripts/base/utils/numbers.zeek
|
scripts/base/utils/numbers.zeek
|
||||||
scripts/base/utils/queue.zeek
|
scripts/base/utils/queue.zeek
|
||||||
scripts/base/utils/strings.zeek
|
|
||||||
scripts/base/utils/thresholds.zeek
|
scripts/base/utils/thresholds.zeek
|
||||||
scripts/base/utils/time.zeek
|
scripts/base/utils/time.zeek
|
||||||
scripts/base/utils/urls.zeek
|
scripts/base/utils/urls.zeek
|
||||||
|
@ -347,7 +347,8 @@ scripts/base/init-default.zeek
|
||||||
scripts/base/frameworks/netcontrol/non-cluster.zeek
|
scripts/base/frameworks/netcontrol/non-cluster.zeek
|
||||||
scripts/base/frameworks/telemetry/__load__.zeek
|
scripts/base/frameworks/telemetry/__load__.zeek
|
||||||
scripts/base/frameworks/telemetry/main.zeek
|
scripts/base/frameworks/telemetry/main.zeek
|
||||||
scripts/base/misc/version.zeek
|
scripts/base/frameworks/spicy/__load__.zeek
|
||||||
|
scripts/base/frameworks/spicy/main.zeek
|
||||||
scripts/base/protocols/conn/__load__.zeek
|
scripts/base/protocols/conn/__load__.zeek
|
||||||
scripts/base/protocols/conn/main.zeek
|
scripts/base/protocols/conn/main.zeek
|
||||||
scripts/base/protocols/conn/contents.zeek
|
scripts/base/protocols/conn/contents.zeek
|
||||||
|
@ -463,8 +464,5 @@ scripts/base/init-default.zeek
|
||||||
scripts/base/misc/find-filtered-trace.zeek
|
scripts/base/misc/find-filtered-trace.zeek
|
||||||
build/scripts/base/misc/installation.zeek
|
build/scripts/base/misc/installation.zeek
|
||||||
build/scripts/builtin-plugins/__load__.zeek
|
build/scripts/builtin-plugins/__load__.zeek
|
||||||
build/scripts/builtin-plugins/Zeek_Spicy/__load__.zeek
|
|
||||||
build/scripts/builtin-plugins/Zeek_Spicy/Zeek/Spicy/bare.zeek
|
|
||||||
build/scripts/builtin-plugins/Zeek_Spicy/Zeek/Spicy/default.zeek
|
|
||||||
scripts/policy/misc/loaded-scripts.zeek
|
scripts/policy/misc/loaded-scripts.zeek
|
||||||
#close XXXX-XX-XX-XX-XX-XX
|
#close XXXX-XX-XX-XX-XX-XX
|
||||||
|
|
|
@ -790,7 +790,6 @@
|
||||||
0.000000 MetaHookPost CallFunction(Version::parse, ..., ...) -> <no result>
|
0.000000 MetaHookPost CallFunction(Version::parse, ..., ...) -> <no result>
|
||||||
0.000000 MetaHookPost CallFunction(__init_primary_bifs, <null>, ()) -> <no result>
|
0.000000 MetaHookPost CallFunction(__init_primary_bifs, <null>, ()) -> <no result>
|
||||||
0.000000 MetaHookPost CallFunction(__init_secondary_bifs, <null>, ()) -> <no result>
|
0.000000 MetaHookPost CallFunction(__init_secondary_bifs, <null>, ()) -> <no result>
|
||||||
0.000000 MetaHookPost CallFunction(bare_mode, <null>, ()) -> <no result>
|
|
||||||
0.000000 MetaHookPost CallFunction(cat, ..., ...) -> <no result>
|
0.000000 MetaHookPost CallFunction(cat, ..., ...) -> <no result>
|
||||||
0.000000 MetaHookPost CallFunction(current_time, <frame>, ()) -> <no result>
|
0.000000 MetaHookPost CallFunction(current_time, <frame>, ()) -> <no result>
|
||||||
0.000000 MetaHookPost CallFunction(disable_event_group, <frame>, (Analyzer::Logging::include_confirmations)) -> <no result>
|
0.000000 MetaHookPost CallFunction(disable_event_group, <frame>, (Analyzer::Logging::include_confirmations)) -> <no result>
|
||||||
|
@ -802,6 +801,7 @@
|
||||||
0.000000 MetaHookPost CallFunction(gsub, ..., ...) -> <no result>
|
0.000000 MetaHookPost CallFunction(gsub, ..., ...) -> <no result>
|
||||||
0.000000 MetaHookPost CallFunction(has_event_group, <frame>, (Analyzer::Logging)) -> <no result>
|
0.000000 MetaHookPost CallFunction(has_event_group, <frame>, (Analyzer::Logging)) -> <no result>
|
||||||
0.000000 MetaHookPost CallFunction(has_module_events, <frame>, (Analyzer::Logging)) -> <no result>
|
0.000000 MetaHookPost CallFunction(has_module_events, <frame>, (Analyzer::Logging)) -> <no result>
|
||||||
|
0.000000 MetaHookPost CallFunction(have_spicy, <null>, ()) -> <no result>
|
||||||
0.000000 MetaHookPost CallFunction(have_spicy_analyzers, <null>, ()) -> <no result>
|
0.000000 MetaHookPost CallFunction(have_spicy_analyzers, <null>, ()) -> <no result>
|
||||||
0.000000 MetaHookPost CallFunction(is_file_analyzer, <frame>, (AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS)) -> <no result>
|
0.000000 MetaHookPost CallFunction(is_file_analyzer, <frame>, (AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS)) -> <no result>
|
||||||
0.000000 MetaHookPost CallFunction(is_packet_analyzer, <frame>, (AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS)) -> <no result>
|
0.000000 MetaHookPost CallFunction(is_packet_analyzer, <frame>, (AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS)) -> <no result>
|
||||||
|
@ -938,9 +938,6 @@
|
||||||
0.000000 MetaHookPost LoadFile(0, ./Zeek_SSL.events.bif.zeek, <...>/Zeek_SSL.events.bif.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, ./Zeek_SSL.events.bif.zeek, <...>/Zeek_SSL.events.bif.zeek) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, ./Zeek_SSL.functions.bif.zeek, <...>/Zeek_SSL.functions.bif.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, ./Zeek_SSL.functions.bif.zeek, <...>/Zeek_SSL.functions.bif.zeek) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, ./Zeek_SSL.types.bif.zeek, <...>/Zeek_SSL.types.bif.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, ./Zeek_SSL.types.bif.zeek, <...>/Zeek_SSL.types.bif.zeek) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, ./Zeek_Spicy.consts.bif.zeek, <...>/Zeek_Spicy.consts.bif.zeek) -> -1
|
|
||||||
0.000000 MetaHookPost LoadFile(0, ./Zeek_Spicy.events.bif.zeek, <...>/Zeek_Spicy.events.bif.zeek) -> -1
|
|
||||||
0.000000 MetaHookPost LoadFile(0, ./Zeek_Spicy.functions.bif.zeek, <...>/Zeek_Spicy.functions.bif.zeek) -> -1
|
|
||||||
0.000000 MetaHookPost LoadFile(0, ./Zeek_TCP.events.bif.zeek, <...>/Zeek_TCP.events.bif.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, ./Zeek_TCP.events.bif.zeek, <...>/Zeek_TCP.events.bif.zeek) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, ./Zeek_TCP.functions.bif.zeek, <...>/Zeek_TCP.functions.bif.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, ./Zeek_TCP.functions.bif.zeek, <...>/Zeek_TCP.functions.bif.zeek) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, ./Zeek_TCP.types.bif.zeek, <...>/Zeek_TCP.types.bif.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, ./Zeek_TCP.types.bif.zeek, <...>/Zeek_TCP.types.bif.zeek) -> -1
|
||||||
|
@ -1024,6 +1021,7 @@
|
||||||
0.000000 MetaHookPost LoadFile(0, ./smb1-main, <...>/smb1-main.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, ./smb1-main, <...>/smb1-main.zeek) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, ./smb2-main, <...>/smb2-main.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, ./smb2-main, <...>/smb2-main.zeek) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, ./spicy-events, <...>/spicy-events.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, ./spicy-events, <...>/spicy-events.zeek) -> -1
|
||||||
|
0.000000 MetaHookPost LoadFile(0, ./spicy.bif.zeek, <...>/spicy.bif.zeek) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, ./stats.bif.zeek, <...>/stats.bif.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, ./stats.bif.zeek, <...>/stats.bif.zeek) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, ./std-dev, <...>/std-dev.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, ./std-dev, <...>/std-dev.zeek) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, ./store, <...>/store.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, ./store, <...>/store.zeek) -> -1
|
||||||
|
@ -1058,10 +1056,6 @@
|
||||||
0.000000 MetaHookPost LoadFile(0, <...>/__load__.zeek, <...>/__load__.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, <...>/__load__.zeek, <...>/__load__.zeek) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, <...>/__preload__.zeek, <...>/__preload__.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, <...>/__preload__.zeek, <...>/__preload__.zeek) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, <...>/hooks.zeek, <...>/hooks.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, <...>/hooks.zeek, <...>/hooks.zeek) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, Zeek<...>/bare.zeek, <...>/bare.zeek) -> -1
|
|
||||||
0.000000 MetaHookPost LoadFile(0, Zeek<...>/default.zeek, <...>/default.zeek) -> -1
|
|
||||||
0.000000 MetaHookPost LoadFile(0, Zeek_Spicy/__load__.zeek, <...>/__load__.zeek) -> -1
|
|
||||||
0.000000 MetaHookPost LoadFile(0, Zeek_Spicy/__preload__.zeek, <...>/__preload__.zeek) -> -1
|
|
||||||
0.000000 MetaHookPost LoadFile(0, base/bif, <...>/bif) -> -1
|
0.000000 MetaHookPost LoadFile(0, base/bif, <...>/bif) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, base/init-default.zeek, <...>/init-default.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, base/init-default.zeek, <...>/init-default.zeek) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, base/init-frameworks-and-bifs.zeek, <...>/init-frameworks-and-bifs.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, base/init-frameworks-and-bifs.zeek, <...>/init-frameworks-and-bifs.zeek) -> -1
|
||||||
|
@ -1119,6 +1113,8 @@
|
||||||
0.000000 MetaHookPost LoadFile(0, base<...>/ieee802_11, <...>/ieee802_11) -> -1
|
0.000000 MetaHookPost LoadFile(0, base<...>/ieee802_11, <...>/ieee802_11) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, base<...>/ieee802_11_radio, <...>/ieee802_11_radio) -> -1
|
0.000000 MetaHookPost LoadFile(0, base<...>/ieee802_11_radio, <...>/ieee802_11_radio) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, base<...>/imap, <...>/imap) -> -1
|
0.000000 MetaHookPost LoadFile(0, base<...>/imap, <...>/imap) -> -1
|
||||||
|
0.000000 MetaHookPost LoadFile(0, base<...>/init-bare, <...>/init-bare.zeek) -> -1
|
||||||
|
0.000000 MetaHookPost LoadFile(0, base<...>/init-framework, <...>/init-framework.zeek) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, base<...>/input, <...>/input) -> -1
|
0.000000 MetaHookPost LoadFile(0, base<...>/input, <...>/input) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, base<...>/input.bif, <...>/input.bif.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, base<...>/input.bif, <...>/input.bif.zeek) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, base<...>/installation, <...>/installation.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, base<...>/installation, <...>/installation.zeek) -> -1
|
||||||
|
@ -1177,6 +1173,7 @@
|
||||||
0.000000 MetaHookPost LoadFile(0, base<...>/snmp, <...>/snmp) -> -1
|
0.000000 MetaHookPost LoadFile(0, base<...>/snmp, <...>/snmp) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, base<...>/socks, <...>/socks) -> -1
|
0.000000 MetaHookPost LoadFile(0, base<...>/socks, <...>/socks) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, base<...>/software, <...>/software) -> -1
|
0.000000 MetaHookPost LoadFile(0, base<...>/software, <...>/software) -> -1
|
||||||
|
0.000000 MetaHookPost LoadFile(0, base<...>/spicy, <...>/spicy) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, base<...>/ssh, <...>/ssh) -> -1
|
0.000000 MetaHookPost LoadFile(0, base<...>/ssh, <...>/ssh) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, base<...>/ssl, <...>/ssl) -> -1
|
0.000000 MetaHookPost LoadFile(0, base<...>/ssl, <...>/ssl) -> -1
|
||||||
0.000000 MetaHookPost LoadFile(0, base<...>/stats.bif, <...>/stats.bif.zeek) -> -1
|
0.000000 MetaHookPost LoadFile(0, base<...>/stats.bif, <...>/stats.bif.zeek) -> -1
|
||||||
|
@ -1331,9 +1328,6 @@
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_SSL.events.bif.zeek, <...>/Zeek_SSL.events.bif.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_SSL.events.bif.zeek, <...>/Zeek_SSL.events.bif.zeek) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_SSL.functions.bif.zeek, <...>/Zeek_SSL.functions.bif.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_SSL.functions.bif.zeek, <...>/Zeek_SSL.functions.bif.zeek) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_SSL.types.bif.zeek, <...>/Zeek_SSL.types.bif.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_SSL.types.bif.zeek, <...>/Zeek_SSL.types.bif.zeek) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_Spicy.consts.bif.zeek, <...>/Zeek_Spicy.consts.bif.zeek) -> (-1, <no content>)
|
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_Spicy.events.bif.zeek, <...>/Zeek_Spicy.events.bif.zeek) -> (-1, <no content>)
|
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_Spicy.functions.bif.zeek, <...>/Zeek_Spicy.functions.bif.zeek) -> (-1, <no content>)
|
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_TCP.events.bif.zeek, <...>/Zeek_TCP.events.bif.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_TCP.events.bif.zeek, <...>/Zeek_TCP.events.bif.zeek) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_TCP.functions.bif.zeek, <...>/Zeek_TCP.functions.bif.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_TCP.functions.bif.zeek, <...>/Zeek_TCP.functions.bif.zeek) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_TCP.types.bif.zeek, <...>/Zeek_TCP.types.bif.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_TCP.types.bif.zeek, <...>/Zeek_TCP.types.bif.zeek) -> (-1, <no content>)
|
||||||
|
@ -1417,6 +1411,7 @@
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, ./smb1-main, <...>/smb1-main.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, ./smb1-main, <...>/smb1-main.zeek) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, ./smb2-main, <...>/smb2-main.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, ./smb2-main, <...>/smb2-main.zeek) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, ./spicy-events, <...>/spicy-events.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, ./spicy-events, <...>/spicy-events.zeek) -> (-1, <no content>)
|
||||||
|
0.000000 MetaHookPost LoadFileExtended(0, ./spicy.bif.zeek, <...>/spicy.bif.zeek) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, ./stats.bif.zeek, <...>/stats.bif.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, ./stats.bif.zeek, <...>/stats.bif.zeek) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, ./std-dev, <...>/std-dev.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, ./std-dev, <...>/std-dev.zeek) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, ./store, <...>/store.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, ./store, <...>/store.zeek) -> (-1, <no content>)
|
||||||
|
@ -1451,10 +1446,6 @@
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, <...>/__load__.zeek, <...>/__load__.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, <...>/__load__.zeek, <...>/__load__.zeek) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, <...>/__preload__.zeek, <...>/__preload__.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, <...>/__preload__.zeek, <...>/__preload__.zeek) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, <...>/hooks.zeek, <...>/hooks.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, <...>/hooks.zeek, <...>/hooks.zeek) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, Zeek<...>/bare.zeek, <...>/bare.zeek) -> (-1, <no content>)
|
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, Zeek<...>/default.zeek, <...>/default.zeek) -> (-1, <no content>)
|
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, Zeek_Spicy/__load__.zeek, <...>/__load__.zeek) -> (-1, <no content>)
|
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, Zeek_Spicy/__preload__.zeek, <...>/__preload__.zeek) -> (-1, <no content>)
|
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, base/bif, <...>/bif) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, base/bif, <...>/bif) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, base/init-default.zeek, <...>/init-default.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, base/init-default.zeek, <...>/init-default.zeek) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, base/init-frameworks-and-bifs.zeek, <...>/init-frameworks-and-bifs.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, base/init-frameworks-and-bifs.zeek, <...>/init-frameworks-and-bifs.zeek) -> (-1, <no content>)
|
||||||
|
@ -1512,6 +1503,8 @@
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, base<...>/ieee802_11, <...>/ieee802_11) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, base<...>/ieee802_11, <...>/ieee802_11) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, base<...>/ieee802_11_radio, <...>/ieee802_11_radio) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, base<...>/ieee802_11_radio, <...>/ieee802_11_radio) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, base<...>/imap, <...>/imap) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, base<...>/imap, <...>/imap) -> (-1, <no content>)
|
||||||
|
0.000000 MetaHookPost LoadFileExtended(0, base<...>/init-bare, <...>/init-bare.zeek) -> (-1, <no content>)
|
||||||
|
0.000000 MetaHookPost LoadFileExtended(0, base<...>/init-framework, <...>/init-framework.zeek) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, base<...>/input, <...>/input) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, base<...>/input, <...>/input) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, base<...>/input.bif, <...>/input.bif.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, base<...>/input.bif, <...>/input.bif.zeek) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, base<...>/installation, <...>/installation.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, base<...>/installation, <...>/installation.zeek) -> (-1, <no content>)
|
||||||
|
@ -1570,6 +1563,7 @@
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, base<...>/snmp, <...>/snmp) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, base<...>/snmp, <...>/snmp) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, base<...>/socks, <...>/socks) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, base<...>/socks, <...>/socks) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, base<...>/software, <...>/software) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, base<...>/software, <...>/software) -> (-1, <no content>)
|
||||||
|
0.000000 MetaHookPost LoadFileExtended(0, base<...>/spicy, <...>/spicy) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, base<...>/ssh, <...>/ssh) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, base<...>/ssh, <...>/ssh) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, base<...>/ssl, <...>/ssl) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, base<...>/ssl, <...>/ssl) -> (-1, <no content>)
|
||||||
0.000000 MetaHookPost LoadFileExtended(0, base<...>/stats.bif, <...>/stats.bif.zeek) -> (-1, <no content>)
|
0.000000 MetaHookPost LoadFileExtended(0, base<...>/stats.bif, <...>/stats.bif.zeek) -> (-1, <no content>)
|
||||||
|
@ -2410,7 +2404,6 @@
|
||||||
0.000000 MetaHookPre CallFunction(Version::parse, ..., ...)
|
0.000000 MetaHookPre CallFunction(Version::parse, ..., ...)
|
||||||
0.000000 MetaHookPre CallFunction(__init_primary_bifs, <null>, ())
|
0.000000 MetaHookPre CallFunction(__init_primary_bifs, <null>, ())
|
||||||
0.000000 MetaHookPre CallFunction(__init_secondary_bifs, <null>, ())
|
0.000000 MetaHookPre CallFunction(__init_secondary_bifs, <null>, ())
|
||||||
0.000000 MetaHookPre CallFunction(bare_mode, <null>, ())
|
|
||||||
0.000000 MetaHookPre CallFunction(cat, ..., ...)
|
0.000000 MetaHookPre CallFunction(cat, ..., ...)
|
||||||
0.000000 MetaHookPre CallFunction(current_time, <frame>, ())
|
0.000000 MetaHookPre CallFunction(current_time, <frame>, ())
|
||||||
0.000000 MetaHookPre CallFunction(disable_event_group, <frame>, (Analyzer::Logging::include_confirmations))
|
0.000000 MetaHookPre CallFunction(disable_event_group, <frame>, (Analyzer::Logging::include_confirmations))
|
||||||
|
@ -2422,6 +2415,7 @@
|
||||||
0.000000 MetaHookPre CallFunction(gsub, ..., ...)
|
0.000000 MetaHookPre CallFunction(gsub, ..., ...)
|
||||||
0.000000 MetaHookPre CallFunction(has_event_group, <frame>, (Analyzer::Logging))
|
0.000000 MetaHookPre CallFunction(has_event_group, <frame>, (Analyzer::Logging))
|
||||||
0.000000 MetaHookPre CallFunction(has_module_events, <frame>, (Analyzer::Logging))
|
0.000000 MetaHookPre CallFunction(has_module_events, <frame>, (Analyzer::Logging))
|
||||||
|
0.000000 MetaHookPre CallFunction(have_spicy, <null>, ())
|
||||||
0.000000 MetaHookPre CallFunction(have_spicy_analyzers, <null>, ())
|
0.000000 MetaHookPre CallFunction(have_spicy_analyzers, <null>, ())
|
||||||
0.000000 MetaHookPre CallFunction(is_file_analyzer, <frame>, (AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS))
|
0.000000 MetaHookPre CallFunction(is_file_analyzer, <frame>, (AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS))
|
||||||
0.000000 MetaHookPre CallFunction(is_packet_analyzer, <frame>, (AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS))
|
0.000000 MetaHookPre CallFunction(is_packet_analyzer, <frame>, (AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS))
|
||||||
|
@ -2558,9 +2552,6 @@
|
||||||
0.000000 MetaHookPre LoadFile(0, ./Zeek_SSL.events.bif.zeek, <...>/Zeek_SSL.events.bif.zeek)
|
0.000000 MetaHookPre LoadFile(0, ./Zeek_SSL.events.bif.zeek, <...>/Zeek_SSL.events.bif.zeek)
|
||||||
0.000000 MetaHookPre LoadFile(0, ./Zeek_SSL.functions.bif.zeek, <...>/Zeek_SSL.functions.bif.zeek)
|
0.000000 MetaHookPre LoadFile(0, ./Zeek_SSL.functions.bif.zeek, <...>/Zeek_SSL.functions.bif.zeek)
|
||||||
0.000000 MetaHookPre LoadFile(0, ./Zeek_SSL.types.bif.zeek, <...>/Zeek_SSL.types.bif.zeek)
|
0.000000 MetaHookPre LoadFile(0, ./Zeek_SSL.types.bif.zeek, <...>/Zeek_SSL.types.bif.zeek)
|
||||||
0.000000 MetaHookPre LoadFile(0, ./Zeek_Spicy.consts.bif.zeek, <...>/Zeek_Spicy.consts.bif.zeek)
|
|
||||||
0.000000 MetaHookPre LoadFile(0, ./Zeek_Spicy.events.bif.zeek, <...>/Zeek_Spicy.events.bif.zeek)
|
|
||||||
0.000000 MetaHookPre LoadFile(0, ./Zeek_Spicy.functions.bif.zeek, <...>/Zeek_Spicy.functions.bif.zeek)
|
|
||||||
0.000000 MetaHookPre LoadFile(0, ./Zeek_TCP.events.bif.zeek, <...>/Zeek_TCP.events.bif.zeek)
|
0.000000 MetaHookPre LoadFile(0, ./Zeek_TCP.events.bif.zeek, <...>/Zeek_TCP.events.bif.zeek)
|
||||||
0.000000 MetaHookPre LoadFile(0, ./Zeek_TCP.functions.bif.zeek, <...>/Zeek_TCP.functions.bif.zeek)
|
0.000000 MetaHookPre LoadFile(0, ./Zeek_TCP.functions.bif.zeek, <...>/Zeek_TCP.functions.bif.zeek)
|
||||||
0.000000 MetaHookPre LoadFile(0, ./Zeek_TCP.types.bif.zeek, <...>/Zeek_TCP.types.bif.zeek)
|
0.000000 MetaHookPre LoadFile(0, ./Zeek_TCP.types.bif.zeek, <...>/Zeek_TCP.types.bif.zeek)
|
||||||
|
@ -2644,6 +2635,7 @@
|
||||||
0.000000 MetaHookPre LoadFile(0, ./smb1-main, <...>/smb1-main.zeek)
|
0.000000 MetaHookPre LoadFile(0, ./smb1-main, <...>/smb1-main.zeek)
|
||||||
0.000000 MetaHookPre LoadFile(0, ./smb2-main, <...>/smb2-main.zeek)
|
0.000000 MetaHookPre LoadFile(0, ./smb2-main, <...>/smb2-main.zeek)
|
||||||
0.000000 MetaHookPre LoadFile(0, ./spicy-events, <...>/spicy-events.zeek)
|
0.000000 MetaHookPre LoadFile(0, ./spicy-events, <...>/spicy-events.zeek)
|
||||||
|
0.000000 MetaHookPre LoadFile(0, ./spicy.bif.zeek, <...>/spicy.bif.zeek)
|
||||||
0.000000 MetaHookPre LoadFile(0, ./stats.bif.zeek, <...>/stats.bif.zeek)
|
0.000000 MetaHookPre LoadFile(0, ./stats.bif.zeek, <...>/stats.bif.zeek)
|
||||||
0.000000 MetaHookPre LoadFile(0, ./std-dev, <...>/std-dev.zeek)
|
0.000000 MetaHookPre LoadFile(0, ./std-dev, <...>/std-dev.zeek)
|
||||||
0.000000 MetaHookPre LoadFile(0, ./store, <...>/store.zeek)
|
0.000000 MetaHookPre LoadFile(0, ./store, <...>/store.zeek)
|
||||||
|
@ -2678,10 +2670,6 @@
|
||||||
0.000000 MetaHookPre LoadFile(0, <...>/__load__.zeek, <...>/__load__.zeek)
|
0.000000 MetaHookPre LoadFile(0, <...>/__load__.zeek, <...>/__load__.zeek)
|
||||||
0.000000 MetaHookPre LoadFile(0, <...>/__preload__.zeek, <...>/__preload__.zeek)
|
0.000000 MetaHookPre LoadFile(0, <...>/__preload__.zeek, <...>/__preload__.zeek)
|
||||||
0.000000 MetaHookPre LoadFile(0, <...>/hooks.zeek, <...>/hooks.zeek)
|
0.000000 MetaHookPre LoadFile(0, <...>/hooks.zeek, <...>/hooks.zeek)
|
||||||
0.000000 MetaHookPre LoadFile(0, Zeek<...>/bare.zeek, <...>/bare.zeek)
|
|
||||||
0.000000 MetaHookPre LoadFile(0, Zeek<...>/default.zeek, <...>/default.zeek)
|
|
||||||
0.000000 MetaHookPre LoadFile(0, Zeek_Spicy/__load__.zeek, <...>/__load__.zeek)
|
|
||||||
0.000000 MetaHookPre LoadFile(0, Zeek_Spicy/__preload__.zeek, <...>/__preload__.zeek)
|
|
||||||
0.000000 MetaHookPre LoadFile(0, base/bif, <...>/bif)
|
0.000000 MetaHookPre LoadFile(0, base/bif, <...>/bif)
|
||||||
0.000000 MetaHookPre LoadFile(0, base/init-default.zeek, <...>/init-default.zeek)
|
0.000000 MetaHookPre LoadFile(0, base/init-default.zeek, <...>/init-default.zeek)
|
||||||
0.000000 MetaHookPre LoadFile(0, base/init-frameworks-and-bifs.zeek, <...>/init-frameworks-and-bifs.zeek)
|
0.000000 MetaHookPre LoadFile(0, base/init-frameworks-and-bifs.zeek, <...>/init-frameworks-and-bifs.zeek)
|
||||||
|
@ -2739,6 +2727,8 @@
|
||||||
0.000000 MetaHookPre LoadFile(0, base<...>/ieee802_11, <...>/ieee802_11)
|
0.000000 MetaHookPre LoadFile(0, base<...>/ieee802_11, <...>/ieee802_11)
|
||||||
0.000000 MetaHookPre LoadFile(0, base<...>/ieee802_11_radio, <...>/ieee802_11_radio)
|
0.000000 MetaHookPre LoadFile(0, base<...>/ieee802_11_radio, <...>/ieee802_11_radio)
|
||||||
0.000000 MetaHookPre LoadFile(0, base<...>/imap, <...>/imap)
|
0.000000 MetaHookPre LoadFile(0, base<...>/imap, <...>/imap)
|
||||||
|
0.000000 MetaHookPre LoadFile(0, base<...>/init-bare, <...>/init-bare.zeek)
|
||||||
|
0.000000 MetaHookPre LoadFile(0, base<...>/init-framework, <...>/init-framework.zeek)
|
||||||
0.000000 MetaHookPre LoadFile(0, base<...>/input, <...>/input)
|
0.000000 MetaHookPre LoadFile(0, base<...>/input, <...>/input)
|
||||||
0.000000 MetaHookPre LoadFile(0, base<...>/input.bif, <...>/input.bif.zeek)
|
0.000000 MetaHookPre LoadFile(0, base<...>/input.bif, <...>/input.bif.zeek)
|
||||||
0.000000 MetaHookPre LoadFile(0, base<...>/installation, <...>/installation.zeek)
|
0.000000 MetaHookPre LoadFile(0, base<...>/installation, <...>/installation.zeek)
|
||||||
|
@ -2797,6 +2787,7 @@
|
||||||
0.000000 MetaHookPre LoadFile(0, base<...>/snmp, <...>/snmp)
|
0.000000 MetaHookPre LoadFile(0, base<...>/snmp, <...>/snmp)
|
||||||
0.000000 MetaHookPre LoadFile(0, base<...>/socks, <...>/socks)
|
0.000000 MetaHookPre LoadFile(0, base<...>/socks, <...>/socks)
|
||||||
0.000000 MetaHookPre LoadFile(0, base<...>/software, <...>/software)
|
0.000000 MetaHookPre LoadFile(0, base<...>/software, <...>/software)
|
||||||
|
0.000000 MetaHookPre LoadFile(0, base<...>/spicy, <...>/spicy)
|
||||||
0.000000 MetaHookPre LoadFile(0, base<...>/ssh, <...>/ssh)
|
0.000000 MetaHookPre LoadFile(0, base<...>/ssh, <...>/ssh)
|
||||||
0.000000 MetaHookPre LoadFile(0, base<...>/ssl, <...>/ssl)
|
0.000000 MetaHookPre LoadFile(0, base<...>/ssl, <...>/ssl)
|
||||||
0.000000 MetaHookPre LoadFile(0, base<...>/stats.bif, <...>/stats.bif.zeek)
|
0.000000 MetaHookPre LoadFile(0, base<...>/stats.bif, <...>/stats.bif.zeek)
|
||||||
|
@ -2951,9 +2942,6 @@
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_SSL.events.bif.zeek, <...>/Zeek_SSL.events.bif.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_SSL.events.bif.zeek, <...>/Zeek_SSL.events.bif.zeek)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_SSL.functions.bif.zeek, <...>/Zeek_SSL.functions.bif.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_SSL.functions.bif.zeek, <...>/Zeek_SSL.functions.bif.zeek)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_SSL.types.bif.zeek, <...>/Zeek_SSL.types.bif.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_SSL.types.bif.zeek, <...>/Zeek_SSL.types.bif.zeek)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_Spicy.consts.bif.zeek, <...>/Zeek_Spicy.consts.bif.zeek)
|
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_Spicy.events.bif.zeek, <...>/Zeek_Spicy.events.bif.zeek)
|
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_Spicy.functions.bif.zeek, <...>/Zeek_Spicy.functions.bif.zeek)
|
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_TCP.events.bif.zeek, <...>/Zeek_TCP.events.bif.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_TCP.events.bif.zeek, <...>/Zeek_TCP.events.bif.zeek)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_TCP.functions.bif.zeek, <...>/Zeek_TCP.functions.bif.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_TCP.functions.bif.zeek, <...>/Zeek_TCP.functions.bif.zeek)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_TCP.types.bif.zeek, <...>/Zeek_TCP.types.bif.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_TCP.types.bif.zeek, <...>/Zeek_TCP.types.bif.zeek)
|
||||||
|
@ -3037,6 +3025,7 @@
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, ./smb1-main, <...>/smb1-main.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, ./smb1-main, <...>/smb1-main.zeek)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, ./smb2-main, <...>/smb2-main.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, ./smb2-main, <...>/smb2-main.zeek)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, ./spicy-events, <...>/spicy-events.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, ./spicy-events, <...>/spicy-events.zeek)
|
||||||
|
0.000000 MetaHookPre LoadFileExtended(0, ./spicy.bif.zeek, <...>/spicy.bif.zeek)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, ./stats.bif.zeek, <...>/stats.bif.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, ./stats.bif.zeek, <...>/stats.bif.zeek)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, ./std-dev, <...>/std-dev.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, ./std-dev, <...>/std-dev.zeek)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, ./store, <...>/store.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, ./store, <...>/store.zeek)
|
||||||
|
@ -3071,10 +3060,6 @@
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, <...>/__load__.zeek, <...>/__load__.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, <...>/__load__.zeek, <...>/__load__.zeek)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, <...>/__preload__.zeek, <...>/__preload__.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, <...>/__preload__.zeek, <...>/__preload__.zeek)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, <...>/hooks.zeek, <...>/hooks.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, <...>/hooks.zeek, <...>/hooks.zeek)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, Zeek<...>/bare.zeek, <...>/bare.zeek)
|
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, Zeek<...>/default.zeek, <...>/default.zeek)
|
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, Zeek_Spicy/__load__.zeek, <...>/__load__.zeek)
|
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, Zeek_Spicy/__preload__.zeek, <...>/__preload__.zeek)
|
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, base/bif, <...>/bif)
|
0.000000 MetaHookPre LoadFileExtended(0, base/bif, <...>/bif)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, base/init-default.zeek, <...>/init-default.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, base/init-default.zeek, <...>/init-default.zeek)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, base/init-frameworks-and-bifs.zeek, <...>/init-frameworks-and-bifs.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, base/init-frameworks-and-bifs.zeek, <...>/init-frameworks-and-bifs.zeek)
|
||||||
|
@ -3132,6 +3117,8 @@
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, base<...>/ieee802_11, <...>/ieee802_11)
|
0.000000 MetaHookPre LoadFileExtended(0, base<...>/ieee802_11, <...>/ieee802_11)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, base<...>/ieee802_11_radio, <...>/ieee802_11_radio)
|
0.000000 MetaHookPre LoadFileExtended(0, base<...>/ieee802_11_radio, <...>/ieee802_11_radio)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, base<...>/imap, <...>/imap)
|
0.000000 MetaHookPre LoadFileExtended(0, base<...>/imap, <...>/imap)
|
||||||
|
0.000000 MetaHookPre LoadFileExtended(0, base<...>/init-bare, <...>/init-bare.zeek)
|
||||||
|
0.000000 MetaHookPre LoadFileExtended(0, base<...>/init-framework, <...>/init-framework.zeek)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, base<...>/input, <...>/input)
|
0.000000 MetaHookPre LoadFileExtended(0, base<...>/input, <...>/input)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, base<...>/input.bif, <...>/input.bif.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, base<...>/input.bif, <...>/input.bif.zeek)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, base<...>/installation, <...>/installation.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, base<...>/installation, <...>/installation.zeek)
|
||||||
|
@ -3190,6 +3177,7 @@
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, base<...>/snmp, <...>/snmp)
|
0.000000 MetaHookPre LoadFileExtended(0, base<...>/snmp, <...>/snmp)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, base<...>/socks, <...>/socks)
|
0.000000 MetaHookPre LoadFileExtended(0, base<...>/socks, <...>/socks)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, base<...>/software, <...>/software)
|
0.000000 MetaHookPre LoadFileExtended(0, base<...>/software, <...>/software)
|
||||||
|
0.000000 MetaHookPre LoadFileExtended(0, base<...>/spicy, <...>/spicy)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, base<...>/ssh, <...>/ssh)
|
0.000000 MetaHookPre LoadFileExtended(0, base<...>/ssh, <...>/ssh)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, base<...>/ssl, <...>/ssl)
|
0.000000 MetaHookPre LoadFileExtended(0, base<...>/ssl, <...>/ssl)
|
||||||
0.000000 MetaHookPre LoadFileExtended(0, base<...>/stats.bif, <...>/stats.bif.zeek)
|
0.000000 MetaHookPre LoadFileExtended(0, base<...>/stats.bif, <...>/stats.bif.zeek)
|
||||||
|
@ -4029,7 +4017,6 @@
|
||||||
0.000000 | HookCallFunction Version::parse(...)
|
0.000000 | HookCallFunction Version::parse(...)
|
||||||
0.000000 | HookCallFunction __init_primary_bifs()
|
0.000000 | HookCallFunction __init_primary_bifs()
|
||||||
0.000000 | HookCallFunction __init_secondary_bifs()
|
0.000000 | HookCallFunction __init_secondary_bifs()
|
||||||
0.000000 | HookCallFunction bare_mode()
|
|
||||||
0.000000 | HookCallFunction cat(...)
|
0.000000 | HookCallFunction cat(...)
|
||||||
0.000000 | HookCallFunction current_time()
|
0.000000 | HookCallFunction current_time()
|
||||||
0.000000 | HookCallFunction disable_event_group(Analyzer::Logging::include_confirmations)
|
0.000000 | HookCallFunction disable_event_group(Analyzer::Logging::include_confirmations)
|
||||||
|
@ -4041,6 +4028,7 @@
|
||||||
0.000000 | HookCallFunction gsub(...)
|
0.000000 | HookCallFunction gsub(...)
|
||||||
0.000000 | HookCallFunction has_event_group(Analyzer::Logging)
|
0.000000 | HookCallFunction has_event_group(Analyzer::Logging)
|
||||||
0.000000 | HookCallFunction has_module_events(Analyzer::Logging)
|
0.000000 | HookCallFunction has_module_events(Analyzer::Logging)
|
||||||
|
0.000000 | HookCallFunction have_spicy()
|
||||||
0.000000 | HookCallFunction have_spicy_analyzers()
|
0.000000 | HookCallFunction have_spicy_analyzers()
|
||||||
0.000000 | HookCallFunction is_file_analyzer(AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS)
|
0.000000 | HookCallFunction is_file_analyzer(AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS)
|
||||||
0.000000 | HookCallFunction is_packet_analyzer(AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS)
|
0.000000 | HookCallFunction is_packet_analyzer(AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS)
|
||||||
|
@ -4177,9 +4165,6 @@
|
||||||
0.000000 | HookLoadFile ./Zeek_SSL.events.bif.zeek <...>/Zeek_SSL.events.bif.zeek
|
0.000000 | HookLoadFile ./Zeek_SSL.events.bif.zeek <...>/Zeek_SSL.events.bif.zeek
|
||||||
0.000000 | HookLoadFile ./Zeek_SSL.functions.bif.zeek <...>/Zeek_SSL.functions.bif.zeek
|
0.000000 | HookLoadFile ./Zeek_SSL.functions.bif.zeek <...>/Zeek_SSL.functions.bif.zeek
|
||||||
0.000000 | HookLoadFile ./Zeek_SSL.types.bif.zeek <...>/Zeek_SSL.types.bif.zeek
|
0.000000 | HookLoadFile ./Zeek_SSL.types.bif.zeek <...>/Zeek_SSL.types.bif.zeek
|
||||||
0.000000 | HookLoadFile ./Zeek_Spicy.consts.bif.zeek <...>/Zeek_Spicy.consts.bif.zeek
|
|
||||||
0.000000 | HookLoadFile ./Zeek_Spicy.events.bif.zeek <...>/Zeek_Spicy.events.bif.zeek
|
|
||||||
0.000000 | HookLoadFile ./Zeek_Spicy.functions.bif.zeek <...>/Zeek_Spicy.functions.bif.zeek
|
|
||||||
0.000000 | HookLoadFile ./Zeek_TCP.events.bif.zeek <...>/Zeek_TCP.events.bif.zeek
|
0.000000 | HookLoadFile ./Zeek_TCP.events.bif.zeek <...>/Zeek_TCP.events.bif.zeek
|
||||||
0.000000 | HookLoadFile ./Zeek_TCP.functions.bif.zeek <...>/Zeek_TCP.functions.bif.zeek
|
0.000000 | HookLoadFile ./Zeek_TCP.functions.bif.zeek <...>/Zeek_TCP.functions.bif.zeek
|
||||||
0.000000 | HookLoadFile ./Zeek_TCP.types.bif.zeek <...>/Zeek_TCP.types.bif.zeek
|
0.000000 | HookLoadFile ./Zeek_TCP.types.bif.zeek <...>/Zeek_TCP.types.bif.zeek
|
||||||
|
@ -4274,6 +4259,7 @@
|
||||||
0.000000 | HookLoadFile ./smb1-main <...>/smb1-main.zeek
|
0.000000 | HookLoadFile ./smb1-main <...>/smb1-main.zeek
|
||||||
0.000000 | HookLoadFile ./smb2-main <...>/smb2-main.zeek
|
0.000000 | HookLoadFile ./smb2-main <...>/smb2-main.zeek
|
||||||
0.000000 | HookLoadFile ./spicy-events <...>/spicy-events.zeek
|
0.000000 | HookLoadFile ./spicy-events <...>/spicy-events.zeek
|
||||||
|
0.000000 | HookLoadFile ./spicy.bif.zeek <...>/spicy.bif.zeek
|
||||||
0.000000 | HookLoadFile ./stats.bif.zeek <...>/stats.bif.zeek
|
0.000000 | HookLoadFile ./stats.bif.zeek <...>/stats.bif.zeek
|
||||||
0.000000 | HookLoadFile ./std-dev <...>/std-dev.zeek
|
0.000000 | HookLoadFile ./std-dev <...>/std-dev.zeek
|
||||||
0.000000 | HookLoadFile ./store <...>/store.zeek
|
0.000000 | HookLoadFile ./store <...>/store.zeek
|
||||||
|
@ -4309,10 +4295,6 @@
|
||||||
0.000000 | HookLoadFile <...>/__load__.zeek <...>/__load__.zeek
|
0.000000 | HookLoadFile <...>/__load__.zeek <...>/__load__.zeek
|
||||||
0.000000 | HookLoadFile <...>/__preload__.zeek <...>/__preload__.zeek
|
0.000000 | HookLoadFile <...>/__preload__.zeek <...>/__preload__.zeek
|
||||||
0.000000 | HookLoadFile <...>/hooks.zeek <...>/hooks.zeek
|
0.000000 | HookLoadFile <...>/hooks.zeek <...>/hooks.zeek
|
||||||
0.000000 | HookLoadFile Zeek<...>/bare.zeek <...>/bare.zeek
|
|
||||||
0.000000 | HookLoadFile Zeek<...>/default.zeek <...>/default.zeek
|
|
||||||
0.000000 | HookLoadFile Zeek_Spicy/__load__.zeek <...>/__load__.zeek
|
|
||||||
0.000000 | HookLoadFile Zeek_Spicy/__preload__.zeek <...>/__preload__.zeek
|
|
||||||
0.000000 | HookLoadFile base/bif <...>/bif
|
0.000000 | HookLoadFile base/bif <...>/bif
|
||||||
0.000000 | HookLoadFile base/init-default.zeek <...>/init-default.zeek
|
0.000000 | HookLoadFile base/init-default.zeek <...>/init-default.zeek
|
||||||
0.000000 | HookLoadFile base/init-frameworks-and-bifs.zeek <...>/init-frameworks-and-bifs.zeek
|
0.000000 | HookLoadFile base/init-frameworks-and-bifs.zeek <...>/init-frameworks-and-bifs.zeek
|
||||||
|
@ -4370,6 +4352,8 @@
|
||||||
0.000000 | HookLoadFile base<...>/ieee802_11 <...>/ieee802_11
|
0.000000 | HookLoadFile base<...>/ieee802_11 <...>/ieee802_11
|
||||||
0.000000 | HookLoadFile base<...>/ieee802_11_radio <...>/ieee802_11_radio
|
0.000000 | HookLoadFile base<...>/ieee802_11_radio <...>/ieee802_11_radio
|
||||||
0.000000 | HookLoadFile base<...>/imap <...>/imap
|
0.000000 | HookLoadFile base<...>/imap <...>/imap
|
||||||
|
0.000000 | HookLoadFile base<...>/init-bare <...>/init-bare.zeek
|
||||||
|
0.000000 | HookLoadFile base<...>/init-framework <...>/init-framework.zeek
|
||||||
0.000000 | HookLoadFile base<...>/input <...>/input
|
0.000000 | HookLoadFile base<...>/input <...>/input
|
||||||
0.000000 | HookLoadFile base<...>/input.bif <...>/input.bif.zeek
|
0.000000 | HookLoadFile base<...>/input.bif <...>/input.bif.zeek
|
||||||
0.000000 | HookLoadFile base<...>/installation <...>/installation.zeek
|
0.000000 | HookLoadFile base<...>/installation <...>/installation.zeek
|
||||||
|
@ -4428,6 +4412,7 @@
|
||||||
0.000000 | HookLoadFile base<...>/snmp <...>/snmp
|
0.000000 | HookLoadFile base<...>/snmp <...>/snmp
|
||||||
0.000000 | HookLoadFile base<...>/socks <...>/socks
|
0.000000 | HookLoadFile base<...>/socks <...>/socks
|
||||||
0.000000 | HookLoadFile base<...>/software <...>/software
|
0.000000 | HookLoadFile base<...>/software <...>/software
|
||||||
|
0.000000 | HookLoadFile base<...>/spicy <...>/spicy
|
||||||
0.000000 | HookLoadFile base<...>/ssh <...>/ssh
|
0.000000 | HookLoadFile base<...>/ssh <...>/ssh
|
||||||
0.000000 | HookLoadFile base<...>/ssl <...>/ssl
|
0.000000 | HookLoadFile base<...>/ssl <...>/ssl
|
||||||
0.000000 | HookLoadFile base<...>/stats.bif <...>/stats.bif.zeek
|
0.000000 | HookLoadFile base<...>/stats.bif <...>/stats.bif.zeek
|
||||||
|
@ -4570,9 +4555,6 @@
|
||||||
0.000000 | HookLoadFileExtended ./Zeek_SSL.events.bif.zeek <...>/Zeek_SSL.events.bif.zeek
|
0.000000 | HookLoadFileExtended ./Zeek_SSL.events.bif.zeek <...>/Zeek_SSL.events.bif.zeek
|
||||||
0.000000 | HookLoadFileExtended ./Zeek_SSL.functions.bif.zeek <...>/Zeek_SSL.functions.bif.zeek
|
0.000000 | HookLoadFileExtended ./Zeek_SSL.functions.bif.zeek <...>/Zeek_SSL.functions.bif.zeek
|
||||||
0.000000 | HookLoadFileExtended ./Zeek_SSL.types.bif.zeek <...>/Zeek_SSL.types.bif.zeek
|
0.000000 | HookLoadFileExtended ./Zeek_SSL.types.bif.zeek <...>/Zeek_SSL.types.bif.zeek
|
||||||
0.000000 | HookLoadFileExtended ./Zeek_Spicy.consts.bif.zeek <...>/Zeek_Spicy.consts.bif.zeek
|
|
||||||
0.000000 | HookLoadFileExtended ./Zeek_Spicy.events.bif.zeek <...>/Zeek_Spicy.events.bif.zeek
|
|
||||||
0.000000 | HookLoadFileExtended ./Zeek_Spicy.functions.bif.zeek <...>/Zeek_Spicy.functions.bif.zeek
|
|
||||||
0.000000 | HookLoadFileExtended ./Zeek_TCP.events.bif.zeek <...>/Zeek_TCP.events.bif.zeek
|
0.000000 | HookLoadFileExtended ./Zeek_TCP.events.bif.zeek <...>/Zeek_TCP.events.bif.zeek
|
||||||
0.000000 | HookLoadFileExtended ./Zeek_TCP.functions.bif.zeek <...>/Zeek_TCP.functions.bif.zeek
|
0.000000 | HookLoadFileExtended ./Zeek_TCP.functions.bif.zeek <...>/Zeek_TCP.functions.bif.zeek
|
||||||
0.000000 | HookLoadFileExtended ./Zeek_TCP.types.bif.zeek <...>/Zeek_TCP.types.bif.zeek
|
0.000000 | HookLoadFileExtended ./Zeek_TCP.types.bif.zeek <...>/Zeek_TCP.types.bif.zeek
|
||||||
|
@ -4667,6 +4649,7 @@
|
||||||
0.000000 | HookLoadFileExtended ./smb1-main <...>/smb1-main.zeek
|
0.000000 | HookLoadFileExtended ./smb1-main <...>/smb1-main.zeek
|
||||||
0.000000 | HookLoadFileExtended ./smb2-main <...>/smb2-main.zeek
|
0.000000 | HookLoadFileExtended ./smb2-main <...>/smb2-main.zeek
|
||||||
0.000000 | HookLoadFileExtended ./spicy-events <...>/spicy-events.zeek
|
0.000000 | HookLoadFileExtended ./spicy-events <...>/spicy-events.zeek
|
||||||
|
0.000000 | HookLoadFileExtended ./spicy.bif.zeek <...>/spicy.bif.zeek
|
||||||
0.000000 | HookLoadFileExtended ./stats.bif.zeek <...>/stats.bif.zeek
|
0.000000 | HookLoadFileExtended ./stats.bif.zeek <...>/stats.bif.zeek
|
||||||
0.000000 | HookLoadFileExtended ./std-dev <...>/std-dev.zeek
|
0.000000 | HookLoadFileExtended ./std-dev <...>/std-dev.zeek
|
||||||
0.000000 | HookLoadFileExtended ./store <...>/store.zeek
|
0.000000 | HookLoadFileExtended ./store <...>/store.zeek
|
||||||
|
@ -4702,10 +4685,6 @@
|
||||||
0.000000 | HookLoadFileExtended <...>/__load__.zeek <...>/__load__.zeek
|
0.000000 | HookLoadFileExtended <...>/__load__.zeek <...>/__load__.zeek
|
||||||
0.000000 | HookLoadFileExtended <...>/__preload__.zeek <...>/__preload__.zeek
|
0.000000 | HookLoadFileExtended <...>/__preload__.zeek <...>/__preload__.zeek
|
||||||
0.000000 | HookLoadFileExtended <...>/hooks.zeek <...>/hooks.zeek
|
0.000000 | HookLoadFileExtended <...>/hooks.zeek <...>/hooks.zeek
|
||||||
0.000000 | HookLoadFileExtended Zeek<...>/bare.zeek <...>/bare.zeek
|
|
||||||
0.000000 | HookLoadFileExtended Zeek<...>/default.zeek <...>/default.zeek
|
|
||||||
0.000000 | HookLoadFileExtended Zeek_Spicy/__load__.zeek <...>/__load__.zeek
|
|
||||||
0.000000 | HookLoadFileExtended Zeek_Spicy/__preload__.zeek <...>/__preload__.zeek
|
|
||||||
0.000000 | HookLoadFileExtended base/bif <...>/bif
|
0.000000 | HookLoadFileExtended base/bif <...>/bif
|
||||||
0.000000 | HookLoadFileExtended base/init-default.zeek <...>/init-default.zeek
|
0.000000 | HookLoadFileExtended base/init-default.zeek <...>/init-default.zeek
|
||||||
0.000000 | HookLoadFileExtended base/init-frameworks-and-bifs.zeek <...>/init-frameworks-and-bifs.zeek
|
0.000000 | HookLoadFileExtended base/init-frameworks-and-bifs.zeek <...>/init-frameworks-and-bifs.zeek
|
||||||
|
@ -4763,6 +4742,8 @@
|
||||||
0.000000 | HookLoadFileExtended base<...>/ieee802_11 <...>/ieee802_11
|
0.000000 | HookLoadFileExtended base<...>/ieee802_11 <...>/ieee802_11
|
||||||
0.000000 | HookLoadFileExtended base<...>/ieee802_11_radio <...>/ieee802_11_radio
|
0.000000 | HookLoadFileExtended base<...>/ieee802_11_radio <...>/ieee802_11_radio
|
||||||
0.000000 | HookLoadFileExtended base<...>/imap <...>/imap
|
0.000000 | HookLoadFileExtended base<...>/imap <...>/imap
|
||||||
|
0.000000 | HookLoadFileExtended base<...>/init-bare <...>/init-bare.zeek
|
||||||
|
0.000000 | HookLoadFileExtended base<...>/init-framework <...>/init-framework.zeek
|
||||||
0.000000 | HookLoadFileExtended base<...>/input <...>/input
|
0.000000 | HookLoadFileExtended base<...>/input <...>/input
|
||||||
0.000000 | HookLoadFileExtended base<...>/input.bif <...>/input.bif.zeek
|
0.000000 | HookLoadFileExtended base<...>/input.bif <...>/input.bif.zeek
|
||||||
0.000000 | HookLoadFileExtended base<...>/installation <...>/installation.zeek
|
0.000000 | HookLoadFileExtended base<...>/installation <...>/installation.zeek
|
||||||
|
@ -4821,6 +4802,7 @@
|
||||||
0.000000 | HookLoadFileExtended base<...>/snmp <...>/snmp
|
0.000000 | HookLoadFileExtended base<...>/snmp <...>/snmp
|
||||||
0.000000 | HookLoadFileExtended base<...>/socks <...>/socks
|
0.000000 | HookLoadFileExtended base<...>/socks <...>/socks
|
||||||
0.000000 | HookLoadFileExtended base<...>/software <...>/software
|
0.000000 | HookLoadFileExtended base<...>/software <...>/software
|
||||||
|
0.000000 | HookLoadFileExtended base<...>/spicy <...>/spicy
|
||||||
0.000000 | HookLoadFileExtended base<...>/ssh <...>/ssh
|
0.000000 | HookLoadFileExtended base<...>/ssh <...>/ssh
|
||||||
0.000000 | HookLoadFileExtended base<...>/ssl <...>/ssl
|
0.000000 | HookLoadFileExtended base<...>/ssl <...>/ssl
|
||||||
0.000000 | HookLoadFileExtended base<...>/stats.bif <...>/stats.bif.zeek
|
0.000000 | HookLoadFileExtended base<...>/stats.bif <...>/stats.bif.zeek
|
||||||
|
|
6
testing/btest/Baseline/spicy.analyzer-tag/output
Normal file
6
testing/btest/Baseline/spicy.analyzer-tag/output
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
Have analyzer!
|
||||||
|
tag: Analyzer::ANALYZER_SPICY_SSH
|
||||||
|
name: SPICY_SSH
|
||||||
|
|
||||||
|
Do not have analyzer!
|
3
testing/btest/Baseline/spicy.conn-id/output
Normal file
3
testing/btest/Baseline/spicy.conn-id/output
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
(192.150.186.169, 49244/tcp, 131.159.14.23, 22/tcp)
|
||||||
|
(2001:470:1f11:81f:c999:d94:aa7c:2e3e, 49185/tcp, 2001:470:4867:99::21, 21/tcp)
|
2
testing/btest/Baseline/spicy.context/output
Normal file
2
testing/btest/Baseline/spicy.context/output
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
(b"2.0", b"1.99")
|
3
testing/btest/Baseline/spicy.dns/output
Normal file
3
testing/btest/Baseline/spicy.dns/output
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[orig_h=192.150.186.169, orig_p=55587/udp, resp_h=192.150.186.8, resp_p=53/udp], [id=29622, opcode=0, rcode=0, QR=F, AA=F, TC=F, RD=T, RA=F, Z=0, num_queries=1, num_answers=0, num_auth=0, num_addl=0], www.heise.de, 1, 1
|
||||||
|
[orig_h=192.150.186.169, orig_p=55588/udp, resp_h=192.150.186.8, resp_p=53/udp], [id=15429, opcode=0, rcode=0, QR=F, AA=F, TC=F, RD=T, RA=F, Z=0, num_queries=1, num_answers=0, num_auth=0, num_addl=0], www.google.com, 1, 1
|
||||||
|
[orig_h=192.150.186.169, orig_p=55589/udp, resp_h=192.150.186.8, resp_p=53/udp], [id=27360, opcode=0, rcode=0, QR=F, AA=F, TC=F, RD=T, RA=F, Z=0, num_queries=1, num_answers=0, num_auth=0, num_addl=0], www.net.in.tum.de, 1, 1
|
5
testing/btest/Baseline/spicy.double-event/output
Normal file
5
testing/btest/Baseline/spicy.double-event/output
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
1, OpenSSH_3.8.1p1
|
||||||
|
1, OpenSSH_3.9p1
|
||||||
|
2, OpenSSH_3.8.1p1
|
||||||
|
2, OpenSSH_3.9p1
|
4
testing/btest/Baseline/spicy.double-types/output
Normal file
4
testing/btest/Baseline/spicy.double-types/output
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
dtest_message, dtest::FUNCS_YES
|
||||||
|
dtest_result, dtest::RESULT_YES_AGAIN
|
||||||
|
dtest_result_tuple, dtest::FUNCS_YES, dtest::RESULT_YES_AGAIN
|
3
testing/btest/Baseline/spicy.event-args-fail-2/output
Normal file
3
testing/btest/Baseline/spicy.event-args-fail-2/output
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
[error] <...>/event-args-fail.evt:2: signature for hook must be: %error or %error(err: string)
|
||||||
|
[error] <Spicy Plugin for Zeek>: aborting after errors
|
3
testing/btest/Baseline/spicy.event-args-fail-3/output
Normal file
3
testing/btest/Baseline/spicy.event-args-fail-3/output
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
[error] <...>/event-args-fail.evt:2: signature for hook must be: %error or %error(err: string)
|
||||||
|
[error] <Spicy Plugin for Zeek>: aborting after errors
|
3
testing/btest/Baseline/spicy.event-args-fail-4/output
Normal file
3
testing/btest/Baseline/spicy.event-args-fail-4/output
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
[error] <...>/event-args-fail.evt:2: expected id
|
||||||
|
[error] error loading EVT file "<...>/event-args-fail.evt"
|
3
testing/btest/Baseline/spicy.event-args-fail-5/output
Normal file
3
testing/btest/Baseline/spicy.event-args-fail-5/output
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
[error] <...>/event-args-fail.evt:2: expected id
|
||||||
|
[error] error loading EVT file "<...>/event-args-fail.evt"
|
3
testing/btest/Baseline/spicy.event-args-fail-6/output
Normal file
3
testing/btest/Baseline/spicy.event-args-fail-6/output
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
[error] <...>/event-args-fail.evt:2: expected ':'
|
||||||
|
[error] error loading EVT file "<...>/event-args-fail.evt"
|
3
testing/btest/Baseline/spicy.event-args-fail/output
Normal file
3
testing/btest/Baseline/spicy.event-args-fail/output
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
[error] <...>/event-args-fail.evt:10: mismatching type
|
||||||
|
[error] error loading EVT file "<...>/event-args-fail.evt"
|
2
testing/btest/Baseline/spicy.event-args-mismatch/output
Normal file
2
testing/btest/Baseline/spicy.event-args-mismatch/output
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
XXXXXXXXXX.XXXXXX analyzer error in <...>/test.evt, line 6: Event parameter mismatch, cannot convert Spicy value of type 'string' to Zeek value of type 'count'
|
3
testing/btest/Baseline/spicy.event-args/output
Normal file
3
testing/btest/Baseline/spicy.event-args/output
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
Error message: failed to match regular expression (<...>/test.spicy:7:15)
|
||||||
|
Error message: n/a
|
6
testing/btest/Baseline/spicy.event-cond/output
Normal file
6
testing/btest/Baseline/spicy.event-cond/output
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
1, OpenSSH_3.8.1p1
|
||||||
|
1, OpenSSH_3.9p1
|
||||||
|
3, OpenSSH_3.9p1
|
||||||
|
4, OpenSSH_3.8.1p1
|
||||||
|
5, OpenSSH_3.8.1p1
|
5
testing/btest/Baseline/spicy.event-user-type/output
Normal file
5
testing/btest/Baseline/spicy.event-user-type/output
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
is_orig=1 y=[n=1, y=12345]
|
||||||
|
is_orig=0 y=[n=2, y=ABCDE]
|
||||||
|
is_orig=1 y=[n=3, y=67890]
|
||||||
|
is_orig=0 y=[n=4, y=FGHIJ]
|
4
testing/btest/Baseline/spicy.export-enum/output
Normal file
4
testing/btest/Baseline/spicy.export-enum/output
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
TupleEnum::TestEnum_A
|
||||||
|
TupleEnum::TestEnum_Undef
|
||||||
|
[Type] TupleEnum::TestEnum
|
6
testing/btest/Baseline/spicy.export-type-fail/output
Normal file
6
testing/btest/Baseline/spicy.export-type-fail/output
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
[error] unknown type 'Test::DOES_NOT_EXIST' exported
|
||||||
|
[error] unknown type 'NOT_SCOPED' exported
|
||||||
|
[error] <...>/foo.spicy:1:13-5:3: cannot export Spicy type 'Test::X': type is self-recursive
|
||||||
|
[error] <...>/foo.spicy:9:3-13:3: cannot export Spicy type 'Test::Z': can only convert tuple types with all-named fields to Zeek
|
||||||
|
[error] <Spicy Plugin for Zeek>: aborting after errors
|
42
testing/btest/Baseline/spicy.export-types/output
Normal file
42
testing/btest/Baseline/spicy.export-types/output
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
Test::e
|
||||||
|
Test::s
|
||||||
|
Test::type_enum
|
||||||
|
Test::type_enum_A
|
||||||
|
Test::type_enum_B
|
||||||
|
Test::type_enum_C
|
||||||
|
Test::type_enum_Undef
|
||||||
|
Test::type_record_u, {
|
||||||
|
[s] = [type_name=string, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[u2] = [type_name=record , log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[b] = [type_name=bool, log=F, value=<uninitialized>, default_val=<uninitialized>]
|
||||||
|
}
|
||||||
|
Test::u
|
||||||
|
Test::u2
|
||||||
|
XYZ::type_record_sss, {
|
||||||
|
[a] = [type_name=addr, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[v] = [type_name=vector of string, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[iv] = [type_name=interval, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[t] = [type_name=time, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[s] = [type_name=set[enum], log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[p] = [type_name=port, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[b] = [type_name=string, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[i] = [type_name=int, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[o] = [type_name=string, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[m] = [type_name=table[addr] of string, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[u] = [type_name=record , log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[j] = [type_name=count, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[e] = [type_name=enum, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[r] = [type_name=double, log=F, value=<uninitialized>, default_val=<uninitialized>]
|
||||||
|
}
|
||||||
|
type_record_u2, {
|
||||||
|
[t] = [type_name=record , log=F, value=<uninitialized>, default_val=<uninitialized>]
|
||||||
|
}
|
||||||
|
---
|
||||||
|
[a=1.2.3.4, b=bytes, e=Test::type_enum_B, i=-10, iv=5.0 secs, j=10, m={
|
||||||
|
[4.3.2.1] = addr1,
|
||||||
|
[4.3.2.2] = addr2
|
||||||
|
}, o=string, p=42/tcp, r=3.14, s={
|
||||||
|
Test::type_enum_A,
|
||||||
|
Test::type_enum_B
|
||||||
|
}, t=0.0, u=[s=S, b=T, u2=[t=[x=S, y=T]]], v=[1, 2, 3]]
|
|
@ -0,0 +1,4 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
123456
|
||||||
|
AAABBBCCC
|
||||||
|
!@#$
|
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
dfe2070c79e7ff36a925ffa327ffe3deecf8f9c2 foo-1.txt
|
||||||
|
dfe2070c79e7ff36a925ffa327ffe3deecf8f9c2 foo-2.txt
|
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
FM47gX3vI5ofQPm1li
|
||||||
|
FZjUS57tUkGFTibv3
|
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
01E3B49AA18D8AA981256950B8 CN=GTS CA 1O1,O=Google Trust Services,C=US
|
||||||
|
01E3B49AA18D8AA981256950B8 CN=GTS CA 1O1,O=Google Trust Services,C=US
|
6
testing/btest/Baseline/spicy.file-analyzer-nested/files
Normal file
6
testing/btest/Baseline/spicy.file-analyzer-nested/files
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
SPICY_TEXT2 SPICY_TEXT3 - text/plain3
|
||||||
|
SPICY_TEXT2 SPICY_TEXT3 - text/plain3
|
||||||
|
SPICY_TEXT1 SPICY_TEXT2 - text/plain2
|
||||||
|
HTTP SPICY_TEXT1 - text/plain
|
||||||
|
HTTP (empty) - text/json
|
5
testing/btest/Baseline/spicy.file-analyzer-nested/output
Normal file
5
testing/btest/Baseline/spicy.file-analyzer-nested/output
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
data2, F2Qpmk14ATv4vFSEsi, from 1:hello world
|
||||||
|
data3, FyjjRu4ARLzpsPLhNh, from 2a:from 1:hello world
|
||||||
|
data3, Fz3QLf4Bn4qaQwyUdk, from 2b:from 1:hello world
|
||||||
|
data1, FcRmxz1fPbKQEgGGUi, hello world
|
|
@ -0,0 +1,7 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
data3, FyjjRu4ARLzpsPLhNh,
|
||||||
|
data3, Fz3QLf4Bn4qaQwyUdk,
|
||||||
|
depth warning, FyjjRu4ARLzpsPLhNh, [chunk_event=<uninitialized>, stream_event=<uninitialized>, extract_filename=<uninitialized>, extract_limit=0], 2
|
||||||
|
depth warning, Fz3QLf4Bn4qaQwyUdk, [chunk_event=<uninitialized>, stream_event=<uninitialized>, extract_filename=<uninitialized>, extract_limit=0], 2
|
||||||
|
data2, F2Qpmk14ATv4vFSEsi, from 1:hello world
|
||||||
|
data1, FcRmxz1fPbKQEgGGUi, hello world
|
|
@ -0,0 +1,2 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
text data, FcRmxz1fPbKQEgGGUi, hello world
|
3
testing/btest/Baseline/spicy.file-analyzer/output
Normal file
3
testing/btest/Baseline/spicy.file-analyzer/output
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
Files::ANALYZER_SPICY_TEXT
|
||||||
|
text data, FcRmxz1fPbKQEgGGUi, hello world
|
11
testing/btest/Baseline/spicy.file-analyzer/weird.log
Normal file
11
testing/btest/Baseline/spicy.file-analyzer/weird.log
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
#separator \x09
|
||||||
|
#set_separator ,
|
||||||
|
#empty_field (empty)
|
||||||
|
#unset_field -
|
||||||
|
#path weird
|
||||||
|
#open XXXX-XX-XX-XX-XX-XX
|
||||||
|
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer source
|
||||||
|
#types time string addr port addr port string string bool string string
|
||||||
|
XXXXXXXXXX.XXXXXX - - - - - test_weird FcRmxz1fPbKQEgGGUi F zeek -
|
||||||
|
#close XXXX-XX-XX-XX-XX-XX
|
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
FM47gX3vI5ofQPm1li
|
||||||
|
FZjUS57tUkGFTibv3
|
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
01E3B49AA18D8AA981256950B8 CN=GTS CA 1O1,O=Google Trust Services,C=US
|
||||||
|
01E3B49AA18D8AA981256950B8 CN=GTS CA 1O1,O=Google Trust Services,C=US
|
3
testing/btest/Baseline/spicy.file-replaces/output
Normal file
3
testing/btest/Baseline/spicy.file-replaces/output
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
FTP_DATA SPICY_PE - application/x-dosexec
|
||||||
|
FTP_DATA PE - application/x-dosexec
|
3
testing/btest/Baseline/spicy.gap-recovery/output
Normal file
3
testing/btest/Baseline/spicy.gap-recovery/output
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
[$responses=[[$marker=b"HTTP", $len=3070], [$marker=b"HTTP", $len=3070], [$marker=b"HTTP", $len=21999], [$marker=b"HTTP", $len=3070], [$marker=b"HTTP", $len=21999], [$marker=b"HTTP", $len=3070], [$marker=b"HTTP", $len=21999], [$marker=b"HTTP", $len=3070], [$marker=b"HTTP", $len=21999]]]
|
||||||
|
[$requests=[[$marker=b"GET"], [$marker=b"GET"], [$marker=b"GET"], [$marker=b"GET"], [$marker=b"GET"], [$marker=b"GET"], [$marker=b"GET"], [$marker=b"GET"], [$marker=b"GET"], [$marker=b"GET"]]]
|
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
[$responses=[[$marker=b"HTTP", $len=3070], [$marker=b"HTTP", $len=3070], [$marker=b"HTTP", $len=21999], [$marker=b"HTTP", $len=3070], [$marker=b"HTTP", $len=21999], [$marker=b"HTTP", $len=3070], [$marker=b"HTTP", $len=21999]]]
|
||||||
|
[$requests=[[$marker=b"GET"], [$marker=b"GET"], [$marker=b"GET"], [$marker=b"GET"], [$marker=b"GET"], [$marker=b"GET"], [$marker=b"GET"], [$marker=b"GET"], [$marker=b"GET"], [$marker=b"GET"]]]
|
3
testing/btest/Baseline/spicy.import-from/output
Normal file
3
testing/btest/Baseline/spicy.import-from/output
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
Foo::x, Foo::y
|
||||||
|
Foo::x, Foo::y
|
6
testing/btest/Baseline/spicy.list-conversion/output
Normal file
6
testing/btest/Baseline/spicy.list-conversion/output
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
[orig_h=192.150.186.169, orig_p=49244/tcp, resp_h=131.159.14.23, resp_p=22/tcp]
|
||||||
|
T
|
||||||
|
[[a=83, b=84], [a=83, b=84], [a=72, b=73], [a=45, b=46], [a=50, b=51]]
|
||||||
|
11824
|
||||||
|
11599
|
3
testing/btest/Baseline/spicy.module-path/output
Normal file
3
testing/btest/Baseline/spicy.module-path/output
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
Got it
|
||||||
|
Got it
|
2
testing/btest/Baseline/spicy.multiple-enum/output
Normal file
2
testing/btest/Baseline/spicy.multiple-enum/output
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
one, dtest::RESULT_B
|
5
testing/btest/Baseline/spicy.network-time/output
Normal file
5
testing/btest/Baseline/spicy.network-time/output
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
1584014617531080960
|
||||||
|
1584014621661943040
|
||||||
|
1584014625494254080
|
||||||
|
1584014635499969024
|
2
testing/btest/Baseline/spicy.optional/output
Normal file
2
testing/btest/Baseline/spicy.optional/output
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
[x=<uninitialized>]
|
|
@ -0,0 +1,4 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
MACs: src=00:d0:b7:1e:be:20 dst=00:10:dc:72:4c:5f
|
||||||
|
IPs : src=207.158.192.40 dst=10.20.1.31
|
||||||
|
raw bytes: 441
|
|
@ -0,0 +1,2 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
My Ethernet:, \x00\x10\xdcrL_\x00\xd0\xb7\x1e\xbe \x08\x00
|
|
@ -0,0 +1,2 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
[spicy] test::Foo
|
3
testing/btest/Baseline/spicy.packet-analyzer/output
Normal file
3
testing/btest/Baseline/spicy.packet-analyzer/output
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
MACs: src=c8:5b:76:bd:77:ab dst=ff:ff:ff:ff:ff:ff
|
||||||
|
raw data, I am encapsulating
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue