]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #4170: packet_tracer: add tenants to filters
authorSerhii. Vlasiuk -X (svlasiuk - SOFTSERVE INC at Cisco) <svlasiuk@cisco.com>
Wed, 24 Jan 2024 19:55:50 +0000 (19:55 +0000)
committerSteve Chew (stechew) <stechew@cisco.com>
Wed, 24 Jan 2024 19:55:50 +0000 (19:55 +0000)
Merge in SNORT/snort3 from ~SVLASIUK/snort3:pt_tenants_filter to master

Squashed commit of the following:

commit 93fc7a347f3e3792f2a896b234c3f9004b1a8092
Author: Serhii Vlasiuk <svlasiuk@cisco.com>
Date:   Fri Jan 19 15:59:54 2024 +0200

    packet_tracer: add tenants to filters

src/framework/packet_constraints.cc
src/framework/packet_constraints.h
src/network_inspectors/packet_tracer/packet_tracer.cc
src/network_inspectors/packet_tracer/packet_tracer_module.cc
src/trace/trace_parser.cc

index 4b96cb5c4a9a3ea885325a22b71c4e28a7a1f33d..939a287d150b3819193bb87f7dff02b292824efa 100644 (file)
@@ -31,20 +31,54 @@ namespace {
 
 inline bool match_constraints(const snort::PacketConstraints& cs,
     const snort::SfIp& sip, const snort::SfIp& dip, uint16_t sport,
-    uint16_t dport)
+    uint16_t dport, uint32_t tenant_id)
 {
     using SetBits = snort::PacketConstraints::SetBits;
 
-    return (!(cs.set_bits & SetBits::SRC_PORT) or (sport == cs.src_port)) and
+    bool res = (!(cs.set_bits & SetBits::SRC_PORT) or (sport == cs.src_port)) and
         (!(cs.set_bits & SetBits::DST_PORT) or (dport == cs.dst_port)) and
         (!(cs.set_bits & SetBits::SRC_IP) or (sip == cs.src_ip)) and
         (!(cs.set_bits & SetBits::DST_IP) or (dip == cs.dst_ip));
+
+    if (res && tenant_id && !cs.tenants.empty())
+    {
+        auto it = std::find_if(cs.tenants.cbegin(), cs.tenants.cend(),
+            [tenant_id](uint32_t t){ return t == tenant_id; });
+
+        if (it == cs.tenants.cend())
+            return false;
+    }
+
+    return res;
 }
 
 } // namespace
 
 using namespace snort;
 
+PacketConstraints::PacketConstraints(const PacketConstraints& other) :
+    ip_proto(other.ip_proto), src_port(other.src_port), dst_port(other.dst_port),
+    src_ip(other.src_ip), dst_ip(other.dst_ip), set_bits(other.set_bits),
+    match(other.match), tenants(other.tenants)
+{}
+
+PacketConstraints& PacketConstraints::operator=(const PacketConstraints& other)
+{
+    if (this == &other)
+        return *this;
+
+    ip_proto = other.ip_proto;
+    src_port = other.src_port;
+    dst_port = other.dst_port;
+    src_ip = other.src_ip;
+    dst_ip = other.dst_ip;
+    set_bits = other.set_bits;
+    match = other.match;
+    tenants = other.tenants;
+
+    return *this;
+}
+
 bool PacketConstraints::operator==(const PacketConstraints& other) const
 {
     return set_bits == other.set_bits
@@ -52,7 +86,8 @@ bool PacketConstraints::operator==(const PacketConstraints& other) const
         and ( !(set_bits & SRC_PORT) or src_port == other.src_port )
         and ( !(set_bits & DST_PORT) or dst_port == other.dst_port )
         and ( !(set_bits & SRC_IP) or src_ip == other.src_ip )
-        and ( !(set_bits & DST_IP) or dst_ip == other.dst_ip );
+        and ( !(set_bits & DST_IP) or dst_ip == other.dst_ip )
+        and ( tenants == other.tenants );
 }
 
 bool PacketConstraints::packet_match(const Packet& p) const
