blob: 98945a4549b18bdb2777760b12950e2696cb5238 [file] [log] [blame]
Tom485038e2016-12-02 13:44:45 +05301#include <dirent.h>
2#include <dlfcn.h>
3#include <stdlib.h>
4#include <string.h>
5
6#include <iostream>
7
8#include <host-ipmid/ipmid-api.h>
9#include "command_table.hpp"
10#include "main.hpp"
11#include "provider_registration.hpp"
12
13namespace provider
14{
15
16int handler_select(const struct dirent* entry)
17{
18 // Check for versioned libraries .so.*
19 if (strstr(entry->d_name, PROVIDER_SONAME_EXTN))
20 {
21 return 1;
22 }
23 else
24 {
25 return 0;
26 }
27}
28
29void registerCallbackHandlers(const char* providerLibPath)
30{
31 if (providerLibPath == NULL)
32 {
33 std::cerr << "Path not provided for registering IPMI provider libraries"
34 << "\n";
35 return;
36 }
37
38 struct dirent** handlerList = nullptr;
39 std::string handlerPath(providerLibPath);
40
41 auto numLibs = scandir(providerLibPath, &handlerList, handler_select,
42 alphasort);
43 if (numLibs < 0)
44 {
45 return;
46 }
47
48 // dlopen each IPMI provider shared library
49 while (numLibs--)
50 {
51 handlerPath = providerLibPath;
52 handlerPath += handlerList[numLibs]->d_name;
53 std::cout << "Registering handler: " << handlerPath << "\n";
54
55 auto lib_handler = dlopen(handlerPath.c_str(), RTLD_NOW);
56
57 if (lib_handler == NULL)
58 {
59 std::cerr << "Error opening " << handlerPath << dlerror() << "\n";
60 }
61 free(handlerList[numLibs]);
62 }
63
64 free(handlerList);
65}
66
67} // namespace provider
68
69/*
70 * @brief Method that gets called from IPMI provider shared libraries to get
71 * the command handlers registered.
72 *
73 * When the IPMI provider shared library is loaded, the dynamic loader program
74 * looks for special section(.ctors on ELF) which contains references to the
75 * functions marked with the constructor attributes. This function is invoked
76 * in such manner.
77 *
78 * @param[in] netfn - Network Function code
79 * @param[in] cmd - Command
80 * @param[in] context - User specific data
81 * @param[in] handler - The callback routine for the command
Tom Joseph935606c2017-01-27 10:53:33 +053082 * @param[in] priv - IPMI Command Privilege
Tom485038e2016-12-02 13:44:45 +053083 */
84void ipmi_register_callback(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
85 ipmi_context_t context,
Tom Joseph935606c2017-01-27 10:53:33 +053086 ipmid_callback_t handler, ipmi_cmd_privilege_t priv)
Tom485038e2016-12-02 13:44:45 +053087{
88 uint16_t netFn = netfn << 10;
89
90 // The payload type of IPMI commands provided by the shared libraries
91 // is IPMI
92 command::CommandID command =
93 {
94 ((static_cast<uint32_t>(message::PayloadType::IPMI)) << 16) |
95 netFn | cmd
96 };
97
98 std::get<command::Table&>(singletonPool).registerCommand(command,
99 std::make_unique<command::ProviderIpmidEntry>
100 (command, handler, static_cast<session::Privilege>(priv)));
101}
102
103