blob: 1d5c8cfe583f4aff6e6d9b2daad7169c364415e0 [file] [log] [blame]
vishwabmcba0bd5f2015-09-30 16:50:23 +05301#include <stdio.h>
2#include <dlfcn.h>
3#include <iostream>
4#include <unistd.h>
5#include <assert.h>
6#include <dirent.h>
Chris Austen0ba649e2015-10-13 12:28:13 -05007#include <systemd/sd-bus.h>
vishwabmcba0bd5f2015-09-30 16:50:23 +05308#include <string.h>
9#include <stdlib.h>
10#include <map>
Andrew Geissler93c679b2017-04-02 10:06:43 -050011#include <phosphor-logging/log.hpp>
Patrick Williams53a360e2016-08-12 22:01:02 -050012#include "ipmid.hpp"
Chris Austen0ba649e2015-10-13 12:28:13 -050013#include <sys/time.h>
14#include <errno.h>
Brad Bishop35518682016-07-22 08:35:41 -040015#include <mapper.h>
Chris Austen0012e9b2015-10-22 01:37:46 -050016#include "sensorhandler.h"
Tom Joseph9a61b4f2016-07-11 06:56:11 -050017#include <vector>
18#include <algorithm>
19#include <iterator>
Patrick Williams4b9efaa2016-08-12 21:59:51 -050020#include <ipmiwhitelist.hpp>
Chris Austen0ba649e2015-10-13 12:28:13 -050021
Andrew Geissler93c679b2017-04-02 10:06:43 -050022using namespace phosphor::logging;
23
Chris Austen0ba649e2015-10-13 12:28:13 -050024sd_bus *bus = NULL;
vishwab9f559a2016-01-13 01:53:08 -060025sd_bus_slot *ipmid_slot = NULL;
Andrew Geissler93c679b2017-04-02 10:06:43 -050026sd_event *events = nullptr;
Chris Austen30195fa2015-11-13 14:39:19 -060027
Tom Joseph9a61b4f2016-07-11 06:56:11 -050028// Initialise restricted mode to true
29bool restricted_mode = true;
30
Chris Austen41a4b312015-10-25 03:45:42 -050031FILE *ipmiio, *ipmidbus, *ipmicmddetails;
vishwabmcba0bd5f2015-09-30 16:50:23 +053032
Chris Austen99497312015-10-22 13:00:16 -050033void print_usage(void) {
34 fprintf(stderr, "Options: [-d mask]\n");
35 fprintf(stderr, " mask : 0x01 - Print ipmi packets\n");
36 fprintf(stderr, " mask : 0x02 - Print DBUS operations\n");
37 fprintf(stderr, " mask : 0x04 - Print ipmi command details\n");
38 fprintf(stderr, " mask : 0xFF - Print all trace\n");
39}
40
Tom Joseph9a61b4f2016-07-11 06:56:11 -050041// Host settings in DBUS
Tom Joseph9a61b4f2016-07-11 06:56:11 -050042constexpr char settings_host_object[] = "/org/openbmc/settings/host0";
43constexpr char settings_host_intf[] = "org.freedesktop.DBus.Properties";
44
Jeremy Kerre41081f2015-10-27 12:11:36 +080045const char * DBUS_INTF = "org.openbmc.HostIpmi";
vishwabmcba0bd5f2015-09-30 16:50:23 +053046
Jeremy Kerre41081f2015-10-27 12:11:36 +080047const char * FILTER = "type='signal',interface='org.openbmc.HostIpmi',member='ReceivedMessage'";
Tom Joseph9a61b4f2016-07-11 06:56:11 -050048constexpr char RESTRICTED_MODE_FILTER[] = "type='signal',interface='org.freedesktop.DBus.Properties',path='/org/openbmc/settings/host0'";
Chris Austen0ba649e2015-10-13 12:28:13 -050049
vishwabmcba0bd5f2015-09-30 16:50:23 +053050typedef std::pair<ipmi_netfn_t, ipmi_cmd_t> ipmi_fn_cmd_t;
51typedef std::pair<ipmid_callback_t, ipmi_context_t> ipmi_fn_context_t;
52
53// Global data structure that contains the IPMI command handler's registrations.
54std::map<ipmi_fn_cmd_t, ipmi_fn_context_t> g_ipmid_router_map;
55
Nan Li36c0cb62016-03-31 11:16:08 +080056// IPMI Spec, shared Reservation ID.
57unsigned short g_sel_reserve = 0xFFFF;
58
59unsigned short get_sel_reserve_id(void)
60{
61 return g_sel_reserve;
62}
Chris Austen0ba649e2015-10-13 12:28:13 -050063
Chris Austen0ba649e2015-10-13 12:28:13 -050064#ifndef HEXDUMP_COLS
65#define HEXDUMP_COLS 16
66#endif
67
Chris Austen99497312015-10-22 13:00:16 -050068void hexdump(FILE *s, void *mem, size_t len)
Chris Austen0ba649e2015-10-13 12:28:13 -050069{
70 unsigned int i, j;
Chris Austen120f7322015-10-14 23:27:31 -050071
Chris Austen0ba649e2015-10-13 12:28:13 -050072 for(i = 0; i < len + ((len % HEXDUMP_COLS) ? (HEXDUMP_COLS - len % HEXDUMP_COLS) : 0); i++)
73 {
74 /* print offset */
75 if(i % HEXDUMP_COLS == 0)
76 {
Chris Austen99497312015-10-22 13:00:16 -050077 fprintf(s,"0x%06x: ", i);
Chris Austen0ba649e2015-10-13 12:28:13 -050078 }
Chris Austen120f7322015-10-14 23:27:31 -050079
Chris Austen0ba649e2015-10-13 12:28:13 -050080 /* print hex data */
81 if(i < len)
82 {
Chris Austen99497312015-10-22 13:00:16 -050083 fprintf(s,"%02x ", 0xFF & ((char*)mem)[i]);
Chris Austen0ba649e2015-10-13 12:28:13 -050084 }
85 else /* end of block, just aligning for ASCII dump */
86 {
Chris Austen99497312015-10-22 13:00:16 -050087 fprintf(s," ");
Chris Austen0ba649e2015-10-13 12:28:13 -050088 }
Chris Austen120f7322015-10-14 23:27:31 -050089
Chris Austen0ba649e2015-10-13 12:28:13 -050090 /* print ASCII dump */
91 if(i % HEXDUMP_COLS == (HEXDUMP_COLS - 1))
92 {
93 for(j = i - (HEXDUMP_COLS - 1); j <= i; j++)
94 {
95 if(j >= len) /* end of block, not really printing */
96 {
Chris Austen99497312015-10-22 13:00:16 -050097 fputc(' ', s);
Chris Austen0ba649e2015-10-13 12:28:13 -050098 }
99 else if(isprint(((char*)mem)[j])) /* printable char */
100 {
Chris Austen99497312015-10-22 13:00:16 -0500101 fputc(0xFF & ((char*)mem)[j], s);
Chris Austen0ba649e2015-10-13 12:28:13 -0500102 }
103 else /* other char */
104 {
Chris Austen99497312015-10-22 13:00:16 -0500105 fputc('.',s);
Chris Austen0ba649e2015-10-13 12:28:13 -0500106 }
107 }
Chris Austen99497312015-10-22 13:00:16 -0500108 fputc('\n',s);
Chris Austen0ba649e2015-10-13 12:28:13 -0500109 }
110 }
111}
112
113
vishwabmcba0bd5f2015-09-30 16:50:23 +0530114// Method that gets called by shared libraries to get their command handlers registered
Tom05732372016-09-06 17:21:23 +0530115void ipmi_register_callback(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_context_t context,
116 ipmid_callback_t handler, ipmi_cmd_privilege_t priv)
vishwabmcba0bd5f2015-09-30 16:50:23 +0530117{
118 // Pack NetFn and Command in one.
119 auto netfn_and_cmd = std::make_pair(netfn, cmd);
120
121 // Pack Function handler and Data in another.
122 auto handler_and_context = std::make_pair(handler, context);
123
124 // Check if the registration has already been made..
125 auto iter = g_ipmid_router_map.find(netfn_and_cmd);
126 if(iter != g_ipmid_router_map.end())
127 {
128 fprintf(stderr,"ERROR : Duplicate registration for NetFn [0x%X], Cmd:[0x%X]\n",netfn, cmd);
129 }
130 else
131 {
132 // This is a fresh registration.. Add it to the map.
133 g_ipmid_router_map.emplace(netfn_and_cmd, handler_and_context);
134 }
135
136 return;
137}
138
139// Looks at the map and calls corresponding handler functions.
140ipmi_ret_t ipmi_netfn_router(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
141 ipmi_response_t response, ipmi_data_len_t data_len)
142{
143 // return from the Command handlers.
144 ipmi_ret_t rc = IPMI_CC_INVALID;
145
Tom Joseph9a61b4f2016-07-11 06:56:11 -0500146 // If restricted mode is true and command is not whitelisted, don't
147 // execute the command
148 if(restricted_mode)
149 {
150 if (!std::binary_search(whitelist.cbegin(), whitelist.cend(),
151 std::make_pair(netfn, cmd)))
152 {
153 printf("Net function:[0x%X], Command:[0x%X] is not whitelisted\n",
154 netfn, cmd);
155 rc = IPMI_CC_INSUFFICIENT_PRIVILEGE;
156 memcpy(response, &rc, IPMI_CC_LEN);
157 *data_len = IPMI_CC_LEN;
158 return rc;
159 }
160 }
161
vishwabmcba0bd5f2015-09-30 16:50:23 +0530162 // Walk the map that has the registered handlers and invoke the approprite
163 // handlers for matching commands.
164 auto iter = g_ipmid_router_map.find(std::make_pair(netfn, cmd));
165 if(iter == g_ipmid_router_map.end())
166 {
Chris Austen99497312015-10-22 13:00:16 -0500167 fprintf(stderr, "No registered handlers for NetFn:[0x%X], Cmd:[0x%X]"
vishwabmcba0bd5f2015-09-30 16:50:23 +0530168 " trying Wilcard implementation \n",netfn, cmd);
169
170 // Now that we did not find any specific [NetFn,Cmd], tuple, check for
171 // NetFn, WildCard command present.
172 iter = g_ipmid_router_map.find(std::make_pair(netfn, IPMI_CMD_WILDCARD));
173 if(iter == g_ipmid_router_map.end())
174 {
Chris Austen99497312015-10-22 13:00:16 -0500175 fprintf(stderr, "No Registered handlers for NetFn:[0x%X],Cmd:[0x%X]\n",netfn, IPMI_CMD_WILDCARD);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530176
177 // Respond with a 0xC1
178 memcpy(response, &rc, IPMI_CC_LEN);
179 *data_len = IPMI_CC_LEN;
180 return rc;
181 }
182 }
183
184#ifdef __IPMI_DEBUG__
185 // We have either a perfect match -OR- a wild card atleast,
186 printf("Calling Net function:[0x%X], Command:[0x%X]\n", netfn, cmd);
187#endif
188
189 // Extract the map data onto appropriate containers
190 auto handler_and_context = iter->second;
191
192 // Creating a pointer type casted to char* to make sure we advance 1 byte
193 // when we advance pointer to next's address. advancing void * would not
194 // make sense.
195 char *respo = &((char *)response)[IPMI_CC_LEN];
196
197 // Response message from the plugin goes into a byte post the base response
198 rc = (handler_and_context.first) (netfn, cmd, request, respo,
199 data_len, handler_and_context.second);
Chris Austen120f7322015-10-14 23:27:31 -0500200
vishwabmcba0bd5f2015-09-30 16:50:23 +0530201 // Now copy the return code that we got from handler and pack it in first
202 // byte.
203 memcpy(response, &rc, IPMI_CC_LEN);
Chris Austen120f7322015-10-14 23:27:31 -0500204
vishwabmcba0bd5f2015-09-30 16:50:23 +0530205 // Data length is now actual data + completion code.
206 *data_len = *data_len + IPMI_CC_LEN;
207
208 return rc;
209}
210
vishwabmcba0bd5f2015-09-30 16:50:23 +0530211
vishwabmcba0bd5f2015-09-30 16:50:23 +0530212
vishwabmcba0bd5f2015-09-30 16:50:23 +0530213
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800214static int send_ipmi_message(sd_bus_message *req, unsigned char seq, unsigned char netfn, unsigned char lun, unsigned char cmd, unsigned char cc, unsigned char *buf, unsigned char len) {
vishwabmcba0bd5f2015-09-30 16:50:23 +0530215
Chris Austen0ba649e2015-10-13 12:28:13 -0500216 sd_bus_error error = SD_BUS_ERROR_NULL;
217 sd_bus_message *reply = NULL, *m=NULL;
Jeremy Kerre41081f2015-10-27 12:11:36 +0800218 const char *dest, *path;
Chris Austen0ba649e2015-10-13 12:28:13 -0500219 int r, pty;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530220
Jeremy Kerre41081f2015-10-27 12:11:36 +0800221 dest = sd_bus_message_get_sender(req);
222 path = sd_bus_message_get_path(req);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530223
Jeremy Kerre41081f2015-10-27 12:11:36 +0800224 r = sd_bus_message_new_method_call(bus,&m,dest,path,DBUS_INTF,"sendMessage");
Chris Austen0ba649e2015-10-13 12:28:13 -0500225 if (r < 0) {
226 fprintf(stderr, "Failed to add the method object: %s\n", strerror(-r));
227 return -1;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530228 }
229
vishwabmcba0bd5f2015-09-30 16:50:23 +0530230
Chris Austenabfb5e82015-10-13 12:29:24 -0500231 // Responses in IPMI require a bit set. So there ya go...
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800232 netfn |= 0x01;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530233
Chris Austen0ba649e2015-10-13 12:28:13 -0500234
235 // Add the bytes needed for the methods to be called
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800236 r = sd_bus_message_append(m, "yyyyy", seq, netfn, lun, cmd, cc);
Chris Austen0ba649e2015-10-13 12:28:13 -0500237 if (r < 0) {
238 fprintf(stderr, "Failed add the netfn and others : %s\n", strerror(-r));
Chris Austen169395e2015-12-02 20:56:15 -0600239 goto final;
Chris Austen0ba649e2015-10-13 12:28:13 -0500240 }
Chris Austen120f7322015-10-14 23:27:31 -0500241
Chris Austen0ba649e2015-10-13 12:28:13 -0500242 r = sd_bus_message_append_array(m, 'y', buf, len);
243 if (r < 0) {
244 fprintf(stderr, "Failed to add the string of response bytes: %s\n", strerror(-r));
Chris Austen169395e2015-12-02 20:56:15 -0600245 goto final;
Chris Austen0ba649e2015-10-13 12:28:13 -0500246 }
247
248
249
250 // Call the IPMI responder on the bus so the message can be sent to the CEC
251 r = sd_bus_call(bus, m, 0, &error, &reply);
252 if (r < 0) {
Chris Austen169395e2015-12-02 20:56:15 -0600253 fprintf(stderr, "Failed to call the method: %s\n", strerror(-r));
Chris Austen6bd23962015-12-07 21:31:48 -0600254 fprintf(stderr, "Dest: %s, Path: %s\n", dest, path);
Chris Austen169395e2015-12-02 20:56:15 -0600255 goto final;
Chris Austen0ba649e2015-10-13 12:28:13 -0500256 }
257
258 r = sd_bus_message_read(reply, "x", &pty);
Chris Austen0ba649e2015-10-13 12:28:13 -0500259 if (r < 0) {
260 fprintf(stderr, "Failed to get a rc from the method: %s\n", strerror(-r));
Chris Austen0ba649e2015-10-13 12:28:13 -0500261 }
262
Chris Austen169395e2015-12-02 20:56:15 -0600263final:
Chris Austen0ba649e2015-10-13 12:28:13 -0500264 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600265 m = sd_bus_message_unref(m);
266 reply = sd_bus_message_unref(reply);
Chris Austen0ba649e2015-10-13 12:28:13 -0500267
Chris Austen0ba649e2015-10-13 12:28:13 -0500268 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
Chris Austen0ba649e2015-10-13 12:28:13 -0500269}
270
Tom Joseph9a61b4f2016-07-11 06:56:11 -0500271void cache_restricted_mode()
272{
273 sd_bus *bus = ipmid_get_sd_bus_connection();
274 sd_bus_message *reply = NULL;
275 sd_bus_error error = SD_BUS_ERROR_NULL;
276 int rc = 0;
Sergey Solomineb9b8142016-08-23 09:07:28 -0500277 char *busname = NULL;
Tom Joseph9a61b4f2016-07-11 06:56:11 -0500278
Sergey Solomineb9b8142016-08-23 09:07:28 -0500279 rc = mapper_get_service(bus, settings_host_object, &busname);
280 if (rc < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -0400281 fprintf(stderr, "Failed to get %s busname: %s\n",
282 settings_host_object, strerror(-rc));
Sergey Solomineb9b8142016-08-23 09:07:28 -0500283 goto cleanup;
284 }
Tom Joseph9a61b4f2016-07-11 06:56:11 -0500285 rc = sd_bus_call_method(bus,
Sergey Solomineb9b8142016-08-23 09:07:28 -0500286 busname,
Tom Joseph9a61b4f2016-07-11 06:56:11 -0500287 settings_host_object,
288 settings_host_intf,
289 "Get",
290 &error,
291 &reply,
292 "ss",
Sergey Solomineb9b8142016-08-23 09:07:28 -0500293 "org.openbmc.settings.Host",
Tom Joseph9a61b4f2016-07-11 06:56:11 -0500294 "restricted_mode");
295 if(rc < 0)
296 {
297 fprintf(stderr, "Failed sd_bus_call_method method for restricted mode: %s\n",
298 strerror(-rc));
299 goto cleanup;
300 }
301
302 rc = sd_bus_message_read(reply, "v", "b", &restricted_mode);
303 if(rc < 0)
304 {
305 fprintf(stderr, "Failed to parse response message for restricted mode: %s\n",
306 strerror(-rc));
307 // Fail-safe to restricted mode
308 restricted_mode = true;
309 }
310
311 printf("Restricted mode = %d\n", restricted_mode);
312
313cleanup:
314 sd_bus_error_free(&error);
315 reply = sd_bus_message_unref(reply);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500316 free(busname);
Tom Joseph9a61b4f2016-07-11 06:56:11 -0500317}
318
319static int handle_restricted_mode_change(sd_bus_message *m, void *user_data,
320 sd_bus_error *ret_error)
321{
322 cache_restricted_mode();
323 return 0;
324}
325
Chris Austen0ba649e2015-10-13 12:28:13 -0500326static int handle_ipmi_command(sd_bus_message *m, void *user_data, sd_bus_error
327 *ret_error) {
328 int r = 0;
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800329 unsigned char sequence, netfn, lun, cmd;
Chris Austen0ba649e2015-10-13 12:28:13 -0500330 const void *request;
331 size_t sz;
332 size_t resplen =MAX_IPMI_BUFFER;
333 unsigned char response[MAX_IPMI_BUFFER];
334
Chris Austen0ba649e2015-10-13 12:28:13 -0500335 memset(response, 0, MAX_IPMI_BUFFER);
336
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800337 r = sd_bus_message_read(m, "yyyy", &sequence, &netfn, &lun, &cmd);
Chris Austen0ba649e2015-10-13 12:28:13 -0500338 if (r < 0) {
339 fprintf(stderr, "Failed to parse signal message: %s\n", strerror(-r));
340 return -1;
341 }
342
343 r = sd_bus_message_read_array(m, 'y', &request, &sz );
344 if (r < 0) {
345 fprintf(stderr, "Failed to parse signal message: %s\n", strerror(-r));
346 return -1;
347 }
348
Chris Austen99497312015-10-22 13:00:16 -0500349 fprintf(ipmiio, "IPMI Incoming: Seq 0x%02x, NetFn 0x%02x, CMD: 0x%02x \n", sequence, netfn, cmd);
350 hexdump(ipmiio, (void*)request, sz);
Chris Austen0ba649e2015-10-13 12:28:13 -0500351
Chris Austen120f7322015-10-14 23:27:31 -0500352 // Allow the length field to be used for both input and output of the
Chris Austen0ba649e2015-10-13 12:28:13 -0500353 // ipmi call
354 resplen = sz;
355
Chris Austen120f7322015-10-14 23:27:31 -0500356 // Now that we have parsed the entire byte array from the caller
vishwabmcba0bd5f2015-09-30 16:50:23 +0530357 // we can call the ipmi router to do the work...
Chris Austen0ba649e2015-10-13 12:28:13 -0500358 r = ipmi_netfn_router(netfn, cmd, (void *)request, (void *)response, &resplen);
359 if(r != 0)
vishwabmcba0bd5f2015-09-30 16:50:23 +0530360 {
Chris Austen0ba649e2015-10-13 12:28:13 -0500361 fprintf(stderr,"ERROR:[0x%X] handling NetFn:[0x%X], Cmd:[0x%X]\n",r, netfn, cmd);
Nan Li80be4b92016-05-23 19:30:49 +0800362
tomjose7ec0add2016-06-27 07:59:28 -0500363 if(r < 0) {
Nan Li80be4b92016-05-23 19:30:49 +0800364 response[0] = IPMI_CC_UNSPECIFIED_ERROR;
365 }
vishwabmcba0bd5f2015-09-30 16:50:23 +0530366 }
367
Chris Austen99497312015-10-22 13:00:16 -0500368 fprintf(ipmiio, "IPMI Response:\n");
369 hexdump(ipmiio, (void*)response, resplen);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530370
Chris Austen0ba649e2015-10-13 12:28:13 -0500371 // Send the response buffer from the ipmi command
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800372 r = send_ipmi_message(m, sequence, netfn, lun, cmd, response[0],
373 ((unsigned char *)response) + 1, resplen - 1);
Chris Austen0ba649e2015-10-13 12:28:13 -0500374 if (r < 0) {
375 fprintf(stderr, "Failed to send the response message\n");
376 return -1;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530377 }
378
vishwabmcba0bd5f2015-09-30 16:50:23 +0530379
Chris Austen0ba649e2015-10-13 12:28:13 -0500380 return 0;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530381}
382
Chris Austen0ba649e2015-10-13 12:28:13 -0500383
vishwabmcba0bd5f2015-09-30 16:50:23 +0530384//----------------------------------------------------------------------
385// handler_select
386// Select all the files ending with with .so. in the given diretcory
387// @d: dirent structure containing the file name
388//----------------------------------------------------------------------
389int handler_select(const struct dirent *entry)
390{
391 // To hold ".so" from entry->d_name;
392 char dname_copy[4] = {0};
393
394 // We want to avoid checking for everything and isolate to the ones having
Adriana Kobylak87e080b2016-07-10 13:16:53 -0500395 // .so.* or .so in them.
396 // Check for versioned libraries .so.*
397 if(strstr(entry->d_name, IPMI_PLUGIN_SONAME_EXTN))
398 {
399 return 1;
400 }
401 // Check for non versioned libraries .so
402 else if(strstr(entry->d_name, IPMI_PLUGIN_EXTN))
vishwabmcba0bd5f2015-09-30 16:50:23 +0530403 {
404 // It is possible that .so could be anywhere in the string but unlikely
Chris Austen120f7322015-10-14 23:27:31 -0500405 // But being careful here. Get the base address of the string, move
vishwabmcba0bd5f2015-09-30 16:50:23 +0530406 // until end and come back 3 steps and that gets what we need.
407 strcpy(dname_copy, (entry->d_name + strlen(entry->d_name)-strlen(IPMI_PLUGIN_EXTN)));
408 if(strcmp(dname_copy, IPMI_PLUGIN_EXTN) == 0)
409 {
410 return 1;
411 }
412 }
413 return 0;
414}
415
416// This will do a dlopen of every .so in ipmi_lib_path and will dlopen everything so that they will
Chris Austen120f7322015-10-14 23:27:31 -0500417// register a callback handler
vishwabmcba0bd5f2015-09-30 16:50:23 +0530418void ipmi_register_callback_handlers(const char* ipmi_lib_path)
419{
420 // For walking the ipmi_lib_path
421 struct dirent **handler_list;
422 int num_handlers = 0;
423
424 // This is used to check and abort if someone tries to register a bad one.
425 void *lib_handler = NULL;
426
427 if(ipmi_lib_path == NULL)
428 {
429 fprintf(stderr,"ERROR; No handlers to be registered for ipmi.. Aborting\n");
430 assert(0);
431 }
432 else
433 {
434 // 1: Open ipmi_lib_path. Its usually "/usr/lib/phosphor-host-ipmid"
435 // 2: Scan the directory for the files that end with .so
Chris Austen120f7322015-10-14 23:27:31 -0500436 // 3: For each one of them, just do a 'dlopen' so that they register
vishwabmcba0bd5f2015-09-30 16:50:23 +0530437 // the handlers for callback routines.
438
439 std::string handler_fqdn = ipmi_lib_path;
Chris Austen120f7322015-10-14 23:27:31 -0500440
vishwabmcba0bd5f2015-09-30 16:50:23 +0530441 // Append a "/" since we need to add the name of the .so. If there is
442 // already a .so, adding one more is not any harm.
443 handler_fqdn += "/";
444
445 num_handlers = scandir(ipmi_lib_path, &handler_list, handler_select, alphasort);
Nan Li36c0cb62016-03-31 11:16:08 +0800446 if (num_handlers < 0)
447 return;
Jeremy Kerr5e8f85e2015-10-27 13:43:54 +0800448
vishwabmcba0bd5f2015-09-30 16:50:23 +0530449 while(num_handlers--)
450 {
Chris Austen54030262015-10-13 12:30:46 -0500451 handler_fqdn = ipmi_lib_path;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530452 handler_fqdn += handler_list[num_handlers]->d_name;
Chris Austen54030262015-10-13 12:30:46 -0500453 printf("Registering handler:[%s]\n",handler_fqdn.c_str());
454
vishwabmcba0bd5f2015-09-30 16:50:23 +0530455 lib_handler = dlopen(handler_fqdn.c_str(), RTLD_NOW);
Nan Li36c0cb62016-03-31 11:16:08 +0800456
vishwabmcba0bd5f2015-09-30 16:50:23 +0530457 if(lib_handler == NULL)
458 {
Chris Austen120f7322015-10-14 23:27:31 -0500459 fprintf(stderr,"ERROR opening [%s]: %s\n",
460 handler_fqdn.c_str(), dlerror());
vishwabmcba0bd5f2015-09-30 16:50:23 +0530461 }
462 // Wipe the memory allocated for this particular entry.
463 free(handler_list[num_handlers]);
464 }
Nan Li36c0cb62016-03-31 11:16:08 +0800465
vishwabmcba0bd5f2015-09-30 16:50:23 +0530466 // Done with all registration.
467 free(handler_list);
468 }
469
470 // TODO : What to be done on the memory that is given by dlopen ?.
471 return;
472}
473
Chris Austen30195fa2015-11-13 14:39:19 -0600474sd_bus *ipmid_get_sd_bus_connection(void) {
475 return bus;
476}
477
Andrew Geissler93c679b2017-04-02 10:06:43 -0500478sd_event *ipmid_get_sd_event_connection(void) {
479 return events;
480}
481
vishwab9f559a2016-01-13 01:53:08 -0600482sd_bus_slot *ipmid_get_sd_bus_slot(void) {
483 return ipmid_slot;
484}
485
vishwabmcba0bd5f2015-09-30 16:50:23 +0530486int main(int argc, char *argv[])
487{
Chris Austen0ba649e2015-10-13 12:28:13 -0500488 int r;
Chris Austen99497312015-10-22 13:00:16 -0500489 unsigned long tvalue;
490 int c;
491
492
493
494 // This file and subsequient switch is for turning on levels
495 // of trace
496 ipmicmddetails = ipmiio = ipmidbus = fopen("/dev/null", "w");
497
498 while ((c = getopt (argc, argv, "h:d:")) != -1)
499 switch (c) {
500 case 'd':
501 tvalue = strtoul(optarg, NULL, 16);
502 if (1&tvalue) {
503 ipmiio = stdout;
504 }
505 if (2&tvalue) {
506 ipmidbus = stdout;
507 }
508 if (4&tvalue) {
509 ipmicmddetails = stdout;
510 }
511 break;
512 case 'h':
513 case '?':
514 print_usage();
515 return 1;
516 }
Chris Austen0ba649e2015-10-13 12:28:13 -0500517
518
Chris Austen0ba649e2015-10-13 12:28:13 -0500519 /* Connect to system bus */
520 r = sd_bus_open_system(&bus);
521 if (r < 0) {
522 fprintf(stderr, "Failed to connect to system bus: %s\n",
523 strerror(-r));
524 goto finish;
525 }
vishwabmcba0bd5f2015-09-30 16:50:23 +0530526
Andrew Geissler93c679b2017-04-02 10:06:43 -0500527 /* Get an sd event handler */
528 r = sd_event_default(&events);
529 if (r < 0)
530 {
531 log<level::ERR>("Failure to create sd_event handler",
532 entry("ERROR=%s", strerror(-r)));
533 goto finish;
534 }
535
536
Chris Austen30195fa2015-11-13 14:39:19 -0600537 // Register all the handlers that provider implementation to IPMI commands.
538 ipmi_register_callback_handlers(HOST_IPMI_LIB_PATH);
539
vishwa36993272015-11-20 12:43:49 -0600540 // Watch for BT messages
vishwab9f559a2016-01-13 01:53:08 -0600541 r = sd_bus_add_match(bus, &ipmid_slot, FILTER, handle_ipmi_command, NULL);
Chris Austen0ba649e2015-10-13 12:28:13 -0500542 if (r < 0) {
543 fprintf(stderr, "Failed: sd_bus_add_match: %s : %s\n", strerror(-r), FILTER);
544 goto finish;
545 }
vishwabmcba0bd5f2015-09-30 16:50:23 +0530546
Tom Joseph9a61b4f2016-07-11 06:56:11 -0500547 // Wait for changes on Restricted mode
548 r = sd_bus_add_match(bus, &ipmid_slot, RESTRICTED_MODE_FILTER, handle_restricted_mode_change, NULL);
549 if (r < 0) {
550 fprintf(stderr, "Failed: sd_bus_add_match: %s : %s\n", strerror(-r), RESTRICTED_MODE_FILTER);
551 goto finish;
552 }
553
Andrew Geissler93c679b2017-04-02 10:06:43 -0500554 // Attach the bus to sd_event to service user requests
555 sd_bus_attach_event(bus, events, SD_EVENT_PRIORITY_NORMAL);
556
557 // Initialize restricted mode
Tom Joseph9a61b4f2016-07-11 06:56:11 -0500558 cache_restricted_mode();
vishwabmcba0bd5f2015-09-30 16:50:23 +0530559
Chris Austen0ba649e2015-10-13 12:28:13 -0500560 for (;;) {
561 /* Process requests */
Andrew Geissler93c679b2017-04-02 10:06:43 -0500562 r = sd_event_run(events, (uint64_t)-1);
563 if (r < 0)
564 {
565 log<level::ERR>("Failure in processing request",
566 entry("ERROR=%s", strerror(-r)));
Chris Austen0ba649e2015-10-13 12:28:13 -0500567 goto finish;
568 }
569 }
570
571finish:
Andrew Geissler93c679b2017-04-02 10:06:43 -0500572 sd_event_unref(events);
573 sd_bus_detach_event(bus);
vishwab9f559a2016-01-13 01:53:08 -0600574 sd_bus_slot_unref(ipmid_slot);
Chris Austen0ba649e2015-10-13 12:28:13 -0500575 sd_bus_unref(bus);
576 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
577
vishwabmcba0bd5f2015-09-30 16:50:23 +0530578}