Load IPMI provider libraries into net-ipmid
The logic to scan /usr/lib/net-ipmid for shared libraries
and load them and the callback function to register commands
to command table.
Change-Id: Ib09cce5a9b418171822208d1d7b322e4b1c8b2b9
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
diff --git a/provider_registration.cpp b/provider_registration.cpp
new file mode 100644
index 0000000..aaa397c
--- /dev/null
+++ b/provider_registration.cpp
@@ -0,0 +1,103 @@
+#include <dirent.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <iostream>
+
+#include <host-ipmid/ipmid-api.h>
+#include "command_table.hpp"
+#include "main.hpp"
+#include "provider_registration.hpp"
+
+namespace provider
+{
+
+int handler_select(const struct dirent* entry)
+{
+ // Check for versioned libraries .so.*
+ if (strstr(entry->d_name, PROVIDER_SONAME_EXTN))
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void registerCallbackHandlers(const char* providerLibPath)
+{
+ if (providerLibPath == NULL)
+ {
+ std::cerr << "Path not provided for registering IPMI provider libraries"
+ << "\n";
+ return;
+ }
+
+ struct dirent** handlerList = nullptr;
+ std::string handlerPath(providerLibPath);
+
+ auto numLibs = scandir(providerLibPath, &handlerList, handler_select,
+ alphasort);
+ if (numLibs < 0)
+ {
+ return;
+ }
+
+ // dlopen each IPMI provider shared library
+ while (numLibs--)
+ {
+ handlerPath = providerLibPath;
+ handlerPath += handlerList[numLibs]->d_name;
+ std::cout << "Registering handler: " << handlerPath << "\n";
+
+ auto lib_handler = dlopen(handlerPath.c_str(), RTLD_NOW);
+
+ if (lib_handler == NULL)
+ {
+ std::cerr << "Error opening " << handlerPath << dlerror() << "\n";
+ }
+ free(handlerList[numLibs]);
+ }
+
+ free(handlerList);
+}
+
+} // namespace provider
+
+/*
+ * @brief Method that gets called from IPMI provider shared libraries to get
+ * the command handlers registered.
+ *
+ * When the IPMI provider shared library is loaded, the dynamic loader program
+ * looks for special section(.ctors on ELF) which contains references to the
+ * functions marked with the constructor attributes. This function is invoked
+ * in such manner.
+ *
+ * @param[in] netfn - Network Function code
+ * @param[in] cmd - Command
+ * @param[in] context - User specific data
+ * @param[in] handler - The callback routine for the command
+ * @param[in] priv - IPMI Command Prvilege
+ */
+void ipmi_register_callback(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_context_t context,
+ ipmid_callback_t handler, ipmi_cmd_privilege priv)
+{
+ uint16_t netFn = netfn << 10;
+
+ // The payload type of IPMI commands provided by the shared libraries
+ // is IPMI
+ command::CommandID command =
+ {
+ ((static_cast<uint32_t>(message::PayloadType::IPMI)) << 16) |
+ netFn | cmd
+ };
+
+ std::get<command::Table&>(singletonPool).registerCommand(command,
+ std::make_unique<command::ProviderIpmidEntry>
+ (command, handler, static_cast<session::Privilege>(priv)));
+}
+
+