@@ -76,8 +111,8 @@ bool PacketConstraints::packet_match(const Packet& p) const
     const auto sp = p.ptrs.sp;
     const auto dp = p.ptrs.dp;
 
-    return match_constraints(*this, sip, dip, sp, dp) or
-        match_constraints(*this, dip, sip, dp, sp);
+    return match_constraints(*this, sip, dip, sp, dp, p.pkth->tenant_id) or
+        match_constraints(*this, dip, sip, dp, sp, p.pkth->tenant_id);
 }
 
 bool PacketConstraints::flow_match(const Flow& f) const
@@ -90,7 +125,7 @@ bool PacketConstraints::flow_match(const Flow& f) const
         return false;
 
     return match_constraints(*this, f.client_ip, f.server_ip, f.client_port,
-        f.server_port);
+        f.server_port, f.tenant);
 }
 
 #ifdef UNIT_TEST
@@ -101,10 +136,10 @@ TEST_CASE("Packet constraints comparison", "[framework]")
 {
     SECTION("all unset")
     {
-        const PacketConstraints exp = IpProtocol::TCP, 10, 20,
-            SfIp(), SfIp(), 0 };
-        const PacketConstraints act = IpProtocol::UDP, 30, 40,
-            SfIp(), SfIp(), 0 };
+        const PacketConstraints exp = PacketConstraints(IpProtocol::TCP, 10, 20,
+            SfIp(), SfIp(), 0, true);
+        const PacketConstraints act = PacketConstraints(IpProtocol::UDP, 30, 40,
+            SfIp(), SfIp(), 0, true);
         CHECK( exp == act );
     }
 
@@ -112,12 +147,12 @@ TEST_CASE("Packet constraints comparison", "[framework]")
     {
         const uint32_t ip1 = 0x01010101;
         const uint32_t ip2 = 0x02020202;
-        const PacketConstraints exp = IpProtocol::PROTO_NOT_SET, 10, 20,
+        const PacketConstraints exp = PacketConstraints(IpProtocol::PROTO_NOT_SET, 10, 20,
             SfIp(&ip1, AF_INET), SfIp(&ip2, AF_INET),
-            (uint8_t)~PacketConstraints::SetBits::DST_IP };
-        const PacketConstraints act = IpProtocol::PROTO_NOT_SET, 10, 20,
+            (uint8_t)~PacketConstraints::SetBits::DST_IP, true);
+        const PacketConstraints act = PacketConstraints(IpProtocol::PROTO_NOT_SET, 10, 20,
             SfIp(&ip1, AF_INET), SfIp(),
-            (uint8_t)~PacketConstraints::SetBits::DST_IP };
+            (uint8_t)~PacketConstraints::SetBits::DST_IP, true);
         CHECK( exp == act );
     }
 
@@ -126,21 +161,31 @@ TEST_CASE("Packet constraints comparison", "[framework]")
         const uint32_t ip1 = 0x01010101;
         const uint32_t ip2 = 0x02020202;
         const uint32_t ip3 = 0x03030303;
