diff --git a/NEWS b/NEWS
index b4541fb3ba..d4b07aae16 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,12 @@ New Functionality
- File analyzers can now raise analyzer violations to the script-layer via
the new ``AnalyzerViolation()`` method.
+- Packet analyzers can now be disabled and enabled at runtime using
+ the ``Analyzer::enable_analyzer()`` and ``Analyzer::disable_analyzer()``
+ wrappers. While initially for protocol analyzers only, these have
+ been extended to work for packet analyzers, too. Packet analyzers can
+ be added to ``Analyzer::disabled_analyzers``, too.
+
Changed Functionality
---------------------
diff --git a/scripts/base/frameworks/analyzer/main.zeek b/scripts/base/frameworks/analyzer/main.zeek
index 18a8c97c52..a484ec3963 100644
--- a/scripts/base/frameworks/analyzer/main.zeek
+++ b/scripts/base/frameworks/analyzer/main.zeek
@@ -33,7 +33,7 @@ export {
## tag: The tag of the analyzer to enable.
##
## Returns: True if the analyzer was successfully enabled.
- global enable_analyzer: function(tag: Analyzer::Tag) : bool;
+ global enable_analyzer: function(tag: AllAnalyzers::Tag) : bool;
## Disables an analyzer. Once disabled, the analyzer will not be used
## further for analysis of future connections.
@@ -41,7 +41,7 @@ export {
## tag: The tag of the analyzer to disable.
##
## Returns: True if the analyzer was successfully disabled.
- global disable_analyzer: function(tag: Analyzer::Tag) : bool;
+ global disable_analyzer: function(tag: AllAnalyzers::Tag) : bool;
## Registers a set of well-known ports for an analyzer. If a future
## connection on one of these ports is seen, the analyzer will be
@@ -130,7 +130,7 @@ export {
## A set of analyzers to disable by default at startup. The default set
## contains legacy analyzers that are no longer supported.
- global disabled_analyzers: set[Analyzer::Tag] = {
+ global disabled_analyzers: set[AllAnalyzers::Tag] = {
ANALYZER_TCPSTATS,
} &redef;
@@ -152,13 +152,19 @@ event zeek_init() &priority=5
disable_analyzer(a);
}
-function enable_analyzer(tag: Analyzer::Tag) : bool
+function enable_analyzer(tag: AllAnalyzers::Tag) : bool
{
+ if ( is_packet_analyzer(tag) )
+ return PacketAnalyzer::__enable_analyzer(tag);
+
return __enable_analyzer(tag);
}
-function disable_analyzer(tag: Analyzer::Tag) : bool
+function disable_analyzer(tag: AllAnalyzers::Tag) : bool
{
+ if ( is_packet_analyzer(tag) )
+ return PacketAnalyzer::__disable_analyzer(tag);
+
return __disable_analyzer(tag);
}
diff --git a/src/packet_analysis/Analyzer.cc b/src/packet_analysis/Analyzer.cc
index 0161b26ca5..afd21ec40f 100644
--- a/src/packet_analysis/Analyzer.cc
+++ b/src/packet_analysis/Analyzer.cc
@@ -107,6 +107,14 @@ bool Analyzer::ForwardPacket(size_t len, const uint8_t* data, Packet* packet,
return false;
}
+ if ( ! inner_analyzer->IsEnabled() )
+ {
+ DBG_LOG(DBG_PACKET_ANALYSIS,
+ "Analysis in %s found disabled next layer analyzer %s for identifier %#x",
+ GetAnalyzerName(), inner_analyzer->GetAnalyzerName(), identifier);
+ return false;
+ }
+
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.",
GetAnalyzerName(), identifier);
return inner_analyzer->AnalyzePacket(len, data, packet);
diff --git a/src/packet_analysis/Analyzer.h b/src/packet_analysis/Analyzer.h
index b3b36bafc9..e3c962a94e 100644
--- a/src/packet_analysis/Analyzer.h
+++ b/src/packet_analysis/Analyzer.h
@@ -71,6 +71,20 @@ public:
*/
bool IsAnalyzer(const char* name);
+ /**
+ * Enable or disable this analyzer.
+ *
+ * @param value The new enabled value.
+ */
+ void SetEnabled(bool value) { enabled = value; }
+
+ /**
+ * Return whether this analyzer is enabled or not.
+ *
+ * @return true if the analyzer is enabled, else false.
+ */
+ bool IsEnabled() const { return enabled; }
+
/**
* Analyzes the given packet. A common case is that the analyzed protocol
* encapsulates another protocol, which can be determined by an identifier
@@ -258,6 +272,7 @@ private:
zeek::Tag tag;
Dispatcher dispatcher;
AnalyzerPtr default_analyzer = nullptr;
+ bool enabled = true;
/**
* Flag for whether to report unknown protocols in ForwardPacket.
diff --git a/src/packet_analysis/Manager.cc b/src/packet_analysis/Manager.cc
index 74cb92010a..e97fa3620e 100644
--- a/src/packet_analysis/Manager.cc
+++ b/src/packet_analysis/Manager.cc
@@ -88,6 +88,30 @@ AnalyzerPtr Manager::GetAnalyzer(const std::string& name)
return analyzer_it->second;
}
+bool Manager::EnableAnalyzer(EnumVal* tag)
+ {
+ Component* c = Lookup(tag);
+ AnalyzerPtr a = GetAnalyzer(c->Name());
+ if ( ! a )
+ return false;
+
+ a->SetEnabled(true);
+
+ return true;
+ }
+
+bool Manager::DisableAnalyzer(EnumVal* tag)
+ {
+ Component* c = Lookup(tag);
+ AnalyzerPtr a = GetAnalyzer(c->Name());
+ if ( ! a )
+ return false;
+
+ a->SetEnabled(false);
+
+ return true;
+ }
+
void Manager::ProcessPacket(Packet* packet)
{
#ifdef DEBUG
diff --git a/src/packet_analysis/Manager.h b/src/packet_analysis/Manager.h
index 1ae50c2ef2..10f3eee88e 100644
--- a/src/packet_analysis/Manager.h
+++ b/src/packet_analysis/Manager.h
@@ -82,6 +82,46 @@ public:
*/
AnalyzerPtr GetAnalyzer(const std::string& name);
+ /**
+ * Enables an analyzer type. Only enabled analyzers will participate
+ * in packet processing.
+ *
+ * @param tag The analyzer's tag.
+ *
+ * @return True if successful.
+ */
+ bool EnableAnalyzer(zeek::EnumVal* tag);
+
+ /**
+ * Enables an analyzer type. Only enabled analyzers will participate
+ * in packet processing.
+ *
+ * @param tag The analyzer's tag.
+ *
+ * @return True if successful.
+ */
+ bool EnableAnalyzer(const zeek::Tag& tag) { return EnableAnalyzer(tag.AsVal().get()); }
+
+ /**
+ * Disables an analyzer type. Disabled analyzers will not participate
+ * in packet processing.
+ *
+ * @param tag The packet analyzer's tag.
+ *
+ * @return True if successful.
+ */
+ bool DisableAnalyzer(zeek::EnumVal* tag);
+
+ /**
+ * Disables an analyzer type. Disabled analyzers will not participate
+ * in packet processing.
+ *
+ * @param tag The packet analyzer's tag.
+ *
+ * @return True if successful.
+ */
+ bool DisableAnalyzer(const zeek::Tag& tag) { return DisableAnalyzer(tag.AsVal().get()); };
+
/**
* Processes a packet by applying the configured packet analyzers.
*
diff --git a/src/packet_analysis/packet_analysis.bif b/src/packet_analysis/packet_analysis.bif
index c3f6e18194..c90e2665c9 100644
--- a/src/packet_analysis/packet_analysis.bif
+++ b/src/packet_analysis/packet_analysis.bif
@@ -77,3 +77,17 @@ function register_protocol_detection%(parent: PacketAnalyzer::Tag, child: Packet
parent_analyzer->RegisterProtocolDetection(child_analyzer);
return zeek::val_mgr->True();
%}
+
+## Internal function to disable a packet analyzer.
+function PacketAnalyzer::__disable_analyzer%(id: PacketAnalyzer::Tag%) : bool
+ %{
+ bool result = zeek::packet_mgr->DisableAnalyzer(id->AsEnumVal());
+ return zeek::val_mgr->Bool(result);
+ %}
+
+## Internal function to enable a packet analyzer.
+function PacketAnalyzer::__enable_analyzer%(id: PacketAnalyzer::Tag%) : bool
+ %{
+ bool result = zeek::packet_mgr->EnableAnalyzer(id->AsEnumVal());
+ return zeek::val_mgr->Bool(result);
+ %}
diff --git a/testing/btest/Baseline/plugins.hooks/output b/testing/btest/Baseline/plugins.hooks/output
index 0771edcf12..328cdbc667 100644
--- a/testing/btest/Baseline/plugins.hooks/output
+++ b/testing/btest/Baseline/plugins.hooks/output
@@ -1,5 +1,5 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
-0.000000 MetaHookPost CallFunction(Analyzer::__disable_analyzer, , (Analyzer::ANALYZER_TCPSTATS)) ->
+0.000000 MetaHookPost CallFunction(Analyzer::__disable_analyzer, , (AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS)) ->
0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, , (Analyzer::ANALYZER_DCE_RPC, 135/tcp)) ->
0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, , (Analyzer::ANALYZER_DHCP, 4011/udp)) ->
0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, , (Analyzer::ANALYZER_DHCP, 67/udp)) ->
@@ -59,7 +59,7 @@
0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, , (Analyzer::ANALYZER_SYSLOG, 514/udp)) ->
0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, , (Analyzer::ANALYZER_XMPP, 5222/tcp)) ->
0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, , (Analyzer::ANALYZER_XMPP, 5269/tcp)) ->
-0.000000 MetaHookPost CallFunction(Analyzer::disable_analyzer, , (Analyzer::ANALYZER_TCPSTATS)) ->
+0.000000 MetaHookPost CallFunction(Analyzer::disable_analyzer, , (AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS)) ->
0.000000 MetaHookPost CallFunction(Analyzer::register_for_port, , (Analyzer::ANALYZER_DCE_RPC, 135/tcp)) ->
0.000000 MetaHookPost CallFunction(Analyzer::register_for_port, , (Analyzer::ANALYZER_DHCP, 4011/udp)) ->
0.000000 MetaHookPost CallFunction(Analyzer::register_for_port, , (Analyzer::ANALYZER_DHCP, 67/udp)) ->
@@ -716,6 +716,7 @@
0.000000 MetaHookPost CallFunction(getenv, , (ZEEK_DEFAULT_LISTEN_ADDRESS)) ->
0.000000 MetaHookPost CallFunction(global_options, , ()) ->
0.000000 MetaHookPost CallFunction(gsub, ..., ...) ->
+0.000000 MetaHookPost CallFunction(is_packet_analyzer, , (AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS)) ->
0.000000 MetaHookPost CallFunction(lstrip, ..., ...) ->
0.000000 MetaHookPost CallFunction(network_time, , ()) ->
0.000000 MetaHookPost CallFunction(port_to_count, , (2123/udp)) ->
@@ -1512,7 +1513,7 @@
0.000000 MetaHookPost QueueEvent(NetControl::init()) -> false
0.000000 MetaHookPost QueueEvent(filter_change_tracking()) -> false
0.000000 MetaHookPost QueueEvent(zeek_init()) -> false
-0.000000 MetaHookPre CallFunction(Analyzer::__disable_analyzer, , (Analyzer::ANALYZER_TCPSTATS))
+0.000000 MetaHookPre CallFunction(Analyzer::__disable_analyzer, , (AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS))
0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, , (Analyzer::ANALYZER_DCE_RPC, 135/tcp))
0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, , (Analyzer::ANALYZER_DHCP, 4011/udp))
0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, , (Analyzer::ANALYZER_DHCP, 67/udp))
@@ -1572,7 +1573,7 @@
0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, , (Analyzer::ANALYZER_SYSLOG, 514/udp))
0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, , (Analyzer::ANALYZER_XMPP, 5222/tcp))
0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, , (Analyzer::ANALYZER_XMPP, 5269/tcp))
-0.000000 MetaHookPre CallFunction(Analyzer::disable_analyzer, , (Analyzer::ANALYZER_TCPSTATS))
+0.000000 MetaHookPre CallFunction(Analyzer::disable_analyzer, , (AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS))
0.000000 MetaHookPre CallFunction(Analyzer::register_for_port, , (Analyzer::ANALYZER_DCE_RPC, 135/tcp))
0.000000 MetaHookPre CallFunction(Analyzer::register_for_port, , (Analyzer::ANALYZER_DHCP, 4011/udp))
0.000000 MetaHookPre CallFunction(Analyzer::register_for_port, , (Analyzer::ANALYZER_DHCP, 67/udp))
@@ -2229,6 +2230,7 @@
0.000000 MetaHookPre CallFunction(getenv, , (ZEEK_DEFAULT_LISTEN_ADDRESS))
0.000000 MetaHookPre CallFunction(global_options, , ())
0.000000 MetaHookPre CallFunction(gsub, ..., ...)
+0.000000 MetaHookPre CallFunction(is_packet_analyzer, , (AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS))
0.000000 MetaHookPre CallFunction(lstrip, ..., ...)
0.000000 MetaHookPre CallFunction(network_time, , ())
0.000000 MetaHookPre CallFunction(port_to_count, , (2123/udp))
@@ -3025,7 +3027,7 @@
0.000000 MetaHookPre QueueEvent(NetControl::init())
0.000000 MetaHookPre QueueEvent(filter_change_tracking())
0.000000 MetaHookPre QueueEvent(zeek_init())
-0.000000 | HookCallFunction Analyzer::__disable_analyzer(Analyzer::ANALYZER_TCPSTATS)
+0.000000 | HookCallFunction Analyzer::__disable_analyzer(AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS)
0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_DCE_RPC, 135/tcp)
0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_DHCP, 4011/udp)
0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_DHCP, 67/udp)
@@ -3085,7 +3087,7 @@
0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_SYSLOG, 514/udp)
0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_XMPP, 5222/tcp)
0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_XMPP, 5269/tcp)
-0.000000 | HookCallFunction Analyzer::disable_analyzer(Analyzer::ANALYZER_TCPSTATS)
+0.000000 | HookCallFunction Analyzer::disable_analyzer(AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS)
0.000000 | HookCallFunction Analyzer::register_for_port(Analyzer::ANALYZER_DCE_RPC, 135/tcp)
0.000000 | HookCallFunction Analyzer::register_for_port(Analyzer::ANALYZER_DHCP, 4011/udp)
0.000000 | HookCallFunction Analyzer::register_for_port(Analyzer::ANALYZER_DHCP, 67/udp)
@@ -3741,6 +3743,7 @@
0.000000 | HookCallFunction getenv(ZEEK_DEFAULT_LISTEN_ADDRESS)
0.000000 | HookCallFunction global_options()
0.000000 | HookCallFunction gsub(...)
+0.000000 | HookCallFunction is_packet_analyzer(AllAnalyzers::ANALYZER_ANALYZER_TCPSTATS)
0.000000 | HookCallFunction lstrip(...)
0.000000 | HookCallFunction network_time()
0.000000 | HookCallFunction port_to_count(2123/udp)
diff --git a/testing/btest/Baseline/scripts.base.frameworks.analyzer.disabled-packet-analyzers/output b/testing/btest/Baseline/scripts.base.frameworks.analyzer.disabled-packet-analyzers/output
new file mode 100644
index 0000000000..c151611fd1
--- /dev/null
+++ b/testing/btest/Baseline/scripts.base.frameworks.analyzer.disabled-packet-analyzers/output
@@ -0,0 +1,11 @@
+### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
+packet, 1
+packet, 2
+packet, 3
+packet, 4
+packet, 5
+packet, 6
+packet, 7
+packet, 8
+packet, 9
+packet, 10
diff --git a/testing/btest/Baseline/scripts.base.frameworks.analyzer.toggle-packet-analyzers/output b/testing/btest/Baseline/scripts.base.frameworks.analyzer.toggle-packet-analyzers/output
new file mode 100644
index 0000000000..39cd890e18
--- /dev/null
+++ b/testing/btest/Baseline/scripts.base.frameworks.analyzer.toggle-packet-analyzers/output
@@ -0,0 +1,17 @@
+### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
+packet, 1
+packet, 2
+vxlan_packet, C4J4Th3PJpwUYZZ6gc, inner, [hl=20, tos=0, len=84, id=12111, ttl=64, p=1, src=10.0.0.1, dst=10.0.0.2]
+packet, 3
+vxlan_packet, CtPZjS20MLrsMUOJi2, inner, [hl=20, tos=0, len=84, id=36913, ttl=64, p=1, src=10.0.0.2, dst=10.0.0.1]
+packet, 4
+Analyzer::disable_analyzer(PacketAnalyzer::ANALYZER_VXLAN), T
+packet, 5
+packet, 6
+packet, 7
+packet, 8
+Analyzer::enable_analyzer(PacketAnalyzer::ANALYZER_VXLAN), T
+vxlan_packet, C4J4Th3PJpwUYZZ6gc, inner, [hl=20, tos=0, len=84, id=12684, ttl=64, p=1, src=10.0.0.1, dst=10.0.0.2]
+packet, 9
+vxlan_packet, CtPZjS20MLrsMUOJi2, inner, [hl=20, tos=0, len=84, id=37295, ttl=64, p=1, src=10.0.0.2, dst=10.0.0.1]
+packet, 10
diff --git a/testing/btest/scripts/base/frameworks/analyzer/disabled-packet-analyzers.zeek b/testing/btest/scripts/base/frameworks/analyzer/disabled-packet-analyzers.zeek
new file mode 100644
index 0000000000..ac7a843ac1
--- /dev/null
+++ b/testing/btest/scripts/base/frameworks/analyzer/disabled-packet-analyzers.zeek
@@ -0,0 +1,21 @@
+# @TEST-DOC: Add a packet analyzer to Analyzer::disabled_analyzers and ensure it does not generate events (vxlan in this case).
+# @TEST-EXEC: zeek -b -r $TRACES/tunnels/vxlan.pcap %INPUT > output
+# @TEST-EXEC: btest-diff output
+#
+
+# Removing this line triggers vxlan events from all but the first two packets.
+redef Analyzer::disabled_analyzers += { PacketAnalyzer::ANALYZER_VXLAN };
+
+global all_packets = 0;
+
+event raw_packet(hdr: raw_pkt_hdr)
+ {
+ ++all_packets;
+ print "packet", all_packets;
+ }
+
+# Should never run.
+event vxlan_packet(outer: connection, inner: pkt_hdr, vni: count)
+ {
+ print "vxlan_packet", outer$uid, "inner", inner$ip;
+ }
diff --git a/testing/btest/scripts/base/frameworks/analyzer/toggle-packet-analyzers.zeek b/testing/btest/scripts/base/frameworks/analyzer/toggle-packet-analyzers.zeek
new file mode 100644
index 0000000000..946f9e1148
--- /dev/null
+++ b/testing/btest/scripts/base/frameworks/analyzer/toggle-packet-analyzers.zeek
@@ -0,0 +1,30 @@
+# @TEST-DOC: Use Analyzer::disable_analyzer() and Analyzer::enable_analyzer() to disable the VXLAN packet analyzers at runtime based on total raw packet count.
+# @TEST-EXEC: zeek -b -r $TRACES/tunnels/vxlan.pcap %INPUT > output
+# @TEST-EXEC: btest-diff output
+#
+
+global all_packets = 0;
+
+event raw_packet(hdr: raw_pkt_hdr)
+ {
+ ++all_packets;
+ print "packet", all_packets;
+
+ if ( all_packets == 4 )
+ {
+ local er = Analyzer::disable_analyzer(PacketAnalyzer::ANALYZER_VXLAN);
+ print "Analyzer::disable_analyzer(PacketAnalyzer::ANALYZER_VXLAN)", er;
+ }
+ # Packets 5 to 8 don't produce vxlan_packet events.
+
+ if ( all_packets == 8 )
+ {
+ local dr = Analyzer::enable_analyzer(PacketAnalyzer::ANALYZER_VXLAN);
+ print "Analyzer::enable_analyzer(PacketAnalyzer::ANALYZER_VXLAN)", dr;
+ }
+ }
+
+event vxlan_packet(outer: connection, inner: pkt_hdr, vni: count)
+ {
+ print "vxlan_packet", outer$uid, "inner", inner$ip;
+ }