check.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef ACL_CHECK_H
  15. #define ACL_CHECK_H
  16. #include <vector>
  17. #include <typeinfo>
  18. #include <sstream>
  19. namespace isc {
  20. namespace acl {
  21. /**
  22. * \brief ACL check base class.
  23. *
  24. * It is intended that all ACL checks are inherited (maybe indirectly) from
  25. * this base class. This will allow us to define new types of checks without
  26. * changing any of the code that is using it and with the correct
  27. * implementation even without changing the thing that parses configuration
  28. * and creates instances of the checks.
  29. *
  30. * It is implemented as a template. This allows easy reuse of the code for
  31. * checking of different types of things (packets of different protocols, etc).
  32. * We'll implement the loader and compound checks as templates as well (
  33. * and just make sure they are instantiated for each type of thing we want
  34. * to check). While most of concrete checks will be specific for one protocol
  35. * (or whatever the entity we check is), it makes sense to implement some of
  36. * these as templates as well (for example the IP address check, for whatever
  37. * context that contains member called ip and has the right methods).
  38. *
  39. * The Context carries whatever information might be checked for that protocol
  40. * (eg. the packet, information where it came from, to what port, ...).
  41. */
  42. template<typename Context> class Check {
  43. protected:
  44. /// \brief Constructor.
  45. ///
  46. /// Just to make sure this thing is not directly instantiated.
  47. Check() { }
  48. public:
  49. /**
  50. * \brief The check itself.
  51. *
  52. * The actual check will be performed here. Every concrete child class
  53. * will reimplement it and decide based on the context passed if it
  54. * matches.
  55. *
  56. * The caller should expect this method can throw. The list of exceptions
  57. * isn't restricted, as we don't know what kind of checks will be needed.
  58. * An exception should be considered as it is impossible to check the
  59. * condition. It should lead to either blackholing the packet or returning
  60. * some 500-like error (ServFail).
  61. *
  62. * \param context The thing we are trying to match against this check.
  63. * \return true if the context satisfies the check, false otherwise.
  64. */
  65. virtual bool matches(const Context& context) const = 0;
  66. /**
  67. * \brief Cost for unknown cost estimate.
  68. *
  69. * This indicates that the estimate for cost is not provided. This
  70. * is arbitrary large value, meaning "somehow longish time". To be
  71. * on the safe side, we guess more and be just happily suprirised
  72. * if it turns out to run faster.
  73. */
  74. static const unsigned UNKNOWN_COST;
  75. /**
  76. * \brief The expected cost of single match.
  77. *
  78. * This is here to provide some kind of cost information to optimising
  79. * routines. It is in units without any real size, just bigger number
  80. * means the check takes longer time. It is expected to be linear scale.
  81. * It doesn't need to be exact, but better accuracy might lead to better
  82. * optimisations. As of writing this, no optimisations exist yet, but
  83. * are expected to exist in future.
  84. *
  85. * The default is UNKNOWN_COST.
  86. */
  87. virtual unsigned cost() const {
  88. return (UNKNOWN_COST);
  89. }
  90. /// \brief Virtual destructor, as we're virtual
  91. virtual ~ Check() { }
  92. /**
  93. * \brief Conversion to text.
  94. *
  95. * This is meant for debugging purposes, it doesn't have to
  96. * serialise the whole information stored in this Check.
  97. *
  98. * If the check is compound, it should not include the subexpressions
  99. * (while we're able to build whatever treeish representation using
  100. * CompoundCheck::subexpressions, we're not able to separate them
  101. * automatically, as this may produce any kind of free-form string).
  102. */
  103. virtual std::string toText() const {
  104. std::stringstream output;
  105. output << typeid(*this).name() << "@" << this;
  106. return (output.rdbuf()->str());
  107. }
  108. };
  109. // This seems to be the propper way for static template members
  110. template<typename Context> const unsigned Check<Context>::UNKNOWN_COST = 10000;
  111. /**
  112. * \brief Base class for compound checks.
  113. *
  114. * While some checks will be a match against some property of the information
  115. * passed (eg. the sender's IP address must be in some range), others will
  116. * combine results of more checks together to get their own. This is base class
  117. * for the second type, allowing listing of the subexpressions (mostly for
  118. * debugging purposes to print the whole tree of matches and possible future
  119. * optimisations which would like to crawl the expression tree).
  120. */
  121. template<typename Context> class CompoundCheck : public Check<Context> {
  122. public:
  123. /// \brief Abbreviated name for list of subexpressions
  124. typedef std::vector<const Check<Context>*> Checks;
  125. /**
  126. * \brief Get the list of subexpressions.
  127. *
  128. * The result contains pointers to the all subexpressions this check holds
  129. * (and therefore might call during its own match() function).
  130. *
  131. * Using shared pointers looks an overkill here. All the checks must be
  132. * alive for the whole life of this one and this check will hold their
  133. * ownership. Therefore the only thing the caller needs to do is to make
  134. * sure this check is not deleted while it's still using the ones from the
  135. * result.
  136. *
  137. * This method must not throw except for the standard allocation exceptions
  138. * to allocate the result.
  139. */
  140. virtual Checks getSubexpressions() const = 0;
  141. /**
  142. * \brief If the result depends only on results of subexpressions.
  143. *
  144. * Some optimisations might use the fact that a compound expression is
  145. * a function of results of its subexpressions (subchecks) only. But
  146. * some compound checks might want to look into the provided context in
  147. * their match() as well as looking at the results of the subexpressions.
  148. *
  149. * This function informs the optimisation routines if it is safe to use
  150. * these optimisations.
  151. *
  152. * \return true if the check depends only on results of subexpressions
  153. * only, false if it examines the context itself as well.
  154. * \note The default implementation returns true, as it is expected to
  155. * be the case in majority of cases.
  156. */
  157. virtual bool pure() const { return (true); }
  158. /**
  159. * \brief Default compound cost function.
  160. *
  161. * It is simply sum of all subexpressions, as an expected upper bound
  162. * on the cost. This expects that the combining itself is cheap relatively
  163. * to the checks performed by the subexpressions. In most cases, this
  164. * should be good enough, but it can be reimplemented in situations
  165. * where most of the subexpressions will be avoided in usual situations.
  166. * Replacing the default of 10000 from Check.
  167. */
  168. virtual unsigned cost() const {
  169. Checks checks(getSubexpressions());
  170. unsigned result(0);
  171. for (typename Checks::const_iterator i(checks.begin());
  172. i != checks.end(); ++ i) {
  173. result += (*i)->cost();
  174. }
  175. return (result);
  176. }
  177. };
  178. }
  179. }
  180. #endif