-        const PacketConstraints exp = IpProtocol::PROTO_NOT_SET, 0, 0,
-            SfIp(&ip1, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1 };
-        const PacketConstraints act = IpProtocol::PROTO_NOT_SET, 0, 0,
-            SfIp(&ip3, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1};
+        const PacketConstraints exp = PacketConstraints(IpProtocol::PROTO_NOT_SET, 0, 0,
+            SfIp(&ip1, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1, true);
+        const PacketConstraints act = PacketConstraints(IpProtocol::PROTO_NOT_SET, 0, 0,
+            SfIp(&ip3, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1, true);
         CHECK( !(exp == act) );
     }
 
     SECTION("equal")
     {
+        std::vector<uint32_t> tenants1;
+        tenants1.push_back(100);
+        tenants1.push_back(200);
+
+        std::vector<uint32_t> tenants2;
+        tenants2.push_back(100);
+        tenants2.push_back(200);
+
         const uint32_t ip1 = 0x01010101;
         const uint32_t ip2 = 0x02020202;
-        const PacketConstraints exp = { IpProtocol::PROTO_NOT_SET, 0, 0,
-            SfIp(&ip1, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1 };
-        const PacketConstraints act = { IpProtocol::PROTO_NOT_SET, 0, 0,
-            SfIp(&ip1, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1 };
+        PacketConstraints exp = PacketConstraints(IpProtocol::PROTO_NOT_SET, 0, 0,
+            SfIp(&ip1, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1, true);
+        exp.tenants = tenants1;
+        PacketConstraints act = PacketConstraints(IpProtocol::PROTO_NOT_SET, 0, 0,
+            SfIp(&ip1, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1, true);
+        act.tenants = tenants2;
         CHECK( exp == act );
     }
 }
@@ -171,7 +216,12 @@ TEST_CASE("Packet constraints matching", "[framework]")
         cs.src_ip = sip;
         cs.dst_ip = dip;
 
-        CHECK( true == match_constraints(cs, sip, dip, sport, dport) );
+        std::vector<uint32_t> tenants;
+        tenants.push_back(100);
+        tenants.push_back(200);
+        cs.tenants = tenants;
+
+        CHECK( true == match_constraints(cs, sip, dip, sport, dport, 100) );
     }
 
     SECTION("backwards")
@@ -188,7 +238,7 @@ TEST_CASE("Packet constraints matching", "[framework]")
         cs.src_ip = sip;
         cs.dst_ip = dip;
 
-        CHECK( false == match_constraints(cs, dip, sip, dport, sport) );
+        CHECK( false == match_constraints(cs, dip, sip, dport, sport, 0) );
     }
 
     SECTION("any ip")
@@ -201,7 +251,7 @@ TEST_CASE("Packet constraints matching", "[framework]")
         cs.src_port = sport;
         cs.dst_port = dport;
 
-        CHECK( true == match_constraints(cs, sip, dip, sport, dport) );
+        CHECK( true == match_constraints(cs, sip, dip, sport, dport, 0) );
     }
 
     SECTION("any port")
@@ -214,7 +264,7 @@ TEST_CASE("Packet constraints matching", "[framework]")
         cs.src_ip = sip;
         cs.dst_ip = dip;
 
-        CHECK( true == match_constraints(cs, sip, dip, sport, dport) );
+        CHECK( true == match_constraints(cs, sip, dip, sport, dport, 0) );
     }
 
     SECTION("any src")
@@ -227,7 +277,7 @@ TEST_CASE("Packet constraints matching", "[framework]")
         cs.dst_port = dport;
         cs.dst_ip = dip;
 
-        CHECK( true == match_constraints(cs, sip, dip, sport, dport) );
+        CHECK( true == match_constraints(cs, sip, dip, sport, dport, 0) );
     }
 }
 
index 73e113359a11e4e62323f91f8a8034cd35771aa8..ffe6c03bce1218bed01dddcf5226ab4c1ad49e5b 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef PACKET_CONSTRAINTS_H
 #define PACKET_CONSTRAINTS_H
 
+#include <vector>
+
 #include "protocols/protocol_ids.h"
 #include "sfip/sf_ip.h"
 
@@ -39,6 +41,15 @@ struct PacketConstraints
         DST_PORT = 1 << 4,
     };
 
+    PacketConstraints() = default;
+    PacketConstraints(IpProtocol ip_proto, uint16_t src_port, uint16_t dst_port,
+        const snort::SfIp& src_ip, const snort::SfIp& dst_ip, uint8_t set_bits, bool match) :
+        ip_proto(ip_proto), src_port(src_port), dst_port(dst_port),
+        src_ip(src_ip), dst_ip(dst_ip), set_bits(set_bits), match(match)
+    {}
+    PacketConstraints(const PacketConstraints&);
+    PacketConstraints& operator=(const PacketConstraints& other);
+
     bool operator==(const PacketConstraints& other) const;
 
     bool packet_match(const Packet& p) const;
