Branch data Line data Source code
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 : :
15 : : #ifndef ACL_ACL_H
16 : : #define ACL_ACL_H
17 : :
18 : : #include "check.h"
19 : : #include <vector>
20 : :
21 : : #include <boost/shared_ptr.hpp>
22 : : #include <boost/noncopyable.hpp>
23 : :
24 : : namespace isc {
25 : : namespace acl {
26 : :
27 : : /**
28 : : * \brief Default actions an ACL could perform.
29 : : *
30 : : * This is the default for the ACL class. It is possible to specify any other
31 : : * data type, as the ACL class does nothing about them, but these look
32 : : * reasonable, so they are provided for convenience. It is not specified what
33 : : * exactly these mean and it's up to whoever uses them.
34 : : */
35 : : enum BasicAction {
36 : : ACCEPT,
37 : : REJECT,
38 : : DROP
39 : : };
40 : :
41 : : /**
42 : : * \brief The ACL itself.
43 : : *
44 : : * It holds bunch of ordered entries, each one consisting of a check (
45 : : * of any kind, it might be even compound) and an action that is returned
46 : : * whenever the action matches. They are tested in the order and first
47 : : * match counts.
48 : : *
49 : : * This is non-copyable. It seems that there's no need to copy them (even
50 : : * when it would be technically possible), so we forbid it just to prevent
51 : : * copying it by accident. If there really is legitimate use, this restriction
52 : : * can be removed.
53 : : *
54 : : * The class is template. It is possible to specify on which context the checks
55 : : * match and which actions it returns. The actions must be copyable
56 : : * for this to work and it is expected to be something small, usually an enum
57 : : * (but other objects are also possible).
58 : : *
59 : : * \note There are protected functions. In fact, you should consider them
60 : : * private, they are protected so tests can get inside. This class
61 : : * is not expected to be subclassed in real applications.
62 : : */
63 : 241 : template<typename Context, typename Action = BasicAction> class ACL :
64 : : public boost::noncopyable {
65 : : public:
66 : : /**
67 : : * \brief Constructor.
68 : : *
69 : : * \param default_action It is the action that is returned when the checked
70 : : * things "falls off" the end of the list (when no rule matched).
71 : : */
72 : 241 : ACL(const Action& default_action) : default_action_(default_action)
73 : 0 : {}
74 : :
75 : : /**
76 : : * \brief Pointer to the check.
77 : : *
78 : : * We use the shared pointer, because we are not able to copy the checks.
79 : : * However, we might need to copy the entries (when we concatenate ACLs
80 : : * together in future).
81 : : */
82 : : typedef boost::shared_ptr<const Check<Context> > ConstCheckPtr;
83 : :
84 : : /**
85 : : * \brief The actual main function that decides.
86 : : *
87 : : * This is the function that takes the entries one by one, checks
88 : : * the context against conditions and if it matches, returns the
89 : : * action that belongs to the first matched entry or default action
90 : : * if nothing matches.
91 : : *
92 : : * \param context The thing that should be checked. It is directly
93 : : * passed to the checks.
94 : : *
95 : : * \return The action for the ACL entry that first matches the context.
96 : : */
97 : 19 : const Action& execute(const Context& context) const {
98 : 116 : const typename Entries::const_iterator end(entries_.end());
99 [ + + ][ + + ]: 187 : for (typename Entries::const_iterator i(entries_.begin()); i != end;
100 : : ++i) {
101 [ + + ][ + + ]: 147 : if (i->first->matches(context)) {
[ + ]
102 : 76 : return (i->second);
103 : : }
104 : : }
105 : 48 : return (default_action_);
106 : : }
107 : :
108 : : /**
109 : : * \brief Add new entry at the end of the list.
110 : : *
111 : : * \note We currently allow only adding at the end. This is enough for now,
112 : : * but we may need more when we start implementing some kind optimisations,
113 : : * including replacements, reorderings and removals.
114 : : *
115 : : * \param check The check to test if the thing matches.
116 : : * \param action The action to return when the thing matches this check.
117 : : */
118 : 168 : void append(ConstCheckPtr check, const Action& action) {
119 : 168 : entries_.push_back(Entry(check, action));
120 : 168 : }
121 : : private:
122 : : // Just type abbreviations.
123 : : typedef std::pair<ConstCheckPtr, Action> Entry;
124 : : typedef std::vector<Entry> Entries;
125 : : /// \brief The default action, when nothing mathes.
126 : : const Action default_action_;
127 : : /// \brief The entries we have.
128 : : Entries entries_;
129 : : protected:
130 : : /**
131 : : * \brief Get the default action.
132 : : *
133 : : * This is for testing purposes only.
134 : : */
135 : : const Action& getDefaultAction() const {
136 : : return (default_action_);
137 : : }
138 : : };
139 : :
140 : : }
141 : : }
142 : :
143 : : #endif
|