diff --git a/unit_tests/engine/test_filter_evttype_resolver.cpp b/unit_tests/engine/test_filter_evttype_resolver.cpp deleted file mode 100644 index dce6ab38..00000000 --- a/unit_tests/engine/test_filter_evttype_resolver.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/* -Copyright (C) 2023 The Falco Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#include -#include -#include -#include - -#define ASSERT_FILTER_EQ(a, b) { ASSERT_EQ(get_filter_set(a), get_filter_set(b)); } - -std::set get_filter_set(const string &fltstr) -{ - set actual; - auto f = libsinsp::filter::parser(fltstr).parse(); - filter_evttype_resolver().evttypes(f.get(), actual); - return actual; -} - -std::set get_set_difference(std::set exclude_set = {}) -{ - std::set set_difference = {}; - - for(uint32_t i = PPME_GENERIC_E; i < PPM_EVENT_MAX; i++) - { - /* Skip events that are unused. */ - if(sinsp::is_unused_event(i)) - { - continue; - } - - if(exclude_set.find(i) == exclude_set.end()) - { - set_difference.insert(i); - } - } - return set_difference; -} - -TEST(EvtTypeResolver, check_openat) -{ - std::set openat_only{ - PPME_SYSCALL_OPENAT_E, PPME_SYSCALL_OPENAT_X, - PPME_SYSCALL_OPENAT_2_E, PPME_SYSCALL_OPENAT_2_X}; - - std::set not_openat = get_set_difference(openat_only); - - /* `openat_only` */ - ASSERT_EQ(get_filter_set("evt.type=openat"), openat_only); - ASSERT_EQ(get_filter_set("evt.type = openat"), openat_only); - ASSERT_EQ(get_filter_set("not evt.type != openat"), openat_only); - ASSERT_EQ(get_filter_set("not not evt.type = openat"), openat_only); - ASSERT_EQ(get_filter_set("not not not not evt.type = openat"), openat_only); - ASSERT_EQ(get_filter_set("evt.type in (openat)"), openat_only); - ASSERT_EQ(get_filter_set("not (not evt.type=openat)"), openat_only); - ASSERT_EQ(get_filter_set("evt.type=openat and proc.name=nginx"), openat_only); - ASSERT_EQ(get_filter_set("evt.type=openat and not proc.name=nginx"), openat_only); - ASSERT_EQ(get_filter_set("evt.type=openat and (proc.name=nginx)"), openat_only); - ASSERT_EQ(get_filter_set("evt.type=openat and not (evt.type=close and proc.name=nginx)"), openat_only); - - /* `not_openat` */ - ASSERT_EQ(get_filter_set("evt.type!=openat"), not_openat); - ASSERT_EQ(get_filter_set("not not not evt.type = openat"), not_openat); - ASSERT_EQ(get_filter_set("not evt.type=openat"), not_openat); - ASSERT_EQ(get_filter_set("evt.type=close or evt.type!=openat"), not_openat); -} - -TEST(EvtTypeResolver, check_openat_or_close) -{ - std::set openat_close_only{ - PPME_SYSCALL_OPENAT_E, PPME_SYSCALL_OPENAT_X, - PPME_SYSCALL_OPENAT_2_E, PPME_SYSCALL_OPENAT_2_X, - PPME_SYSCALL_CLOSE_E, PPME_SYSCALL_CLOSE_X}; - - std::set not_openat_close = get_set_difference(openat_close_only); - - /* `openat_close_only` */ - ASSERT_EQ(get_filter_set("evt.type in (openat, close)"), openat_close_only); - ASSERT_EQ(get_filter_set("evt.type=openat or evt.type=close"), openat_close_only); - ASSERT_EQ(get_filter_set("evt.type=openat or (evt.type=close and proc.name=nginx)"), openat_close_only); - ASSERT_EQ(get_filter_set("evt.type=close or (evt.type=openat and proc.name=nginx)"), openat_close_only); - - /* not `not_openat_close` */ - ASSERT_EQ(get_filter_set("not evt.type in (openat, close)"), not_openat_close); - ASSERT_EQ(get_filter_set("not not not evt.type in (openat, close)"), not_openat_close); - ASSERT_EQ(get_filter_set("evt.type!=openat and evt.type!=close"), not_openat_close); -} - -TEST(EvtTypeResolver, check_all_events) -{ - /* Computed as a difference of the empty set */ - std::set all_events = get_set_difference(); - - ASSERT_EQ(get_filter_set("evt.type!=openat or evt.type!=close"), all_events); - ASSERT_EQ(get_filter_set("proc.name=nginx"), all_events); - ASSERT_EQ(get_filter_set("evt.type=openat or proc.name=nginx"), all_events); - ASSERT_EQ(get_filter_set("evt.type=openat or (proc.name=nginx)"), all_events); - ASSERT_EQ(get_filter_set("(evt.type=openat) or proc.name=nginx"), all_events); - ASSERT_EQ(get_filter_set("evt.type=close or not (evt.type=openat and proc.name=nginx)"), all_events); - ASSERT_EQ(get_filter_set("evt.type=openat or not (evt.type=close and proc.name=nginx)"), all_events); -} - -TEST(EvtTypeResolver, check_no_events) -{ - std::set no_events = {}; - - ASSERT_EQ(get_filter_set("evt.type=close and evt.type=openat"), no_events); - ASSERT_EQ(get_filter_set("evt.type=openat and (evt.type=close and proc.name=nginx)"), no_events); - ASSERT_EQ(get_filter_set("evt.type=openat and (evt.type=close)"), no_events); -} - -TEST(EvtTypeResolver, check_properties) -{ - std::set no_events = {}; - - // see: https://github.com/falcosecurity/libs/pull/854#issuecomment-1411151732 - ASSERT_FILTER_EQ( - "evt.type in (connect, execve, accept, mmap, container) and not (proc.name=cat and evt.type=mmap)", - "evt.type in (accept, connect, container, execve, mmap)"); - ASSERT_EQ(get_filter_set("(evt.type=mmap and not evt.type=mmap)"), no_events); - - // defining algebraic base sets - std::string zerof = "(evt.type in ())"; ///< "zero"-set: no evt type should matches the filter - std::string onef = "(evt.type exists)"; ///< "one"-set: all evt types should match the filter - std::string neutral1 = "(proc.name=cat)"; ///< "neutral"-sets: evt types are not checked in the filter - std::string neutral2 = "(not proc.name=cat)"; - ASSERT_FILTER_EQ(onef, neutral1); - ASSERT_FILTER_EQ(onef, neutral2); - - // algebraic set properties - // 1' = 0 - ASSERT_FILTER_EQ("not " + onef, zerof); - // 0' = 1 - ASSERT_FILTER_EQ("not " + zerof, onef); - // (A')' = A - ASSERT_FILTER_EQ("evt.type=mmap", "not (not evt.type=mmap)"); - // A * A' = 0 - ASSERT_EQ(get_filter_set(zerof), no_events); - // A + A' = 1 - ASSERT_FILTER_EQ("evt.type=mmap or not evt.type=mmap", onef); - ASSERT_FILTER_EQ("evt.type=mmap or not evt.type=mmap", neutral1); - ASSERT_FILTER_EQ("evt.type=mmap or not evt.type=mmap", neutral2); - // 0 * 1 = 0 - ASSERT_FILTER_EQ(zerof + " and " + onef, zerof); - ASSERT_FILTER_EQ(zerof + " and " + neutral1, zerof); - ASSERT_FILTER_EQ(zerof + " and " + neutral2, zerof); - // 0 + 1 = 1 - ASSERT_FILTER_EQ(zerof + " or " + onef, onef); - ASSERT_FILTER_EQ(zerof + " or " + neutral1, onef); - ASSERT_FILTER_EQ(zerof + " or " + neutral2, onef); - // A * 0 = 0 - ASSERT_FILTER_EQ("evt.type=mmap and " + zerof, zerof); - // A * 1 = A - ASSERT_FILTER_EQ("evt.type=mmap and " + onef, "evt.type=mmap"); - ASSERT_FILTER_EQ("evt.type=mmap and " + neutral1, "evt.type=mmap"); - ASSERT_FILTER_EQ("evt.type=mmap and " + neutral2, "evt.type=mmap"); - // A + 0 = A - ASSERT_FILTER_EQ("evt.type=mmap or " + zerof, "evt.type=mmap"); - // A + 1 = 1 - ASSERT_FILTER_EQ("evt.type=mmap or " + onef, onef); - ASSERT_FILTER_EQ("evt.type=mmap or " + neutral1, onef); - ASSERT_FILTER_EQ("evt.type=mmap or " + neutral2, onef); - // A + A = A - ASSERT_FILTER_EQ("evt.type=mmap or evt.type=mmap", "evt.type=mmap"); - // A * A = A - ASSERT_FILTER_EQ("evt.type=mmap and evt.type=mmap", "evt.type=mmap"); - - // de morgan's laws - ASSERT_FILTER_EQ( - "not (proc.name=cat or evt.type=mmap)", - "not proc.name=cat and not evt.type=mmap"); - ASSERT_FILTER_EQ( - "not (proc.name=cat or fd.type=file)", - "not proc.name=cat and not fd.type=file"); - ASSERT_FILTER_EQ( - "not (evt.type=execve or evt.type=mmap)", - "not evt.type=execve and not evt.type=mmap"); - ASSERT_FILTER_EQ( - "not (evt.type=mmap or evt.type=mmap)", - "not evt.type=mmap and not evt.type=mmap"); - ASSERT_FILTER_EQ( - "not (proc.name=cat and evt.type=mmap)", - "not proc.name=cat or not evt.type=mmap"); - ASSERT_FILTER_EQ( - "not (proc.name=cat and fd.type=file)", - "not proc.name=cat or not fd.type=file"); - ASSERT_FILTER_EQ( - "not (evt.type=execve and evt.type=mmap)", - "not evt.type=execve or not evt.type=mmap"); - ASSERT_FILTER_EQ( - "not (evt.type=mmap and evt.type=mmap)", - "not evt.type=mmap or not evt.type=mmap"); - - // negation isomorphism - ASSERT_FILTER_EQ("not evt.type=mmap", "evt.type!=mmap"); - ASSERT_FILTER_EQ("not proc.name=cat", "proc.name!=cat"); - - // commutative property (and) - ASSERT_FILTER_EQ("evt.type=execve and evt.type=mmap", "evt.type=mmap and evt.type=execve"); - ASSERT_FILTER_EQ("not (evt.type=execve and evt.type=mmap)", "not (evt.type=mmap and evt.type=execve)"); - ASSERT_FILTER_EQ("not evt.type=execve and not evt.type=mmap", "not evt.type=mmap and not evt.type=execve"); - ASSERT_FILTER_EQ("proc.name=cat and evt.type=mmap", "evt.type=mmap and proc.name=cat"); - ASSERT_FILTER_EQ("not (proc.name=cat and evt.type=mmap)", "not (evt.type=mmap and proc.name=cat)"); - ASSERT_FILTER_EQ("not proc.name=cat and not evt.type=mmap", "not evt.type=mmap and not proc.name=cat"); - ASSERT_FILTER_EQ("proc.name=cat and fd.type=file", "fd.type=file and proc.name=cat"); - ASSERT_FILTER_EQ("not (proc.name=cat and fd.type=file)", "not (fd.type=file and proc.name=cat)"); - ASSERT_FILTER_EQ("not proc.name=cat and not fd.type=file", "not fd.type=file and not proc.name=cat"); - - // commutative property (or) - ASSERT_FILTER_EQ("evt.type=execve or evt.type=mmap", "evt.type=mmap or evt.type=execve"); - ASSERT_FILTER_EQ("not (evt.type=execve or evt.type=mmap)", "not (evt.type=mmap or evt.type=execve)"); - ASSERT_FILTER_EQ("not evt.type=execve or not evt.type=mmap", "not evt.type=mmap or not evt.type=execve"); - ASSERT_FILTER_EQ("proc.name=cat or evt.type=mmap", "evt.type=mmap or proc.name=cat"); - ASSERT_FILTER_EQ("not (proc.name=cat or evt.type=mmap)", "not (evt.type=mmap or proc.name=cat)"); - ASSERT_FILTER_EQ("not proc.name=cat or not evt.type=mmap", "not evt.type=mmap or not proc.name=cat"); - ASSERT_FILTER_EQ("proc.name=cat or fd.type=file", "fd.type=file or proc.name=cat"); - ASSERT_FILTER_EQ("not (proc.name=cat or fd.type=file)", "not (fd.type=file or proc.name=cat)"); - ASSERT_FILTER_EQ("not proc.name=cat or not fd.type=file", "not fd.type=file or not proc.name=cat"); -} diff --git a/userspace/engine/CMakeLists.txt b/userspace/engine/CMakeLists.txt index a46548d7..d6b2b1cf 100644 --- a/userspace/engine/CMakeLists.txt +++ b/userspace/engine/CMakeLists.txt @@ -19,7 +19,6 @@ set(FALCO_ENGINE_SOURCE_FILES evttype_index_ruleset.cpp formats.cpp filter_macro_resolver.cpp - filter_evttype_resolver.cpp filter_warning_resolver.cpp stats_manager.cpp rule_loader.cpp diff --git a/userspace/engine/filter_evttype_resolver.cpp b/userspace/engine/filter_evttype_resolver.cpp deleted file mode 100644 index 3b41c138..00000000 --- a/userspace/engine/filter_evttype_resolver.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/* -Copyright (C) 2022 The Falco Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#include "filter_evttype_resolver.h" -#include - -/** - * Given a rule filtering condition (in AST form), the following logic is - * responsible of returning the set of event types for which the - * filtering condition can be evaluated to true. - * - * This implementation is based on the boolean algebraic properties of sets - * and works as follows depending on the type of nodes: - * - the evt types of "and" nodes are the intersection set of the evt types of - * their children nodes. - * - the evt types of "or" nodes are the union set of the evt types of - * their children nodes. - * - the evt types of leaf nodes (e.g. "evt.type=open" or "proc.name=cat") - * depend on the type of check: - * * checks based on evt types (e.g. =xxx, != xxx, in (xxx)) give a clear - * definition of the matched event types. The "evt.type exists" check - * matches every evt type. - * * checks non-related to evt types are neutral and match all evt types - * (e.g. proc.name=cat). - * - * The tricky part is handling negation (e.g. "not evt.type=open"). - * Given a set of event types, its negation is the difference between the - * "set of all events" and the set (e.g. all types but not the ones in the set). - * Reasonably, negation should not affect checks unrelated to evt types (e.g. - * "proc.name=cat" is equivalent to "not proc.name=cat" for evt type matching). - * The knowledge of whether a set of event types should be negated or not - * can't be handled nor propagated in "and" and "or" nodes. Since rules' - * conditions are boolean expression, the solution is to use De Morgan's Laws - * to push the negation evaluations down to the leaf nodes as follows: - * - "not (A and B)" is evaluated as "not A or not B" - * - "not (A or B)" is evaluated as "not A and not B" - * By happening only on leaf nodes, the set of matching event types can safely - * be constructed and negated depending on the different cases. - */ - - -using namespace libsinsp::filter; - -extern sinsp_evttables g_infotables; - -static bool is_evttype_operator(const std::string& op) -{ - return op == "==" || op == "=" || op == "!=" || op == "in"; -} - -size_t falco_event_types::get_ppm_event_max() -{ - return PPM_EVENT_MAX; -} - -void filter_evttype_resolver::visitor::inversion(falco_event_types& types) -{ - // we don't invert "neutral" checks - if (m_last_node_has_evttypes) - { - types = m_all_events.diff(types); - } -} - -void filter_evttype_resolver::visitor::try_inversion(falco_event_types& types) -{ - if (m_inside_negation) - { - inversion(types); - } -} - -void filter_evttype_resolver::visitor::evttypes(const std::string& evtname, falco_event_types& out) -{ - for(uint16_t i = PPME_GENERIC_E; i < PPM_EVENT_MAX; i++) - { - // Skip unused events - if(sinsp::is_unused_event(i)) - { - continue; - } - - // Fetch event names associated with event id - const auto evtnames = m_inspector.get_events_names({i}); - for (const auto& name : evtnames) - { - // Skip events not matching the requested evtname - if(evtname.empty() || name == evtname) - { - out.insert(i); - } - } - - } -} - -void filter_evttype_resolver::evttypes( - ast::expr* filter, - std::set& out) const -{ - visitor v; - filter->accept(&v); - v.m_last_node_evttypes.for_each([&out](uint16_t val){out.insert(val); return true;}); -} - -void filter_evttype_resolver::evttypes( - std::shared_ptr filter, - std::set& out) const -{ - evttypes(filter.get(), out); -} - -void filter_evttype_resolver::visitor::conjunction( - const std::vector>& children) -{ - falco_event_types types = m_all_events; - m_last_node_evttypes.clear(); - for (auto &c : children) - { - c->accept(this); - types = types.intersect(m_last_node_evttypes); - } - m_last_node_evttypes = types; -} - -void filter_evttype_resolver::visitor::disjunction( - const std::vector>& children) -{ - falco_event_types types; - m_last_node_evttypes.clear(); - for (auto &c : children) - { - c->accept(this); - types.merge(m_last_node_evttypes); - } - m_last_node_evttypes = types; -} - -void filter_evttype_resolver::visitor::visit(ast::and_expr* e) -{ - if (m_inside_negation) - { - disjunction(e->children); - } - else - { - conjunction(e->children); - } -} - -void filter_evttype_resolver::visitor::visit(ast::or_expr* e) -{ - if (m_inside_negation) - { - conjunction(e->children); - } - else - { - disjunction(e->children); - } -} - -void filter_evttype_resolver::visitor::visit(ast::not_expr* e) -{ - m_last_node_evttypes.clear(); - auto inside_negation = m_inside_negation; - m_inside_negation = !m_inside_negation; - e->child->accept(this); - m_inside_negation = inside_negation; -} - -void filter_evttype_resolver::visitor::visit(ast::binary_check_expr* e) -{ - m_last_node_evttypes.clear(); - m_last_node_has_evttypes = false; - if (e->field == "evt.type" && is_evttype_operator(e->op)) - { - // note: we expect m_inside_negation and m_last_node_has_evttypes - // to be handled and altered by the child node - m_expect_value = true; - e->value->accept(this); - m_expect_value = false; - if (e->op == "!=") - { - // note: since we push the "negation" down to the tree leaves - // (following de morgan's laws logic), the child node may have - // already inverted the set of matched event type. As such, - // inverting here again is safe for supporting both the - // single-negation and double-negation cases. - inversion(m_last_node_evttypes); - } - return; - } - m_last_node_evttypes = m_all_events; - try_inversion(m_last_node_evttypes); -} - -void filter_evttype_resolver::visitor::visit(ast::unary_check_expr* e) -{ - m_last_node_evttypes.clear(); - m_last_node_has_evttypes = e->field == "evt.type" && e->op == "exists"; - m_last_node_evttypes = m_all_events; - try_inversion(m_last_node_evttypes); -} - -void filter_evttype_resolver::visitor::visit(ast::value_expr* e) -{ - m_last_node_evttypes.clear(); - m_last_node_has_evttypes = m_expect_value; - if (m_expect_value) - { - evttypes(e->value, m_last_node_evttypes); - } - else - { - // this case only happens if a macro has not yet been substituted - // with an actual condition. Should not happen, but we handle it - // for consistency. - m_last_node_evttypes = m_all_events; - } - try_inversion(m_last_node_evttypes); -} - -void filter_evttype_resolver::visitor::visit(ast::list_expr* e) -{ - m_last_node_evttypes.clear(); - m_last_node_has_evttypes = false; - if (m_expect_value) - { - m_last_node_has_evttypes = true; - for (auto &v : e->values) - { - evttypes(v, m_last_node_evttypes); - } - try_inversion(m_last_node_evttypes); - return; - } - m_last_node_evttypes = m_all_events; - try_inversion(m_last_node_evttypes); -} diff --git a/userspace/engine/filter_evttype_resolver.h b/userspace/engine/filter_evttype_resolver.h deleted file mode 100644 index 57aed271..00000000 --- a/userspace/engine/filter_evttype_resolver.h +++ /dev/null @@ -1,227 +0,0 @@ -/* -Copyright (C) 2022 The Falco Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -class falco_event_types -{ -private: - using vec_t = std::vector; - vec_t m_types{}; - - static inline void check_range(uint16_t e) - { - static const auto enum_max = get_ppm_event_max(); - if(e > enum_max) - { - throw std::range_error("invalid event type"); - } - } - -public: - falco_event_types(falco_event_types&&) = default; - falco_event_types(const falco_event_types&) = default; - falco_event_types& operator=(falco_event_types&&) = default; - falco_event_types& operator=(const falco_event_types&) = default; - - static size_t get_ppm_event_max(); - - inline falco_event_types(): - m_types(get_ppm_event_max() + 1, 0) - { - } - - inline void insert(uint16_t e) - { - check_range(e); - m_types[e] = 1; - } - - void merge(const falco_event_types& other) - { - for(size_t i = 0; i <= get_ppm_event_max(); ++i) - { - m_types[i] |= other.m_types[i]; - } - } - - void merge(const std::set& other) - { - for(const auto& e : other) - { - insert(e); - } - } - - inline bool contains(uint16_t e) const - { - check_range(e); - return m_types[e] != 0; - } - - void clear() - { - for(auto& v : m_types) - { - v = 0; - } - } - - bool equals(const falco_event_types& other) const - { - return m_types == other.m_types; - } - - falco_event_types diff(const falco_event_types& other) const - { - falco_event_types ret; - for(size_t i = 0; i <= get_ppm_event_max(); ++i) - { - if(m_types[i] == 1 && other.m_types[i] == 0) - { - ret.m_types[i] = 1; - } - } - return ret; - } - - falco_event_types intersect(const falco_event_types& other) const - { - falco_event_types ret; - for(size_t i = 0; i <= get_ppm_event_max(); ++i) - { - if(m_types[i] == 1 && other.m_types[i] == 1) - { - ret.m_types[i] = 1; - } - } - return ret; - } - - void for_each(std::function consumer) const - { - for(uint16_t i = 0; i < m_types.size(); ++i) - { - if(m_types[i] != 0) - { - if(!consumer(i)) - { - return; - } - } - } - } -}; - -inline bool operator==(const falco_event_types& lhs, const falco_event_types& rhs) -{ - return lhs.equals(rhs); -} - -inline bool operator!=(const falco_event_types& lhs, const falco_event_types& rhs) -{ - return !(lhs == rhs); -} - -/*! - \brief Helper class for finding event types -*/ -class filter_evttype_resolver -{ -public: - /*! - \brief Collects the evttypes related to the provided event name. - The event types are inserted in the set provided as parameter. - The set is not cleared before inserting the elements. - \param evtname The event name used to search event types. If an empty - string is passed, all the available evttypes are collected - \param out The set to be filled with the evttypes - */ - inline void evttypes(const std::string& evtname, falco_event_types& out) const - { - falco_event_types evt_types; - visitor().evttypes(evtname, evt_types); - evt_types.for_each([&out](uint16_t val) - {out.insert(val); return true; }); - } - - /*! - \brief Visits a filter AST and collects all the evttypes for which - the filter expression can be evaluated as true. The event types are - inserted in the set provided as parameter. The set is not cleared before - inserting the elements. - \param filter The filter AST to be explored - \param out The set to be filled with the evttypes - */ - void evttypes( - libsinsp::filter::ast::expr* filter, - std::set& out) const; - - /*! - \brief Overloaded version of evttypes() that supports filters wrapped - in shared pointers - */ - void evttypes( - std::shared_ptr filter, - std::set& out) const; - -private: - struct visitor : public libsinsp::filter::ast::expr_visitor - { - visitor(): - m_expect_value(false), - m_inside_negation(false), - m_last_node_has_evttypes(false), - m_last_node_evttypes({}), - m_all_events({}), - m_inspector() - { - evttypes("", m_all_events); - } - visitor(visitor&&) = default; - visitor& operator = (visitor&&) = default; - visitor(const visitor&) = default; - visitor& operator = (const visitor&) = default; - - bool m_expect_value; - bool m_inside_negation; - bool m_last_node_has_evttypes; - falco_event_types m_last_node_evttypes; - falco_event_types m_all_events; - sinsp m_inspector; - - void visit(libsinsp::filter::ast::and_expr* e) override; - void visit(libsinsp::filter::ast::or_expr* e) override; - void visit(libsinsp::filter::ast::not_expr* e) override; - void visit(libsinsp::filter::ast::value_expr* e) override; - void visit(libsinsp::filter::ast::list_expr* e) override; - void visit(libsinsp::filter::ast::unary_check_expr* e) override; - void visit(libsinsp::filter::ast::binary_check_expr* e) override; - void try_inversion(falco_event_types& types); - void inversion(falco_event_types& types); - void evttypes(const std::string& evtname, falco_event_types& out); - void conjunction(const std::vector>&); - void disjunction(const std::vector>&); - }; -};