| #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 Privilege |
| */ |
| void ipmi_register_callback(ipmi_netfn_t netfn, ipmi_cmd_t cmd, |
| ipmi_context_t context, |
| ipmid_callback_t handler, ipmi_cmd_privilege_t 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))); |
| } |
| |
| |