From 04d6fa3cb74925bfa7bbe1c91d1960f473be5b98 Mon Sep 17 00:00:00 2001 From: bhaskarbhar <126053496+bhaskarbhar@users.noreply.github.com> Date: Tue, 3 Jun 2025 22:06:14 +0530 Subject: [PATCH] Add get_tags_by_category BIF method --- NEWS | 10 ++- scripts/base/init-bare.zeek | 12 +++ src/script_opt/FuncInfo.cc | 1 + src/zeek.bif | 80 ++++++++++++++++++- .../Baseline/bifs.get_tags_by_category/out | 2 + .../Baseline/opt.ZAM-bif-tracking/output | 2 +- testing/btest/bifs/get_tags_by_category.zeek | 15 ++++ testing/btest/opt/ZAM-bif-tracking.zeek | 1 + 8 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 testing/btest/Baseline/bifs.get_tags_by_category/out create mode 100644 testing/btest/bifs/get_tags_by_category.zeek diff --git a/NEWS b/NEWS index fbff6b2b6c..ad366a7304 100644 --- a/NEWS +++ b/NEWS @@ -6,7 +6,8 @@ release. For an exhaustive list of changes, see the ``CHANGES`` file Zeek 8.0.0 ========== -We would like to thank ... for their contributions to this release. +We would like to thank Bhaskar Bhar (@bhaskarbhar) for their contributions to this +release. Breaking Changes ---------------- @@ -124,6 +125,13 @@ New Functionality - The DNS analyzer was extended to support NAPTR RRs (RFC 2915, RFC 3403). A corresponding ``dns_NAPTR_reply`` event was added. +- A new ``get_tags_by_category`` BIF method was added that returns a list of tags for a + specified plugin category. This can be used in lieu of calling ``zeek -NN`` and + parsing the output. For example, this will return the list of all analyzer plugins + currently loaded: + + get_tags_by_category("ANALYZER"); + Changed Functionality --------------------- diff --git a/scripts/base/init-bare.zeek b/scripts/base/init-bare.zeek index 11185edeb7..712b3d6eb6 100644 --- a/scripts/base/init-bare.zeek +++ b/scripts/base/init-bare.zeek @@ -373,6 +373,18 @@ type endpoint_stats: record { endian_type: count; }; +## Record containing information about a tag. +## +## .. zeek:see:: get_tags_by_category +type tag_component: record { + name: string; + canonical_name: string; + tag: string; + enabled: bool; +}; + +type tag_component_vec : vector of tag_component; + ## Arguments given to Zeek from the command line. In order to use this, Zeek ## must use a ``--`` command line argument immediately followed by a script ## file and additional arguments after that. For example:: diff --git a/src/script_opt/FuncInfo.cc b/src/script_opt/FuncInfo.cc index f99d060557..1ff3036e05 100644 --- a/src/script_opt/FuncInfo.cc +++ b/src/script_opt/FuncInfo.cc @@ -317,6 +317,7 @@ static std::unordered_map func_attrs = { {"global_ids", ATTR_IDEMPOTENT}, {"global_options", ATTR_IDEMPOTENT}, {"gsub", ATTR_FOLDABLE}, + {"get_tags_by_category", ATTR_NO_ZEEK_SIDE_EFFECTS}, {"has_event_group", ATTR_NO_ZEEK_SIDE_EFFECTS}, {"has_module_events", ATTR_NO_ZEEK_SIDE_EFFECTS}, {"have_spicy", ATTR_IDEMPOTENT}, diff --git a/src/zeek.bif b/src/zeek.bif index d77d600583..75e0ed1676 100644 --- a/src/zeek.bif +++ b/src/zeek.bif @@ -9,7 +9,7 @@ %%{ // C++ segment #include - +#include #include #include #include @@ -32,6 +32,9 @@ #include "zeek/Hash.h" #include "zeek/CompHash.h" #include "zeek/packet_analysis/Manager.h" +#include "zeek/plugin/Manager.h" +#include "zeek/plugin/Plugin.h" +#include "zeek/plugin/Component.h" using namespace std; @@ -338,6 +341,34 @@ zeek::RecordValPtr zeek::detail::build_dummy_conn_record() return c; } + + //List of components +static zeek::plugin::component::Type CategoryStringToEnum(const std::string& category) + { + static const std::unordered_map type_map = { + {"READER", zeek::plugin::component::READER}, + {"WRITER", zeek::plugin::component::WRITER}, + {"ANALYZER", zeek::plugin::component::ANALYZER}, + {"PACKET_ANALYZER", zeek::plugin::component::PACKET_ANALYZER}, + {"FILE_ANALYZER", zeek::plugin::component::FILE_ANALYZER}, + {"IOSOURCE", zeek::plugin::component::IOSOURCE}, + {"PKTSRC", zeek::plugin::component::PKTSRC}, + {"PKTDUMPER", zeek::plugin::component::PKTDUMPER}, + {"SESSION_ADAPTER", zeek::plugin::component::SESSION_ADAPTER}, + {"CLUSTER_BACKEND", zeek::plugin::component::CLUSTER_BACKEND}, + {"EVENT_SERIALIZER", zeek::plugin::component::EVENT_SERIALIZER}, + {"LOG_SERIALIZER", zeek::plugin::component::LOG_SERIALIZER}, + {"STORAGE_BACKEND", zeek::plugin::component::STORAGE_BACKEND}, + {"STORAGE_SERIALIZER", zeek::plugin::component::STORAGE_SERIALIZER}, + }; + + auto it = type_map.find(category); + if ( it != type_map.end() ) + return it->second; + + return static_cast(-1); // Invalid + } + %%} # =========================================================================== @@ -5615,3 +5646,50 @@ function find_in_zeekpath%(p: string%): string return zeek::make_intrusive(resolved.c_str()); %} + +## Get a list of tags available for a plugin category. +## +## category: The plugin category to request tags for. +## +## Returns: A vector of records containing the tags of all plugin components +## that belong to the specified category. +function get_tags_by_category%(category: string%): tag_component_vec + %{ + std::string cat = category->CheckString(); + auto type = CategoryStringToEnum(cat); + + if ( type == static_cast(-1) ) + { + reporter->Error("Unknown category type: %s", cat.c_str()); + return nullptr; + } + + static auto vec_type = zeek::id::find_type("tag_component_vec"); + static auto rec_type = zeek::id::find_type("tag_component"); + + if ( ! vec_type || ! rec_type ) + { + reporter->Error("Required types not found (tag_component or component_vec)"); + return nullptr; + } + + auto result = zeek::make_intrusive(vec_type); + auto all_components = plugin_mgr->Components(); + + for ( auto* component : all_components ) + { + if ( component->Type() == type ) + { + auto rec = zeek::make_intrusive(rec_type); + + rec->Assign(0, zeek::make_intrusive(component->Name())); + rec->Assign(1, zeek::make_intrusive(component->CanonicalName())); + rec->Assign(2, zeek::make_intrusive(cat + "_" + component->CanonicalName())); + rec->Assign(3, zeek::make_intrusive(component->Enabled())); + + result->Append(std::move(rec)); + } + } + + return result; + %} diff --git a/testing/btest/Baseline/bifs.get_tags_by_category/out b/testing/btest/Baseline/bifs.get_tags_by_category/out new file mode 100644 index 0000000000..d1f9bbac57 --- /dev/null +++ b/testing/btest/Baseline/bifs.get_tags_by_category/out @@ -0,0 +1,2 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +[name=FTP, canonical_name=FTP, tag=ANALYZER_FTP, enabled=T] diff --git a/testing/btest/Baseline/opt.ZAM-bif-tracking/output b/testing/btest/Baseline/opt.ZAM-bif-tracking/output index 3294385ed4..5926891fca 100644 --- a/testing/btest/Baseline/opt.ZAM-bif-tracking/output +++ b/testing/btest/Baseline/opt.ZAM-bif-tracking/output @@ -1,2 +1,2 @@ ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. -563 seen BiFs, 0 unseen BiFs (), 0 new BiFs () +564 seen BiFs, 0 unseen BiFs (), 0 new BiFs () diff --git a/testing/btest/bifs/get_tags_by_category.zeek b/testing/btest/bifs/get_tags_by_category.zeek new file mode 100644 index 0000000000..7fe8e85549 --- /dev/null +++ b/testing/btest/bifs/get_tags_by_category.zeek @@ -0,0 +1,15 @@ +# +# @TEST-EXEC: zeek -b %INPUT >out +# @TEST-EXEC: btest-diff out + +event zeek_init() +{ + local result = get_tags_by_category("ANALYZER"); + + for (i in result) + { + local rec = result[i]; + if ( rec$name == "FTP" ) + print rec; + } +} diff --git a/testing/btest/opt/ZAM-bif-tracking.zeek b/testing/btest/opt/ZAM-bif-tracking.zeek index 3a6dcb1c27..c65d4932a0 100644 --- a/testing/btest/opt/ZAM-bif-tracking.zeek +++ b/testing/btest/opt/ZAM-bif-tracking.zeek @@ -345,6 +345,7 @@ global known_BiFs = set( "get_reporter_stats", "get_resp_seq", "get_script_comments", + "get_tags_by_category", "get_thread_stats", "get_timer_stats", "getenv",