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
|