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

Generated by: LCOV version 1.14