LCOV - code coverage report
Current view: top level - root/contrail/src/contrail-analytics/contrail-collector/ruleparser - t_ruleparser.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 67 232 28.9 %
Date: 2026-11-09 02:10:49 Functions: 13 64 20.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #ifndef T_RULEENG_H
       7             : #define T_RULEENG_H
       8             : 
       9             : #include <string>
      10             : #include <vector>
      11             : #include <iostream>
      12             : #include <unistd.h>
      13             : #include "boost/lexical_cast.hpp"
      14             : #include <boost/scoped_ptr.hpp>
      15             : #include <boost/ptr_container/ptr_vector.hpp>
      16             : 
      17             : #include "ruleutil.h"
      18             : #include "t_doc.h"
      19             : #include "../viz_message.h"
      20             : 
      21             : #include "syslog.h"
      22             : 
      23             : /**
      24             :  * t_rulemsgtype - class to carry msgtype given in a rule
      25             :  * it will also optionally have context
      26             :  */
      27             : struct t_rulemsgtype {
      28           0 :     t_rulemsgtype(std::string msgtype) : msgtype_(msgtype) {
      29           0 :         has_context_ = false;
      30           0 :     }
      31             : 
      32           0 :     t_rulemsgtype(char* msgtype) : msgtype_(msgtype) {
      33           0 :         has_context_ = false;
      34           0 :     }
      35             : 
      36             :     t_rulemsgtype(std::string msgtype, std::string context) :
      37             :         msgtype_(msgtype), context_(context) {
      38             :             has_context_ = true;
      39             :     }
      40             : 
      41           0 :     t_rulemsgtype(char* msgtype, char* context) :
      42           0 :         msgtype_(msgtype), context_(context) {
      43           0 :             has_context_ = true;
      44           0 :     }
      45             : 
      46             :     bool operator==(const t_rulemsgtype& rhs) {
      47             :         return ((msgtype_ == rhs.msgtype_) &
      48             :                 (has_context_ == rhs.has_context_) &
      49             :                 (!has_context_ ||
      50             :                  context_ == rhs.context_));
      51             :     }
      52             : 
      53             :     bool has_context_;
      54             :     std::string msgtype_;
      55             :     std::string context_;
      56             : };
      57             : 
      58             : typedef enum {
      59             :     RANGEVALUE_S = 1,
      60             :     RANGEVALUE_D
      61             : } RANGEVALUE_TYPE;
      62             : 
      63             : struct t_rangevalue_base {
      64           0 :     t_rangevalue_base(RANGEVALUE_TYPE type) : type_(type) {}
      65           0 :     virtual ~t_rangevalue_base() {}
      66             :     RANGEVALUE_TYPE type_;
      67             : 
      68             :     virtual bool range_check(const std::string& type, const std::string& value) = 0;
      69             : };
      70             : 
      71             : struct t_rangevalue_s : public t_rangevalue_base {
      72           0 :     t_rangevalue_s(std::string rangevalue1) :
      73             :         t_rangevalue_base(RANGEVALUE_S),
      74           0 :         rangevalue1_(rangevalue1) {}
      75           0 :     ~t_rangevalue_s() {}
      76             : 
      77           0 :     virtual bool range_check(const std::string& type, const std::string& value) {
      78           0 :         if (type == "string") {
      79           0 :             return (rangevalue1_ == value);
      80           0 :         } else if ((type == "i16") ||
      81           0 :                 (type == "i32")) {
      82           0 :             int val1 = boost::lexical_cast<int>(value);
      83           0 :             int val2 = boost::lexical_cast<int>(rangevalue1_);
      84           0 :             return (val1 == val2);
      85             :         }
      86           0 :         return false;
      87             :     }
      88             : 
      89             :     std::string rangevalue1_;
      90             : };
      91             : 
      92             : struct t_rangevalue_d : public t_rangevalue_base {
      93           0 :     t_rangevalue_d(std::string rangevalue1, std::string rangevalue2) :
      94             :         t_rangevalue_base(RANGEVALUE_D),
      95           0 :         rangevalue1_(rangevalue1), rangevalue2_(rangevalue2) {}
      96           0 :     ~t_rangevalue_d() {}
      97             : 
      98           0 :     virtual bool range_check(const std::string& type, const std::string& value) {
      99           0 :         if (type == "string") {
     100           0 :             return false;
     101           0 :         } else if ((type == "i16") ||
     102           0 :                 (type == "i32")) {
     103           0 :             int val = boost::lexical_cast<int>(value);
     104           0 :             int val1 = boost::lexical_cast<int>(rangevalue1_);
     105           0 :             int val2 = boost::lexical_cast<int>(rangevalue2_);
     106           0 :             return (val > val1 && val < val2);
     107             :         }
     108           0 :         return false;
     109             :     }
     110             : 
     111             :     std::string rangevalue1_;
     112             :     std::string rangevalue2_;
     113             : };
     114             : 
     115             : class t_rangevalue {
     116             :     public:
     117           0 :         t_rangevalue() {
     118           0 :         }
     119           0 :         ~t_rangevalue() {}
     120             : 
     121           0 :         void add_rangevalue(t_rangevalue_base* elem) {
     122           0 :             rangevalue_v.push_back(elem);
     123           0 :         }
     124             : 
     125           0 :         void print(std::ostream& os) {
     126           0 :             boost::ptr_vector<t_rangevalue_base>::const_iterator iter;
     127             : 
     128           0 :             os << "[";
     129           0 :             bool first = true;
     130           0 :             for (iter = rangevalue_v.begin(); iter != rangevalue_v.end(); iter++) {
     131           0 :                 if (first) {
     132           0 :                     first = false;
     133             :                 } else {
     134           0 :                     os << ", ";
     135             :                 }
     136           0 :                 if ((iter)->type_ == RANGEVALUE_S) {
     137           0 :                     t_rangevalue_s *value = (t_rangevalue_s *)(&(*iter));
     138           0 :                     os << (value)->rangevalue1_;
     139           0 :                 } else if ((iter)->type_ == RANGEVALUE_D) {
     140           0 :                     t_rangevalue_d *value = (t_rangevalue_d *)(&(*iter));
     141           0 :                     os << (value)->rangevalue1_;
     142           0 :                     os << " - ";
     143           0 :                     os << (value)->rangevalue2_;
     144             :                 }
     145             :             }
     146           0 :             os << "]";
     147           0 :         }
     148           0 :         bool range_check(const std::string& type, const std::string& value) {
     149           0 :             boost::ptr_vector<t_rangevalue_base>::iterator it;
     150           0 :             for (it = rangevalue_v.begin(); it != rangevalue_v.end(); it++) {
     151           0 :                 if ((it)->range_check(type, value))
     152           0 :                     return true;
     153             :             }
     154           0 :             return false;
     155             :         }
     156             : 
     157             :     private:
     158             :         boost::ptr_vector<t_rangevalue_base> rangevalue_v;
     159             : };
     160             : 
     161             : class t_cond_base {
     162             :     public:
     163           0 :         t_cond_base(std::string fieldid) : fieldid_(fieldid) {}
     164           0 :         virtual ~t_cond_base() {}
     165             :         virtual void print(std::ostream& os) = 0;
     166             :         virtual bool rule_match(const RuleMsg& rmsg) = 0;
     167             : 
     168             :     protected:
     169             :         std::string fieldid_;
     170             : };
     171             : 
     172             : class t_cond_range : public t_cond_base {
     173             :     public:
     174           0 :     t_cond_range(std::string fieldid, t_rangevalue* value) :
     175           0 :         t_cond_base(fieldid), rangevalue_(value) {
     176           0 :     }
     177           0 :     ~t_cond_range() {}
     178             : 
     179           0 :     virtual void print(std::ostream& os) {
     180           0 :         os << "    (" << fieldid_ << " in ";
     181           0 :         rangevalue_->print(os);
     182           0 :         os << ")";
     183           0 :     }
     184             : 
     185           0 :     virtual bool rule_match(const RuleMsg& rmsg) {
     186           0 :         std::string type, value;
     187           0 :         int ret = rmsg.field_value(fieldid_, type, value);
     188             : 
     189           0 :         if (!ret) {
     190           0 :             return rangevalue_->range_check(type, value);
     191             :         }
     192           0 :         return false;
     193           0 :     }
     194             : 
     195             :     private:
     196             :         boost::scoped_ptr<t_rangevalue> rangevalue_;
     197             : };
     198             : 
     199             : class t_cond_simple : public t_cond_base {
     200             :     public:
     201           0 :     t_cond_simple(std::string fieldid, char op, std::string value) :
     202           0 :         t_cond_base(fieldid), value_(value), operation_(op) {
     203           0 :     }
     204           0 :     ~t_cond_simple() {}
     205             : 
     206           0 :     virtual void print(std::ostream& os) {
     207           0 :         os << "    (" << fieldid_ << " " << operation_ << " " << value_ << ")";
     208           0 :     }
     209             : 
     210           0 :     virtual bool rule_match(const RuleMsg& rmsg) {
     211           0 :         std::string type, value;
     212           0 :         int ret = rmsg.field_value(fieldid_, type, value);
     213             : 
     214           0 :         if (!ret) {
     215           0 :             if (type == "string") {
     216           0 :                 if (operation_ == '=') {
     217           0 :                     return (value_ == value);
     218             :                 }
     219           0 :             } else if ((type == "i16") ||
     220           0 :                     (type == "i32")) {
     221           0 :                 int val1 = boost::lexical_cast<int>(value);
     222           0 :                 int val2 = boost::lexical_cast<int>(value_);
     223           0 :                 if (operation_ == '=') {
     224           0 :                     return (val1 == val2);
     225           0 :                 } else if (operation_ == '<') {
     226           0 :                     return (val1 < val2);
     227           0 :                 } else if (operation_ == '>') {
     228           0 :                     return (val1 > val2);
     229             :                 }
     230             :             }
     231             :         }
     232           0 :         return false;
     233           0 :     }
     234             : 
     235             :     private:
     236             :         std::string value_;
     237             :         char   operation_;
     238             : };
     239             : 
     240             : class t_rulecondlist {
     241             :     public:
     242           0 :         t_rulecondlist() {}
     243           0 :         ~t_rulecondlist() {}
     244             : 
     245           0 :         void add_field(t_cond_base *cond) {
     246           0 :             conditions_.insert(conditions_.begin(), cond);
     247           0 :         }
     248             : 
     249           6 :         void print(std::ostream& os) {
     250           6 :             boost::ptr_vector<t_cond_base>::iterator iter;
     251           6 :             bool first = true;
     252          22 :             for (iter = conditions_.begin(); iter != conditions_.end(); iter++) {
     253          16 :                 if (first) {
     254           6 :                     first = false;
     255             :                 } else {
     256          10 :                     os << " and\n";
     257             :                 }
     258          16 :                 iter->print(os);
     259             :             }
     260           6 :             os << "\n";
     261           6 :         }
     262             : 
     263           4 :         bool rule_match(const RuleMsg& rmsg) {
     264           4 :             boost::ptr_vector<t_cond_base>::iterator iter;
     265          13 :             for (iter = conditions_.begin(); iter != conditions_.end(); iter++) {
     266          10 :                 if (!((iter)->rule_match(rmsg)))
     267           1 :                     return false;
     268             :             }
     269           3 :             return true;
     270             :         }
     271             : 
     272             :     private:
     273             :         boost::ptr_vector<t_cond_base> conditions_;
     274             : };
     275             : 
     276             : class t_ruleaction {
     277             :     public:
     278           0 :         t_ruleaction() {
     279           0 :         }
     280           0 :         ~t_ruleaction() {}
     281             : 
     282           0 :         std::string get_actionid() {
     283           0 :             return actionid_;
     284             :         }
     285             : 
     286             :         void set_actionid(std::string actionid) {
     287             :             actionid_ = actionid;
     288             :         }
     289             : 
     290           0 :         void set_actionid(char* actionid) {
     291           0 :             actionid_ = actionid;
     292           0 :         }
     293             : 
     294             :         void add_actionparam(std::string elem) {
     295             :             paramlist_.push_back(elem);
     296             :         }
     297             : 
     298           0 :         void add_actionparam(char* elem) {
     299           0 :             paramlist_.push_back(elem);
     300           0 :         }
     301             : 
     302          12 :         void print(std::ostream& os) {
     303          12 :             os << "action " << actionid_; 
     304          12 :             std::vector<std::string>::const_iterator iter;
     305          36 :             for (iter = paramlist_.begin(); iter != paramlist_.end(); iter++) {
     306          24 :                 os << " " << (*iter);
     307             :             }
     308          12 :             os << "\n";
     309          12 :         }
     310             : 
     311             :         void execute(const RuleMsg& rmsg);
     312             : 
     313             :         static std::string RuleActionEchoResult;
     314             : 
     315             :     private:
     316             :         std::string parse_python_exception();
     317             :         std::string actionid_;
     318             :         std::vector<std::string> paramlist_;
     319             : };
     320             : 
     321             : class t_ruleactionlist {
     322             :     public:
     323           0 :         t_ruleactionlist() {}
     324           0 :         ~t_ruleactionlist() {}
     325             : 
     326           0 :         void add_action(t_ruleaction* action) {
     327           0 :             boost::ptr_vector<t_ruleaction>::iterator iter;
     328           0 :             for (iter = actions_.begin(); iter != actions_.end(); iter++) {
     329           0 :                 if (action->get_actionid() == (iter)->get_actionid()) {
     330           0 :                     LOG(DEBUG, "Duplicate action \n");
     331           0 :                     delete action;
     332           0 :                     return;
     333             :                 }
     334             :             }
     335           0 :             actions_.insert(actions_.begin(), action);
     336             :         }
     337             : 
     338           8 :         void print(std::ostream& os) {
     339           8 :             boost::ptr_vector<t_ruleaction>::iterator iter;
     340          20 :             for (iter = actions_.begin(); iter != actions_.end(); iter++) {
     341          12 :                 (iter)->print(os);
     342             :             }
     343           8 :         }
     344             : 
     345           5 :         void execute(const RuleMsg& rmsg) {
     346             : 
     347           5 :             boost::ptr_vector<t_ruleaction>::iterator iter;
     348          12 :             for (iter = actions_.begin(); iter != actions_.end(); iter++) {
     349           7 :                 (iter)->execute(rmsg);
     350             :             }
     351           5 :         }
     352             : 
     353             :     private:
     354             :         boost::ptr_vector<t_ruleaction> actions_;
     355             : };
     356             : 
     357             : /**
     358             :  * t_rule - full definition of a rule along with
     359             :  * its conditions and actions
     360             :  *
     361             :  */
     362             : class t_rule : public t_doc {
     363             :     public:
     364             :         t_rule(std::string name) :
     365             :             rulename_(name) {
     366             :         }
     367           0 :         ~t_rule() {}
     368             : 
     369           0 :         t_rule(t_rulemsgtype *rulemsgtype, t_rulecondlist *condlist, t_ruleactionlist *actionlist) :
     370           0 :             rulemsgtype_(rulemsgtype), condlist_(condlist), actionlist_(actionlist) {
     371           0 :         }
     372             : 
     373           0 :         void set_name(std::string name) {
     374           0 :             rulename_ = name;
     375           0 :         }
     376             : 
     377          48 :         std::string get_name() {
     378          48 :             return rulename_;
     379             :         }
     380             : 
     381             :         std::string get_name() const {
     382             :             return rulename_;
     383             :         }
     384             : 
     385           8 :         void print(std::ostream& os) {
     386           8 :             os << "Rule " << rulename_ << " :\n";
     387           8 :             if (rulemsgtype_->has_context_) {
     388           2 :                 os << "For ((msgtype eq " << rulemsgtype_->msgtype_ << ") and (context eq " << rulemsgtype_->context_ << "))";
     389             :             } else {
     390           6 :                 os << "For msgtype eq " << rulemsgtype_->msgtype_;
     391             :             }
     392             : 
     393           8 :             if (condlist_) {
     394           6 :                 os << " match\n";
     395           6 :                 condlist_->print(os);
     396             :             } else {
     397           2 :                 os << "\n";
     398             :             }
     399             : 
     400           8 :             actionlist_->print(os);
     401           8 :         }
     402             : 
     403           0 :         bool rule_present(const t_rulemsgtype& m) {
     404           0 :             return ((rulemsgtype_->msgtype_ == m.msgtype_) &
     405           0 :                     (rulemsgtype_->has_context_ == m.has_context_) &
     406           0 :                     (!rulemsgtype_->has_context_ ||
     407           0 :                      rulemsgtype_->context_ == m.context_));
     408             :         }
     409             : 
     410             :         bool rule_present(const t_rulemsgtype& m) const {
     411             :             return ((rulemsgtype_->msgtype_ == m.msgtype_) &
     412             :                     (rulemsgtype_->has_context_ == m.has_context_) &
     413             :                     (!rulemsgtype_->has_context_ ||
     414             :                      rulemsgtype_->context_ == m.context_));
     415             :         }
     416             : 
     417          16 :         void rule_execute(const RuleMsg& rmsg) {
     418          22 :             if (!((rulemsgtype_->msgtype_ == rmsg.messagetype) &&
     419           6 :                 ((!rulemsgtype_->has_context_ && !rmsg.hdr.__isset.Context) ||
     420           1 :                  (rulemsgtype_->has_context_ && rmsg.hdr.__isset.Context && rulemsgtype_->context_ == rmsg.hdr.Context)))) {
     421          10 :                 return;
     422             :             }
     423             : 
     424           6 :             if (!condlist_ || condlist_->rule_match(rmsg)) {
     425           5 :                 if (actionlist_)
     426           5 :                     actionlist_->execute(rmsg);
     427             :             }
     428             :         }
     429             : 
     430             :         void rule_execute(const RuleMsg& rmsg) const {
     431             :             if (!((rulemsgtype_->msgtype_ == rmsg.messagetype) &&
     432             :                 ((!rulemsgtype_->has_context_ && !rmsg.hdr.__isset.Context) ||
     433             :                  (rulemsgtype_->has_context_ && rmsg.hdr.__isset.Context && rulemsgtype_->context_ == rmsg.hdr.Context)))) {
     434             :                 return;
     435             :             }
     436             : 
     437             :             if (!condlist_ || condlist_->rule_match(rmsg)) {
     438             :                 if (actionlist_)
     439             :                     actionlist_->execute(rmsg);
     440             :             }
     441             :         }
     442             : 
     443             :     private:
     444             :         std::string rulename_;
     445             :         boost::scoped_ptr<t_rulemsgtype> rulemsgtype_;
     446             :         boost::scoped_ptr<t_rulecondlist> condlist_;
     447             :         boost::scoped_ptr<t_ruleactionlist> actionlist_;
     448             : };
     449             : 
     450             : /**
     451             :  * t_rulelist consists of all rules parsed in a file
     452             :  *
     453             :  */
     454             : class t_rulelist: public t_doc {
     455             :     public:
     456             :         t_rulelist(std::string path):
     457             :             path_(path),
     458             :             name_(program_name(path)) {
     459             :         }
     460             : 
     461           4 :         t_rulelist() {}
     462           8 :         ~t_rulelist() {}
     463             : 
     464           0 :         void add_rule(t_rule* rule) {
     465           0 :             boost::ptr_vector<t_rule>::iterator iter;
     466           0 :             for (iter = rules_.begin(); iter != rules_.end(); iter++) {
     467           0 :                 if (rule->get_name() == iter->get_name()) {
     468           0 :                     LOG(DEBUG, "Duplicate rule \n");
     469           0 :                     delete rule;
     470           0 :                     return;
     471             :                 }
     472             :             }
     473           0 :             rules_.push_back(rule);
     474             :         }
     475             : 
     476           0 :         boost::ptr_vector<t_rule>& get_rules() {
     477           0 :             return rules_;
     478             :         }
     479             : 
     480           2 :         void print(std::ostream& os) {
     481           2 :             boost::ptr_vector<t_rule>::iterator iter;
     482          10 :             for (iter = rules_.begin(); iter != rules_.end(); iter++) {
     483           8 :                 (iter)->print(os);
     484             :             }
     485           2 :         }
     486             : 
     487           0 :         bool rule_present(const t_rulemsgtype& msgtype) {
     488           0 :             boost::ptr_vector<t_rule>::iterator iter;
     489           0 :             for (iter = rules_.begin(); iter != rules_.end(); iter++) {
     490           0 :                 if ((iter)->rule_present(msgtype)) {
     491           0 :                     return true;
     492             :                 }
     493             :             }
     494           0 :             return false;
     495             :         }
     496             : 
     497           4 :         bool rule_execute(const RuleMsg& rmsg) {
     498           4 :             t_ruleaction::RuleActionEchoResult.clear();
     499             : 
     500           4 :             boost::ptr_vector<t_rule>::iterator iter;
     501          20 :             for (iter = rules_.begin(); iter != rules_.end(); iter++) {
     502          16 :                 (iter)->rule_execute(rmsg);
     503             :             }
     504           4 :             return true;
     505             :         }
     506             : 
     507             :     private:
     508             :         // File path
     509             :         std::string path_;
     510             : 
     511             :         // Name
     512             :         std::string name_;
     513             : 
     514             :         // vector of all rules
     515             :         boost::ptr_vector<t_rule> rules_;
     516             : };
     517             : 
     518             : #endif

Generated by: LCOV version 1.14