]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #991 in SNORT/snort3 from binder_order to master
authorMichael Altizer (mialtize) <mialtize@cisco.com>
Fri, 18 Aug 2017 20:47:49 +0000 (16:47 -0400)
committerMichael Altizer (mialtize) <mialtize@cisco.com>
Fri, 18 Aug 2017 20:47:49 +0000 (16:47 -0400)
Squashed commit of the following:

commit 0a44cace2f0cb9798caf59a9f6aba64f21c73de3
Author: Carter Waxman <cwaxman@cisco.com>
Date:   Mon Aug 14 12:19:28 2017 -0400

    snort2lua: enforced ordering to bindings in binder table

commit 4d9a66aefe11ea13f20d2468fccfd140cb18df09
Author: Carter Waxman <cwaxman@cisco.com>
Date:   Thu Aug 10 17:56:35 2017 -0400

    snort2lua: removed dead code

tools/snort2lua/helpers/converter.cc
tools/snort2lua/helpers/converter.h
tools/snort2lua/helpers/parse_cmd_line.cc
tools/snort2lua/helpers/util_binder.cc
tools/snort2lua/helpers/util_binder.h

index a8de1ce55e9e02d5da7365809e6980b0990c52a4..2c25b863887b98186778b03db69bb2bc158db846 100644 (file)
@@ -17,6 +17,7 @@
 //--------------------------------------------------------------------------
 // converter.cc author Josh Rosenbaum <jrosenba@cisco.com>
 
+#include <algorithm>
 #include <stdexcept>
 
 #include "helpers/converter.h"
@@ -258,13 +259,13 @@ bool Converter::initialize()
 
 Binder& Converter::make_binder(Binder& b)
 {
-    binders.push_back(std::unique_ptr<Binder>(new Binder(b)));
+    binders.push_back(std::shared_ptr<Binder>(new Binder(b)));
     return *binders.back();
 }
 
 Binder& Converter::make_binder()
 {
-    binders.push_back(std::unique_ptr<Binder>(new Binder(table_api)));
+    binders.push_back(std::shared_ptr<Binder>(new Binder(table_api)));
     return *binders.back();
 }
 
