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
|