@@ -53,6 +64,8 @@ struct PacketConstraints
     uint8_t set_bits = 0;
 
     bool match = true;
+
+    std::vector<uint32_t> tenants;
 };
 
 } // namespace snort
index 5b52ecb58f08d961f39e9cd48b169554efbb41ef..108e75facd3ff592205a7d419f5f96519070be57 100644 (file)
@@ -464,9 +464,23 @@ void PacketTracer::update_constraints(const PacketConstraints* cs)
     constraints = *cs;
     constraints.src_ip.ntop(sipstr, sizeof(sipstr));
     constraints.dst_ip.ntop(dipstr, sizeof(dipstr));
-    LogMessage("Debugging packet tracer with %s-%hu and %s-%hu %hhu\n",
+
+    std::string tenants = "none";
+    if (constraints.tenants.size())
+    {
+        std::ostringstream oss;
+        for (size_t i = 0; i < constraints.tenants.size(); ++i)
+        {
+            oss << constraints.tenants[i];
+            if (i < constraints.tenants.size() - 1)
+                oss << ",";
+        }
+        tenants = oss.str();
+    }
+
+    LogMessage("Debugging packet tracer with %s-%hu and %s-%hu %hhu and tenants:%s\n",
         sipstr, constraints.src_port, dipstr, constraints.dst_port,
-        static_cast<uint8_t>(constraints.ip_proto));
+        static_cast<uint8_t>(constraints.ip_proto), tenants.c_str());
 
     shell_enabled = true;
 
index 56c2e57d035884df40bea81c23479a8e38d1b209..841b6c2b8e841a75235e088d96fa3c9794899ccf 100644 (file)
 
 using namespace snort;
 
+static void StrToVector(const std::string& s,
+    char delim,
+    std::vector<uint32_t>& elems)
+{
+    std::istringstream ss(s);
+    std::string item;
+    while (std::getline(ss, item, delim))
+    {
+        size_t pos;
+        uint32_t i = std::stoul(item, &pos);
+        elems.push_back(i);
+    }
+}
+
 static int enable(lua_State*);
 static int disable(lua_State*);
 
@@ -58,6 +72,7 @@ static const Parameter enable_packet_tracer_params[] =
     {"src_port", Parameter::PT_INT, "0:65535", nullptr, "source port filter"},
     {"dst_ip", Parameter::PT_STRING, nullptr, nullptr, "destination IP address filter"},
     {"dst_port", Parameter::PT_INT, "0:65535", nullptr, "destination port filter"},
+    {"tenants", Parameter::PT_STRING, nullptr, nullptr, "tenants filter"},
     {nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr}
 };
 
@@ -71,7 +86,7 @@ static const Command packet_tracer_cmds[] =
 class PacketTracerDebug : public AnalyzerCommand
 {
   public:
-    PacketTracerDebug(PacketConstraints* cs);
+    PacketTracerDebug(const PacketConstraints* cs);
     bool execute(Analyzer&, void**) override;
     const char *stringify() override { return "PACKET_TRACER_DEBUG"; }
 
@@ -80,11 +95,11 @@ class PacketTracerDebug : public AnalyzerCommand
     bool enable = false;
 };
 
-PacketTracerDebug::PacketTracerDebug(PacketConstraints* cs)
+PacketTracerDebug::PacketTracerDebug(const PacketConstraints* cs)
 {
     if (cs)
     {
-        memcpy(&constraints, cs, sizeof(constraints));
+        constraints = *cs;
         enable = true;
     }
 }
@@ -107,6 +122,8 @@ static int enable(lua_State* L)
     const char *dipstr = luaL_optstring(L, 4, nullptr);
     int dport = luaL_optint(L, 5, 0);
 
+    const char *tenantsstr = luaL_optstring(L, 6, nullptr);
+
     SfIp sip, dip;
     sip.clear();
     dip.clear();