@@ -280,6 +281,7 @@ int Converter::convert(std::string input,
 
     // vector::clear()'s ordering isn't deterministic but this is
     // keep in place for stable regressions
+    std::stable_sort(binders.rbegin(), binders.rend());
     while ( binders.size() )
         binders.pop_back();
 
index 489e5a72b9c5d589e5ec2b0554e1efe1c3d6e4bd..19fecca1ce4a12a473d50b88ca986e5c6280bfbc 100644 (file)
@@ -103,7 +103,7 @@ private:
     DataApi data_api;
     TableApi table_api;
     RuleApi rule_api;
-    std::vector<std::unique_ptr<Binder>> binders;
+    std::vector<std::shared_ptr<Binder>> binders;
 
     // the current parsing state.
     ConversionState* state;
index 373696984aa6929a0d7a2733f3ff06f05cd62ed8..216c47fb227f7e811d58a857ab23785943a3b9e8 100644 (file)
@@ -31,6 +31,7 @@
 #include "helpers/converter.h"
 #include "helpers/s2l_util.h"
 #include "helpers/s2l_markup.h"
+#include "helpers/util_binder.h"
 
 namespace parser
 {
@@ -281,6 +282,12 @@ static void print_version(const char* /*key*/, const char* /*val*/)
     std::cout << "Snort2Lua\t0.2.0";
 }
 
+static void print_binder_order(const char* /*key*/, const char* /*val*/)
+{
+    print_binder_priorities();
+    exit(0);
+}
+
 static void help(const char* key, const char* val)
 {
     std::cout << Markup::head(3) << "Usage: snort2lua [OPTIONS]... -c <snort_conf> ...\n";
@@ -386,6 +393,11 @@ static ConfigFunc basic_opts[] =
     { "print-all", print_all, "",
       "Same as '-a'. default option.  print all data" },
 
+#ifdef REG_TEST
+    { "print-binding-order", print_binder_order, ""
+      "Print sorting priority used when generating binder table" },
+#endif
+
     { "print-differences", print_differences, "",
       "Same as '-d'. output the differences, and only the differences, "
       "between the Snort and Snort++ configurations to the <out_file>" },
index 1973832e45d0bce60078c53bd25ba3622386f7af..56d087fd6db220ededca9621af4dfddf3cb40e1f 100644 (file)
 //--------------------------------------------------------------------------
 // pps_binder.cc author Josh Rosenbaum <jrosenba@cisco.com>
 
+#include <algorithm>
+
 #include "helpers/util_binder.h"
 #include "data/dt_table_api.h"
 
+using namespace std;
+
 Binder::Binder(TableApi& t) :   table_api(t),
     printed(false),
     when_policy_id(-1)
@@ -27,7 +31,7 @@ Binder::Binder(TableApi& t) :   table_api(t),
 
 Binder::~Binder()
 {
-    if (!printed)
+    if ( !printed )
         add_to_configuration();
 }
 
@@ -39,26 +43,26 @@ void Binder::add_to_configuration()
 
     table_api.open_table("when", true);
 
-    if (when_policy_id >= 0)
+    if ( has_policy_id() )
         table_api.add_option("policy_id", when_policy_id);
 
-    if (!when_service.empty())
-        table_api.add_option("service", when_service);
+    for ( auto s : vlans )
+        table_api.add_list("vlans", s);
 
-    if (!when_proto.empty())
-        table_api.add_option("proto", when_proto);
+    if ( has_service() )
+        table_api.add_option("service", when_service);
 
-    if (!when_role.empty() && when_role != "any")
-        table_api.add_option("role", when_role);
+    for ( auto n : nets )
+        table_api.add_list("nets", n);
 
-    for (auto p : ports)
+    for ( auto p : ports )
         table_api.add_list("ports", p);
 
-    for (auto s : vlans)
-        table_api.add_list("vlans", s);
+    if ( has_proto() )
+        table_api.add_option("proto", when_proto);
 
-    for (auto n : nets)
-        table_api.add_list("nets", n);
+    if ( has_role() )
+        table_api.add_option("role", when_role);
 
     table_api.close_table(); // "when"
 
@@ -130,3 +134,139 @@ void Binder::set_use_action(std::string action)
 void Binder::set_use_policy_id(std::string id)
 { use_policy_id = std::string(id); }
 
+/*  This operator is provided for STL compatible sorting. A Binder is considered
+    less than another Binder if it should be printed first in the binder table,
+    thus giving it higher priority. This is determined by checking for presence
+    of when options and assigning them priority. If multiple options exist,
+    the highest-priority non-match is used to determine order.
+    
+    Example of ordering:
+    policy_id vlan net
+    policy_id vlan
+    policy_id net
+    policy_id
+    vlan net
+    vlan
+    net
+
+*/
+bool operator<(const shared_ptr<Binder> left, const shared_ptr<Binder> right)
+{
+    #define TRISTATE(v) \
+    { \
+        if ( (v) < 0 ) return true; \
+        if ( (v) > 0 ) return false; \
+    }
+
+    #define FIRST_IF_LT(left, right) \
+    { \
+        if ( (left) < (right) ) return true; \
+        if ( (left) > (right) ) return false; \
+    }
+
+    #define FIRST_IF_GT(left, right) \
+    { \
+        if ( (left) < (right) ) return false; \
+        if ( (left) > (right) ) return true; \
+    }
+
+    //By priorities of options
+    FIRST_IF_GT(left->has_policy_id(), right->has_policy_id())
+    FIRST_IF_GT(left->has_vlans(), right->has_vlans())
+    FIRST_IF_GT(left->has_service(), right->has_service())
+    FIRST_IF_GT(left->has_nets(), right->has_nets())
+    FIRST_IF_GT(left->has_ports(), right->has_ports())
+    FIRST_IF_GT(left->has_proto(), right->has_proto())
+    FIRST_IF_GT(left->has_role(), right->has_role())
+
+    //By values of options. Fewer specs = more specific.
+    if ( left->has_vlans() && right->has_vlans() )
+        FIRST_IF_LT(left->vlans.size(), right->vlans.size())
+
+    if ( left->has_nets() && right->has_nets() )
+        FIRST_IF_LT(left->nets.size(), right->nets.size())
+
+    if ( left->has_ports() && right->has_ports() )
+        FIRST_IF_LT(left->ports.size(), right->ports.size())
+
+    //Sorted by value for readability if all else is equal
+    if ( left->has_policy_id() && right->has_policy_id() )
+        FIRST_IF_LT(left->when_policy_id, right->when_policy_id)
+
+    if ( left->has_service() && right->has_service() )
+        TRISTATE(left->when_service.compare(right->when_service))
+
+    if ( left->has_proto() && right->has_proto() )
+        TRISTATE(left->when_proto.compare(right->when_proto))
+
+    if ( left->has_role() && right->has_role() )
+        TRISTATE(left->when_role.compare(right->when_role))
+
+    return false; //if here, l == r
+}
+
+#ifdef REG_TEST
+#include <iostream>
+
+void print_binder_priorities()
+{
+    static unsigned const num_combos = 2 * 2 * 2 * 2 * 2 * 2 * 2;
+    vector<shared_ptr<Binder>> binders;
+    TableApi t;
+
+    for ( unsigned i = 0; i < num_combos; i++ )
+    {
+        binders.push_back(shared_ptr<Binder>(new Binder(t)));
+        binders.back()->print_binding(false);
+        
+        if ( i & (1 << 0) )
+            binders.back()->set_when_policy_id(1);
+        
+        if ( i & (1 << 1) )
+            binders.back()->add_when_vlan("a");
+        
+        if ( i & (1 << 2) )
+            binders.back()->set_when_service("a");       
+
+        if ( i & (1 << 3) )
+            binders.back()->add_when_net("a");
+        
+        if ( i & (1 << 4) )
+            binders.back()->add_when_port("a");
+
+        if ( i & (1 << 5) )
+            binders.back()->set_when_proto("a");
+
+        if ( i & (1 << 6) )
+            binders.back()->set_when_role("a");
+    }
+
+    sort(binders.begin(), binders.end());
+
+    for ( auto& b : binders )
+    {
+        if ( b->has_policy_id() )
+            cout << "policy_id ";
+
+        if ( b->has_vlans() )
+            cout << "vlan ";
+
+        if ( b->has_service() )
+            cout << "service ";
+
+        if ( b->has_nets() )
+            cout << "net ";
+
+        if ( b->has_ports() )
+            cout << "port ";
+
+        if ( b->has_proto() )
+            cout << "proto ";
+
+        if ( b->has_role() )
+            cout << "role ";
+
+        cout << endl;
+    }
+}
+#endif
index 5bc8a175e0ecc236528c3db60bc8041f81a5faf7..357ce8e6a56076daabc9af67a586df042e477e85 100644 (file)
@@ -20,6 +20,7 @@
 #ifndef HELPERS_PPS_BINDER_H
 #define HELPERS_PPS_BINDER_H
 
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -30,23 +31,20 @@ class TableApi;
 class Converter;
 class Binder
 {
+public:
     //Only use Converter to instantiate Binders through make_binder()
     //This ensures only one binder tables is created per policy
     friend class Converter;
-public:
+
+    //Binding order matters. This allows STL compatible sorting.
+    friend bool operator<(const std::shared_ptr<Binder>, const std::shared_ptr<Binder>);
+
+    Binder(TableApi&);
     ~Binder();
 
-    //  By calling add_to_configuration(), you are adding this Binder Object
-    //  "as is" to the table_api.  Additionally, after calling
-    //  add_to_configuration(), the destructor will NOT add the object to the
-    //  table_api unless 'print_binding(true)' is called.
-    void add_to_configuration();
     void print_binding(bool should_print)
     { printed = !should_print; }
 
-    bool will_print()
-    { return !printed; }
-
     void set_when_policy_id(int id);
     void set_when_service(std::string service);
     void set_when_role(std::string role);
@@ -56,6 +54,27 @@ public:
     void add_when_port(std::string port);
     void clear_ports();
 
+    bool has_policy_id() const
+    { return when_policy_id >= 0; }
+
+    bool has_service() const
+    { return !when_service.empty(); }
+
+    bool has_proto() const
+    { return !when_proto.empty(); }
+
+    bool has_role() const
+    { return !when_role.empty() && when_role != "any"; }
+
+    bool has_vlans() const
+    { return !vlans.empty(); }
+
+    bool has_nets() const
+    { return !nets.empty(); }
+
+    bool has_ports() const
+    { return !ports.empty(); }
+
     void set_use_type(std::string module_name);
     void set_use_name(std::string struct_name);
     void set_use_file(std::string file_name);
@@ -64,8 +83,6 @@ public:
     void set_use_policy_id(std::string id);
 
 private:
-    Binder(TableApi&);
-
     TableApi& table_api;
     bool printed; // ensures that the binding is added once,
                   // by either the destructor or user
@@ -84,9 +101,17 @@ private:
     std::string use_file;
     std::string use_service;
     std::string use_action;
+
+    void add_to_configuration();
 };
 
+bool operator<(const std::shared_ptr<Binder>, const std::shared_ptr<Binder>);
+
 typedef void (Binder::* binder_func)(std::string);
 
+#ifdef REG_TEST
+void print_binder_priorities();
+#endif
+
 #endif