1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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 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)));
}
|