@@ -125,6 +142,9 @@ static int enable(lua_State* L)
 
     PacketConstraints constraints = {};
 
+    if (tenantsstr)
+        StrToVector(tenantsstr, ',', constraints.tenants);
+
     if (proto and (IpProtocol)proto < IpProtocol::PROTO_NOT_SET)
     {
         constraints.ip_proto = (IpProtocol)proto;
index b10640fc9c422fb5ae6fee4b570d4ed2d33184f7..5b132cfe4c2fe309eb804cd5d88c1da2f7c63fc2 100644 (file)
@@ -358,8 +358,8 @@ TEST_CASE("packet constraints", "[TraceParser]")
     SECTION("ip_proto")
     {
         PROTO_OPTION(ip_proto, 6);
-        const PacketConstraints exp = IpProtocol::TCP, 0, 0,
-            SfIp(), SfIp(), PacketConstraints::IP_PROTO };
+        const PacketConstraints exp = PacketConstraints(IpProtocol::TCP, 0, 0,
+            SfIp(), SfIp(), PacketConstraints::IP_PROTO, true);
 
         CHECK(true == tp.set_constraints(ip_proto));
         tp.finalize_constraints();
@@ -374,8 +374,8 @@ TEST_CASE("packet constraints", "[TraceParser]")
     {
         ADDR_OPTION(src_ip, "10.1.2.3");
         const uint32_t exp_ip = 0x0302010a;
-        const PacketConstraints exp = IpProtocol::PROTO_NOT_SET, 0, 0,
-            SfIp(&exp_ip, AF_INET), SfIp(), PacketConstraints::SRC_IP };
+        const PacketConstraints exp = PacketConstraints(IpProtocol::PROTO_NOT_SET, 0, 0,
+            SfIp(&exp_ip, AF_INET), SfIp(), PacketConstraints::SRC_IP, true);
 
         CHECK(true == tp.set_constraints(src_ip));
         tp.finalize_constraints();
@@ -394,8 +394,8 @@ TEST_CASE("packet constraints", "[TraceParser]")
 
     SECTION("src_port")
     {
-        const PacketConstraints exp = IpProtocol::PROTO_NOT_SET, 100, 0,
-            SfIp(), SfIp(), PacketConstraints::SRC_PORT };
+        const PacketConstraints exp = PacketConstraints(IpProtocol::PROTO_NOT_SET, 100, 0,
+            SfIp(), SfIp(), PacketConstraints::SRC_PORT, true);
         PORT_OPTION(src_port, 100);
 
         CHECK(true == tp.set_constraints(src_port));
@@ -411,8 +411,8 @@ TEST_CASE("packet constraints", "[TraceParser]")
     {
         ADDR_OPTION(dst_ip, "10.3.2.1");
         const uint32_t exp_ip = 0x0102030a;
-        const PacketConstraints exp = IpProtocol::PROTO_NOT_SET, 0, 0,
-            SfIp(), SfIp(&exp_ip, AF_INET), PacketConstraints::DST_IP };
+        const PacketConstraints exp = PacketConstraints(IpProtocol::PROTO_NOT_SET, 0, 0,
+            SfIp(), SfIp(&exp_ip, AF_INET), PacketConstraints::DST_IP, true);
 
         CHECK(true == tp.set_constraints(dst_ip));
         tp.finalize_constraints();
@@ -432,8 +432,8 @@ TEST_CASE("packet constraints", "[TraceParser]")
     SECTION("dst_port")
     {
         PORT_OPTION(dst_port, 200);
-        const PacketConstraints exp = IpProtocol::PROTO_NOT_SET, 0, 200,
-            SfIp(), SfIp(), PacketConstraints::DST_PORT };
+        const PacketConstraints exp = PacketConstraints(IpProtocol::PROTO_NOT_SET, 0, 200,
+            SfIp(), SfIp(), PacketConstraints::DST_PORT, true);
 
         CHECK(true == tp.set_constraints(dst_port));
         tp.finalize_constraints();