summaryrefslogtreecommitdiffstats
path: root/include/ipmid
diff options
context:
space:
mode:
authorVernon Mauery <vernon.mauery@linux.intel.com>2018-11-07 09:36:22 -0800
committerVernon Mauery <vernon.mauery@linux.intel.com>2019-02-25 14:27:21 -0800
commit08a70aa56bebfb087ccafdcac293da36f88b672f (patch)
tree18fc307ccfebed793c4b91d740f985af714c4365 /include/ipmid
parentf984a01ffd001740bed3f9207912c1e1ad41dc90 (diff)
downloadphosphor-host-ipmid-08a70aa56bebfb087ccafdcac293da36f88b672f.tar.gz
phosphor-host-ipmid-08a70aa56bebfb087ccafdcac293da36f88b672f.zip
ipmid: Add command filter mechanism
Every ipmi command will pass through a filter prior to execution by the registered handler. The filter consists of all registered filter handlers that all must either return an IPMI error code or allow the command to be executed. If any of the filter handlers return an error code, the remaining handlers will not get a chance to run. Each handler, executed in registered priority order, can be passed the full message, or just the context (metadata describing the command, netfn, cmd, etc.) Change-Id: I3c48f19ebae0d24344b15fbcd2b940a32f8511d7 Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
Diffstat (limited to 'include/ipmid')
-rw-r--r--include/ipmid/filter.hpp94
-rw-r--r--include/ipmid/registration.hpp36
2 files changed, 130 insertions, 0 deletions
diff --git a/include/ipmid/filter.hpp b/include/ipmid/filter.hpp
new file mode 100644
index 0000000..3cd5d21
--- /dev/null
+++ b/include/ipmid/filter.hpp
@@ -0,0 +1,94 @@
+/**
+ * Copyright © 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+#include <algorithm>
+#include <boost/callable_traits.hpp>
+#include <cstdint>
+#include <ipmid/api.hpp>
+#include <ipmid/message.hpp>
+#include <memory>
+#include <tuple>
+#include <utility>
+
+namespace ipmi
+{
+
+using FilterFunction = ipmi::Cc(ipmi::message::Request::ptr);
+
+/**
+ * @brief Filter base class for dealing with IPMI request/response
+ *
+ * The subclasses are all templated so they can provide access to any type of
+ * command callback functions.
+ */
+class FilterBase
+{
+ public:
+ using ptr = std::shared_ptr<FilterBase>;
+
+ virtual ipmi::Cc call(message::Request::ptr request) = 0;
+};
+
+/**
+ * @brief filter concrete class
+ *
+ * This is the base template that ipmi filters will resolve into. This is
+ * essentially just a wrapper to hold the filter callback so it can be stored in
+ * the filter list.
+ *
+ * Filters are called with a ipmi::message::Request shared_ptr on all IPMI
+ * commands in priority order and each filter has the opportunity to reject the
+ * command (by returning an IPMI error competion code.) If all the filters
+ * return success, the actual IPMI command will be executed. Filters can reject
+ * the command for any reason, based on system state, the context, the command
+ * payload, etc.
+ */
+template <typename Filter>
+class IpmiFilter : public FilterBase
+{
+ public:
+ IpmiFilter(Filter&& filter) : filter_(std::move(filter))
+ {
+ }
+
+ ipmi::Cc call(message::Request::ptr request) override
+ {
+ return filter_(request);
+ }
+
+ private:
+ Filter filter_;
+};
+
+/**
+ * @brief helper function to construct a filter object
+ *
+ * This is called internally by the ipmi::registerFilter function.
+ */
+template <typename Filter>
+static inline auto makeFilter(Filter&& filter)
+{
+ FilterBase::ptr ptr(new IpmiFilter<Filter>(std::forward<Filter>(filter)));
+ return ptr;
+}
+template <typename Filter>
+static inline auto makeFilter(const Filter& filter)
+{
+ Filter lFilter = filter;
+ return makeFilter(std::forward<Filter>(lFilter));
+}
+
+} // namespace ipmi
diff --git a/include/ipmid/registration.hpp b/include/ipmid/registration.hpp
index af89bc8..45391ec 100644
--- a/include/ipmid/registration.hpp
+++ b/include/ipmid/registration.hpp
@@ -16,6 +16,7 @@
#pragma once
#include <ipmid/api.hpp>
+#include <ipmid/filter.hpp>
#include <ipmid/handler.hpp>
namespace ipmi
@@ -32,6 +33,9 @@ bool registerGroupHandler(int prio, Group group, Cmd cmd, Privilege priv,
bool registerOemHandler(int prio, Iana iana, Cmd cmd, Privilege priv,
::ipmi::HandlerBase::ptr handler);
+// IPMI command filter registration implementation
+void registerFilter(int prio, ::ipmi::FilterBase::ptr filter);
+
} // namespace impl
/**
@@ -132,6 +136,38 @@ void registerOemHandler(int prio, Iana iana, Cmd cmd, Privilege priv,
impl::registerOemHandler(prio, iana, cmd, priv, h);
}
+/**
+ * @brief IPMI command filter registration function
+ *
+ * This function should be used to register IPMI command filter functions.
+ * This function just passes the callback to makeFilter, which creates a
+ * wrapper functor object that ultimately calls the callback.
+ *
+ * Filters are called with a ipmi::message::Request shared_ptr on all IPMI
+ * commands in priority order and each filter has the opportunity to reject the
+ * command (by returning an IPMI error competion code.) If all the filters
+ * return success, the actual IPMI command will be executed. Filters can reject
+ * the command for any reason, based on system state, the context, the command
+ * payload, etc.
+ *
+ * @param prio - priority at which to register; see api.hpp
+ * @param filter - the callback function that will handle this request
+ *
+ * @return bool - success of registering the handler
+ */
+template <typename Filter>
+void registerFilter(int prio, Filter&& filter)
+{
+ auto f = ipmi::makeFilter(std::forward<Filter>(filter));
+ impl::registerFilter(prio, f);
+}
+
+template <typename Filter>
+void registerFilter(int prio, const Filter& filter)
+{
+ auto f = ipmi::makeFilter(filter);
+ impl::registerFilter(prio, f);
+}
} // namespace ipmi
#ifdef ALLOW_DEPRECATED_API
OpenPOWER on IntegriCloud