blob: 1f61ce2556f0f26f9036b7ced11d9af88917df77 [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>
Deepak Kodihalli84b3a082017-07-21 23:44:44 -050011#include <memory>
Andrew Geissler93c679b2017-04-02 10:06:43 -050012#include <phosphor-logging/log.hpp>
Patrick Williams53a360e2016-08-12 22:01:02 -050013#include "ipmid.hpp"
Chris Austen0ba649e2015-10-13 12:28:13 -050014#include <sys/time.h>
15#include <errno.h>
Brad Bishop35518682016-07-22 08:35:41 -040016#include <mapper.h>
Chris Austen0012e9b2015-10-22 01:37:46 -050017#include "sensorhandler.h"
Tom Joseph9a61b4f2016-07-11 06:56:11 -050018#include <vector>
19#include <algorithm>
20#include <iterator>
Patrick Williams4b9efaa2016-08-12 21:59:51 -050021#include <ipmiwhitelist.hpp>
Deepak Kodihalli84b3a082017-07-21 23:44:44 -050022#include <sdbusplus/bus.hpp>
23#include <sdbusplus/bus/match.hpp>
24#include <xyz/openbmc_project/Control/Security/RestrictionMode/server.hpp>
25#include "sensorhandler.h"
26#include "ipmid.hpp"
27#include "settings.hpp"
Vishwanatha Subbanna3eb117a2017-07-12 16:13:49 +053028#include <host-cmd-manager.hpp>
Vishwanatha Subbanna6e8979d2017-07-13 16:48:20 +053029#include <host-ipmid/ipmid-host-cmd.hpp>
30#include <timer.hpp>
Chris Austen0ba649e2015-10-13 12:28:13 -050031
Andrew Geissler93c679b2017-04-02 10:06:43 -050032using namespace phosphor::logging;
Deepak Kodihalli84b3a082017-07-21 23:44:44 -050033namespace sdbusRule = sdbusplus::bus::match::rules;
Andrew Geissler93c679b2017-04-02 10:06:43 -050034
Chris Austen0ba649e2015-10-13 12:28:13 -050035sd_bus *bus = NULL;
vishwab9f559a2016-01-13 01:53:08 -060036sd_bus_slot *ipmid_slot = NULL;
Andrew Geissler93c679b2017-04-02 10:06:43 -050037sd_event *events = nullptr;
Chris Austen30195fa2015-11-13 14:39:19 -060038
Vishwanatha Subbanna3eb117a2017-07-12 16:13:49 +053039// Need this to use new sdbusplus compatible interfaces
40sdbusPtr sdbusp;
41
42// Global Host Bound Command manager
43using cmdManagerPtr = std::unique_ptr<phosphor::host::command::Manager>;
44cmdManagerPtr cmdManager;
45
46// Command and handler tuple. Used when clients ask the command to be put
47// into host message queue
48using CommandHandler = phosphor::host::command::CommandHandler;
49
Tom Joseph9a61b4f2016-07-11 06:56:11 -050050// Initialise restricted mode to true
51bool restricted_mode = true;
52
Chris Austen41a4b312015-10-25 03:45:42 -050053FILE *ipmiio, *ipmidbus, *ipmicmddetails;
vishwabmcba0bd5f2015-09-30 16:50:23 +053054
Chris Austen99497312015-10-22 13:00:16 -050055void print_usage(void) {
56 fprintf(stderr, "Options: [-d mask]\n");
57 fprintf(stderr, " mask : 0x01 - Print ipmi packets\n");
58 fprintf(stderr, " mask : 0x02 - Print DBUS operations\n");
59 fprintf(stderr, " mask : 0x04 - Print ipmi command details\n");
60 fprintf(stderr, " mask : 0xFF - Print all trace\n");
61}
62
Jeremy Kerre41081f2015-10-27 12:11:36 +080063const char * DBUS_INTF = "org.openbmc.HostIpmi";
vishwabmcba0bd5f2015-09-30 16:50:23 +053064
Jeremy Kerre41081f2015-10-27 12:11:36 +080065const char * FILTER = "type='signal',interface='org.openbmc.HostIpmi',member='ReceivedMessage'";
Chris Austen0ba649e2015-10-13 12:28:13 -050066
vishwabmcba0bd5f2015-09-30 16:50:23 +053067typedef std::pair<ipmi_netfn_t, ipmi_cmd_t> ipmi_fn_cmd_t;
68typedef std::pair<ipmid_callback_t, ipmi_context_t> ipmi_fn_context_t;
69
70// Global data structure that contains the IPMI command handler's registrations.
71std::map<ipmi_fn_cmd_t, ipmi_fn_context_t> g_ipmid_router_map;
72
Nan Li36c0cb62016-03-31 11:16:08 +080073// IPMI Spec, shared Reservation ID.
74unsigned short g_sel_reserve = 0xFFFF;
75
76unsigned short get_sel_reserve_id(void)
77{
78 return g_sel_reserve;
79}
Chris Austen0ba649e2015-10-13 12:28:13 -050080
Deepak Kodihalli84b3a082017-07-21 23:44:44 -050081namespace internal
82{
83
84constexpr auto restrictionModeIntf =
85 "xyz.openbmc_project.Control.Security.RestrictionMode";
86
87namespace cache
88{
89
90std::unique_ptr<settings::Objects> objects = nullptr;
91
92} // namespace cache
93} // namespace internal
94
Chris Austen0ba649e2015-10-13 12:28:13 -050095#ifndef HEXDUMP_COLS
96#define HEXDUMP_COLS 16
97#endif
98
Chris Austen99497312015-10-22 13:00:16 -050099void hexdump(FILE *s, void *mem, size_t len)
Chris Austen0ba649e2015-10-13 12:28:13 -0500100{
101 unsigned int i, j;
Chris Austen120f7322015-10-14 23:27:31 -0500102
Chris Austen0ba649e2015-10-13 12:28:13 -0500103 for(i = 0; i < len + ((len % HEXDUMP_COLS) ? (HEXDUMP_COLS - len % HEXDUMP_COLS) : 0); i++)
104 {
105 /* print offset */
106 if(i % HEXDUMP_COLS == 0)
107 {
Chris Austen99497312015-10-22 13:00:16 -0500108 fprintf(s,"0x%06x: ", i);
Chris Austen0ba649e2015-10-13 12:28:13 -0500109 }
Chris Austen120f7322015-10-14 23:27:31 -0500110
Chris Austen0ba649e2015-10-13 12:28:13 -0500111 /* print hex data */
112 if(i < len)
113 {
Chris Austen99497312015-10-22 13:00:16 -0500114 fprintf(s,"%02x ", 0xFF & ((char*)mem)[i]);
Chris Austen0ba649e2015-10-13 12:28:13 -0500115 }
116 else /* end of block, just aligning for ASCII dump */
117 {
Chris Austen99497312015-10-22 13:00:16 -0500118 fprintf(s," ");
Chris Austen0ba649e2015-10-13 12:28:13 -0500119 }
Chris Austen120f7322015-10-14 23:27:31 -0500120
Chris Austen0ba649e2015-10-13 12:28:13 -0500121 /* print ASCII dump */
122 if(i % HEXDUMP_COLS == (HEXDUMP_COLS - 1))
123 {
124 for(j = i - (HEXDUMP_COLS - 1); j <= i; j++)
125 {
126 if(j >= len) /* end of block, not really printing */
127 {
Chris Austen99497312015-10-22 13:00:16 -0500128 fputc(' ', s);
Chris Austen0ba649e2015-10-13 12:28:13 -0500129 }
130 else if(isprint(((char*)mem)[j])) /* printable char */
131 {
Chris Austen99497312015-10-22 13:00:16 -0500132 fputc(0xFF & ((char*)mem)[j], s);
Chris Austen0ba649e2015-10-13 12:28:13 -0500133 }
134 else /* other char */
135 {
Chris Austen99497312015-10-22 13:00:16 -0500136 fputc('.',s);
Chris Austen0ba649e2015-10-13 12:28:13 -0500137 }
138 }
Chris Austen99497312015-10-22 13:00:16 -0500139 fputc('\n',s);
Chris Austen0ba649e2015-10-13 12:28:13 -0500140 }
141 }
142}
143
144
vishwabmcba0bd5f2015-09-30 16:50:23 +0530145// Method that gets called by shared libraries to get their command handlers registered
Tom05732372016-09-06 17:21:23 +0530146void ipmi_register_callback(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_context_t context,
147 ipmid_callback_t handler, ipmi_cmd_privilege_t priv)
vishwabmcba0bd5f2015-09-30 16:50:23 +0530148{
149 // Pack NetFn and Command in one.
150 auto netfn_and_cmd = std::make_pair(netfn, cmd);
151
152 // Pack Function handler and Data in another.
153 auto handler_and_context = std::make_pair(handler, context);
154
155 // Check if the registration has already been made..
156 auto iter = g_ipmid_router_map.find(netfn_and_cmd);
157 if(iter != g_ipmid_router_map.end())
158 {
159 fprintf(stderr,"ERROR : Duplicate registration for NetFn [0x%X], Cmd:[0x%X]\n",netfn, cmd);
160 }
161 else
162 {
163 // This is a fresh registration.. Add it to the map.
164 g_ipmid_router_map.emplace(netfn_and_cmd, handler_and_context);
165 }
166
167 return;
168}
169
170// Looks at the map and calls corresponding handler functions.
171ipmi_ret_t ipmi_netfn_router(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
172 ipmi_response_t response, ipmi_data_len_t data_len)
173{
174 // return from the Command handlers.
175 ipmi_ret_t rc = IPMI_CC_INVALID;
176
Tom Joseph9a61b4f2016-07-11 06:56:11 -0500177 // If restricted mode is true and command is not whitelisted, don't
178 // execute the command
179 if(restricted_mode)
180 {
181 if (!std::binary_search(whitelist.cbegin(), whitelist.cend(),
182 std::make_pair(netfn, cmd)))
183 {
184 printf("Net function:[0x%X], Command:[0x%X] is not whitelisted\n",
185 netfn, cmd);
186 rc = IPMI_CC_INSUFFICIENT_PRIVILEGE;
187 memcpy(response, &rc, IPMI_CC_LEN);
188 *data_len = IPMI_CC_LEN;
189 return rc;
190 }
191 }
192
vishwabmcba0bd5f2015-09-30 16:50:23 +0530193 // Walk the map that has the registered handlers and invoke the approprite
194 // handlers for matching commands.
195 auto iter = g_ipmid_router_map.find(std::make_pair(netfn, cmd));
196 if(iter == g_ipmid_router_map.end())
197 {
Chris Austen99497312015-10-22 13:00:16 -0500198 fprintf(stderr, "No registered handlers for NetFn:[0x%X], Cmd:[0x%X]"
vishwabmcba0bd5f2015-09-30 16:50:23 +0530199 " trying Wilcard implementation \n",netfn, cmd);
200
201 // Now that we did not find any specific [NetFn,Cmd], tuple, check for
202 // NetFn, WildCard command present.
203 iter = g_ipmid_router_map.find(std::make_pair(netfn, IPMI_CMD_WILDCARD));
204 if(iter == g_ipmid_router_map.end())
205 {
Chris Austen99497312015-10-22 13:00:16 -0500206 fprintf(stderr, "No Registered handlers for NetFn:[0x%X],Cmd:[0x%X]\n",netfn, IPMI_CMD_WILDCARD);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530207
208 // Respond with a 0xC1
209 memcpy(response, &rc, IPMI_CC_LEN);
210 *data_len = IPMI_CC_LEN;
211 return rc;
212 }
213 }
214
215#ifdef __IPMI_DEBUG__
216 // We have either a perfect match -OR- a wild card atleast,
217 printf("Calling Net function:[0x%X], Command:[0x%X]\n", netfn, cmd);
218#endif
219
220 // Extract the map data onto appropriate containers
221 auto handler_and_context = iter->second;
222
223 // Creating a pointer type casted to char* to make sure we advance 1 byte
224 // when we advance pointer to next's address. advancing void * would not
225 // make sense.
226 char *respo = &((char *)response)[IPMI_CC_LEN];
227
228 // Response message from the plugin goes into a byte post the base response
229 rc = (handler_and_context.first) (netfn, cmd, request, respo,
230 data_len, handler_and_context.second);
Chris Austen120f7322015-10-14 23:27:31 -0500231
vishwabmcba0bd5f2015-09-30 16:50:23 +0530232 // Now copy the return code that we got from handler and pack it in first
233 // byte.
234 memcpy(response, &rc, IPMI_CC_LEN);
Chris Austen120f7322015-10-14 23:27:31 -0500235
vishwabmcba0bd5f2015-09-30 16:50:23 +0530236 // Data length is now actual data + completion code.
237 *data_len = *data_len + IPMI_CC_LEN;
238
239 return rc;
240}
241
vishwabmcba0bd5f2015-09-30 16:50:23 +0530242
vishwabmcba0bd5f2015-09-30 16:50:23 +0530243
vishwabmcba0bd5f2015-09-30 16:50:23 +0530244
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800245static 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 +0530246
Chris Austen0ba649e2015-10-13 12:28:13 -0500247 sd_bus_error error = SD_BUS_ERROR_NULL;
248 sd_bus_message *reply = NULL, *m=NULL;
Jeremy Kerre41081f2015-10-27 12:11:36 +0800249 const char *dest, *path;
Chris Austen0ba649e2015-10-13 12:28:13 -0500250 int r, pty;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530251
Jeremy Kerre41081f2015-10-27 12:11:36 +0800252 dest = sd_bus_message_get_sender(req);
253 path = sd_bus_message_get_path(req);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530254
Vishwanatha Subbanna3eb117a2017-07-12 16:13:49 +0530255 r = sd_bus_message_new_method_call(bus,&m,dest,path,
256 DBUS_INTF,
257 "sendMessage");
Chris Austen0ba649e2015-10-13 12:28:13 -0500258 if (r < 0) {
259 fprintf(stderr, "Failed to add the method object: %s\n", strerror(-r));
260 return -1;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530261 }
262
vishwabmcba0bd5f2015-09-30 16:50:23 +0530263
Chris Austenabfb5e82015-10-13 12:29:24 -0500264 // Responses in IPMI require a bit set. So there ya go...
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800265 netfn |= 0x01;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530266
Chris Austen0ba649e2015-10-13 12:28:13 -0500267
268 // Add the bytes needed for the methods to be called
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800269 r = sd_bus_message_append(m, "yyyyy", seq, netfn, lun, cmd, cc);
Chris Austen0ba649e2015-10-13 12:28:13 -0500270 if (r < 0) {
271 fprintf(stderr, "Failed add the netfn and others : %s\n", strerror(-r));
Chris Austen169395e2015-12-02 20:56:15 -0600272 goto final;
Chris Austen0ba649e2015-10-13 12:28:13 -0500273 }
Chris Austen120f7322015-10-14 23:27:31 -0500274
Chris Austen0ba649e2015-10-13 12:28:13 -0500275 r = sd_bus_message_append_array(m, 'y', buf, len);
276 if (r < 0) {
277 fprintf(stderr, "Failed to add the string of response bytes: %s\n", strerror(-r));
Chris Austen169395e2015-12-02 20:56:15 -0600278 goto final;
Chris Austen0ba649e2015-10-13 12:28:13 -0500279 }
280
281
282
283 // Call the IPMI responder on the bus so the message can be sent to the CEC
284 r = sd_bus_call(bus, m, 0, &error, &reply);
285 if (r < 0) {
Chris Austen169395e2015-12-02 20:56:15 -0600286 fprintf(stderr, "Failed to call the method: %s\n", strerror(-r));
Chris Austen6bd23962015-12-07 21:31:48 -0600287 fprintf(stderr, "Dest: %s, Path: %s\n", dest, path);
Chris Austen169395e2015-12-02 20:56:15 -0600288 goto final;
Chris Austen0ba649e2015-10-13 12:28:13 -0500289 }
290
291 r = sd_bus_message_read(reply, "x", &pty);
Chris Austen0ba649e2015-10-13 12:28:13 -0500292 if (r < 0) {
293 fprintf(stderr, "Failed to get a rc from the method: %s\n", strerror(-r));
Chris Austen0ba649e2015-10-13 12:28:13 -0500294 }
295
Chris Austen169395e2015-12-02 20:56:15 -0600296final:
Chris Austen0ba649e2015-10-13 12:28:13 -0500297 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600298 m = sd_bus_message_unref(m);
299 reply = sd_bus_message_unref(reply);
Chris Austen0ba649e2015-10-13 12:28:13 -0500300
Chris Austen0ba649e2015-10-13 12:28:13 -0500301 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
Chris Austen0ba649e2015-10-13 12:28:13 -0500302}
303
Tom Joseph9a61b4f2016-07-11 06:56:11 -0500304void cache_restricted_mode()
305{
Deepak Kodihalli84b3a082017-07-21 23:44:44 -0500306 restricted_mode = false;
307 using namespace sdbusplus::xyz::openbmc_project::Control::Security::server;
308 using namespace internal;
309 using namespace internal::cache;
310 sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
311 const auto& restrictionModeSetting =
312 objects->map.at(restrictionModeIntf);
313 auto method = dbus.new_method_call(
314 objects->service(restrictionModeSetting,
315 restrictionModeIntf).c_str(),
316 restrictionModeSetting.c_str(),
317 "org.freedesktop.DBus.Properties",
318 "Get");
319 method.append(restrictionModeIntf, "RestrictionMode");
320 auto resp = dbus.call(method);
321 if (resp.is_method_error())
Tom Joseph9a61b4f2016-07-11 06:56:11 -0500322 {
Deepak Kodihalli84b3a082017-07-21 23:44:44 -0500323 log<level::ERR>("Error in RestrictionMode Get");
324 // Fail-safe to true.
325 restricted_mode = true;
326 return;
Tom Joseph9a61b4f2016-07-11 06:56:11 -0500327 }
Deepak Kodihalli84b3a082017-07-21 23:44:44 -0500328 sdbusplus::message::variant<std::string> result;
329 resp.read(result);
330 auto restrictionMode =
331 RestrictionMode::convertModesFromString(result.get<std::string>());
332 if(RestrictionMode::Modes::Whitelist == restrictionMode)
Tom Joseph9a61b4f2016-07-11 06:56:11 -0500333 {
Tom Joseph9a61b4f2016-07-11 06:56:11 -0500334 restricted_mode = true;
335 }
Tom Joseph9a61b4f2016-07-11 06:56:11 -0500336}
337
338static int handle_restricted_mode_change(sd_bus_message *m, void *user_data,
339 sd_bus_error *ret_error)
340{
341 cache_restricted_mode();
342 return 0;
343}
344
Chris Austen0ba649e2015-10-13 12:28:13 -0500345static int handle_ipmi_command(sd_bus_message *m, void *user_data, sd_bus_error
346 *ret_error) {
347 int r = 0;
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800348 unsigned char sequence, netfn, lun, cmd;
Chris Austen0ba649e2015-10-13 12:28:13 -0500349 const void *request;
350 size_t sz;
351 size_t resplen =MAX_IPMI_BUFFER;
352 unsigned char response[MAX_IPMI_BUFFER];
353
Chris Austen0ba649e2015-10-13 12:28:13 -0500354 memset(response, 0, MAX_IPMI_BUFFER);
355
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800356 r = sd_bus_message_read(m, "yyyy", &sequence, &netfn, &lun, &cmd);
Chris Austen0ba649e2015-10-13 12:28:13 -0500357 if (r < 0) {
358 fprintf(stderr, "Failed to parse signal message: %s\n", strerror(-r));
359 return -1;
360 }
361
362 r = sd_bus_message_read_array(m, 'y', &request, &sz );
363 if (r < 0) {
364 fprintf(stderr, "Failed to parse signal message: %s\n", strerror(-r));
365 return -1;
366 }
367
Chris Austen99497312015-10-22 13:00:16 -0500368 fprintf(ipmiio, "IPMI Incoming: Seq 0x%02x, NetFn 0x%02x, CMD: 0x%02x \n", sequence, netfn, cmd);
369 hexdump(ipmiio, (void*)request, sz);
Chris Austen0ba649e2015-10-13 12:28:13 -0500370
Chris Austen120f7322015-10-14 23:27:31 -0500371 // Allow the length field to be used for both input and output of the
Chris Austen0ba649e2015-10-13 12:28:13 -0500372 // ipmi call
373 resplen = sz;
374
Chris Austen120f7322015-10-14 23:27:31 -0500375 // Now that we have parsed the entire byte array from the caller
vishwabmcba0bd5f2015-09-30 16:50:23 +0530376 // we can call the ipmi router to do the work...
Chris Austen0ba649e2015-10-13 12:28:13 -0500377 r = ipmi_netfn_router(netfn, cmd, (void *)request, (void *)response, &resplen);
378 if(r != 0)
vishwabmcba0bd5f2015-09-30 16:50:23 +0530379 {
Chris Austen0ba649e2015-10-13 12:28:13 -0500380 fprintf(stderr,"ERROR:[0x%X] handling NetFn:[0x%X], Cmd:[0x%X]\n",r, netfn, cmd);
Nan Li80be4b92016-05-23 19:30:49 +0800381
tomjose7ec0add2016-06-27 07:59:28 -0500382 if(r < 0) {
Nan Li80be4b92016-05-23 19:30:49 +0800383 response[0] = IPMI_CC_UNSPECIFIED_ERROR;
384 }
vishwabmcba0bd5f2015-09-30 16:50:23 +0530385 }
386
Chris Austen99497312015-10-22 13:00:16 -0500387 fprintf(ipmiio, "IPMI Response:\n");
388 hexdump(ipmiio, (void*)response, resplen);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530389
Chris Austen0ba649e2015-10-13 12:28:13 -0500390 // Send the response buffer from the ipmi command
Jeremy Kerr2564b1a2015-10-27 13:37:17 +0800391 r = send_ipmi_message(m, sequence, netfn, lun, cmd, response[0],
392 ((unsigned char *)response) + 1, resplen - 1);
Chris Austen0ba649e2015-10-13 12:28:13 -0500393 if (r < 0) {
394 fprintf(stderr, "Failed to send the response message\n");
395 return -1;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530396 }
397
vishwabmcba0bd5f2015-09-30 16:50:23 +0530398
Chris Austen0ba649e2015-10-13 12:28:13 -0500399 return 0;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530400}
401
Chris Austen0ba649e2015-10-13 12:28:13 -0500402
vishwabmcba0bd5f2015-09-30 16:50:23 +0530403//----------------------------------------------------------------------
404// handler_select
405// Select all the files ending with with .so. in the given diretcory
406// @d: dirent structure containing the file name
407//----------------------------------------------------------------------
408int handler_select(const struct dirent *entry)
409{
410 // To hold ".so" from entry->d_name;
411 char dname_copy[4] = {0};
412
413 // We want to avoid checking for everything and isolate to the ones having
Adriana Kobylak87e080b2016-07-10 13:16:53 -0500414 // .so.* or .so in them.
415 // Check for versioned libraries .so.*
416 if(strstr(entry->d_name, IPMI_PLUGIN_SONAME_EXTN))
417 {
418 return 1;
419 }
420 // Check for non versioned libraries .so
421 else if(strstr(entry->d_name, IPMI_PLUGIN_EXTN))
vishwabmcba0bd5f2015-09-30 16:50:23 +0530422 {
423 // It is possible that .so could be anywhere in the string but unlikely
Chris Austen120f7322015-10-14 23:27:31 -0500424 // But being careful here. Get the base address of the string, move
vishwabmcba0bd5f2015-09-30 16:50:23 +0530425 // until end and come back 3 steps and that gets what we need.
426 strcpy(dname_copy, (entry->d_name + strlen(entry->d_name)-strlen(IPMI_PLUGIN_EXTN)));
427 if(strcmp(dname_copy, IPMI_PLUGIN_EXTN) == 0)
428 {
429 return 1;
430 }
431 }
432 return 0;
433}
434
435// 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 -0500436// register a callback handler
vishwabmcba0bd5f2015-09-30 16:50:23 +0530437void ipmi_register_callback_handlers(const char* ipmi_lib_path)
438{
439 // For walking the ipmi_lib_path
440 struct dirent **handler_list;
441 int num_handlers = 0;
442
443 // This is used to check and abort if someone tries to register a bad one.
444 void *lib_handler = NULL;
445
446 if(ipmi_lib_path == NULL)
447 {
448 fprintf(stderr,"ERROR; No handlers to be registered for ipmi.. Aborting\n");
449 assert(0);
450 }
451 else
452 {
453 // 1: Open ipmi_lib_path. Its usually "/usr/lib/phosphor-host-ipmid"
454 // 2: Scan the directory for the files that end with .so
Chris Austen120f7322015-10-14 23:27:31 -0500455 // 3: For each one of them, just do a 'dlopen' so that they register
vishwabmcba0bd5f2015-09-30 16:50:23 +0530456 // the handlers for callback routines.
457
458 std::string handler_fqdn = ipmi_lib_path;
Chris Austen120f7322015-10-14 23:27:31 -0500459
vishwabmcba0bd5f2015-09-30 16:50:23 +0530460 // Append a "/" since we need to add the name of the .so. If there is
461 // already a .so, adding one more is not any harm.
462 handler_fqdn += "/";
463
464 num_handlers = scandir(ipmi_lib_path, &handler_list, handler_select, alphasort);
Nan Li36c0cb62016-03-31 11:16:08 +0800465 if (num_handlers < 0)
466 return;
Jeremy Kerr5e8f85e2015-10-27 13:43:54 +0800467
vishwabmcba0bd5f2015-09-30 16:50:23 +0530468 while(num_handlers--)
469 {
Chris Austen54030262015-10-13 12:30:46 -0500470 handler_fqdn = ipmi_lib_path;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530471 handler_fqdn += handler_list[num_handlers]->d_name;
Chris Austen54030262015-10-13 12:30:46 -0500472 printf("Registering handler:[%s]\n",handler_fqdn.c_str());
473
vishwabmcba0bd5f2015-09-30 16:50:23 +0530474 lib_handler = dlopen(handler_fqdn.c_str(), RTLD_NOW);
Nan Li36c0cb62016-03-31 11:16:08 +0800475
vishwabmcba0bd5f2015-09-30 16:50:23 +0530476 if(lib_handler == NULL)
477 {
Chris Austen120f7322015-10-14 23:27:31 -0500478 fprintf(stderr,"ERROR opening [%s]: %s\n",
479 handler_fqdn.c_str(), dlerror());
vishwabmcba0bd5f2015-09-30 16:50:23 +0530480 }
481 // Wipe the memory allocated for this particular entry.
482 free(handler_list[num_handlers]);
483 }
Nan Li36c0cb62016-03-31 11:16:08 +0800484
vishwabmcba0bd5f2015-09-30 16:50:23 +0530485 // Done with all registration.
486 free(handler_list);
487 }
488
489 // TODO : What to be done on the memory that is given by dlopen ?.
490 return;
491}
492
Chris Austen30195fa2015-11-13 14:39:19 -0600493sd_bus *ipmid_get_sd_bus_connection(void) {
494 return bus;
495}
496
Andrew Geissler93c679b2017-04-02 10:06:43 -0500497sd_event *ipmid_get_sd_event_connection(void) {
498 return events;
499}
500
vishwab9f559a2016-01-13 01:53:08 -0600501sd_bus_slot *ipmid_get_sd_bus_slot(void) {
502 return ipmid_slot;
503}
504
Vishwanatha Subbanna3eb117a2017-07-12 16:13:49 +0530505// Calls host command manager to do the right thing for the command
506void ipmid_send_cmd_to_host(CommandHandler&& cmd) {
507 return cmdManager->execute(std::move(cmd));
508}
509
510cmdManagerPtr& ipmid_get_host_cmd_manager() {
511 return cmdManager;
512}
513
514sdbusPtr& ipmid_get_sdbus_plus_handler() {
515 return sdbusp;
516}
517
vishwabmcba0bd5f2015-09-30 16:50:23 +0530518int main(int argc, char *argv[])
519{
Chris Austen0ba649e2015-10-13 12:28:13 -0500520 int r;
Chris Austen99497312015-10-22 13:00:16 -0500521 unsigned long tvalue;
522 int c;
523
524
525
526 // This file and subsequient switch is for turning on levels
527 // of trace
528 ipmicmddetails = ipmiio = ipmidbus = fopen("/dev/null", "w");
529
530 while ((c = getopt (argc, argv, "h:d:")) != -1)
531 switch (c) {
532 case 'd':
533 tvalue = strtoul(optarg, NULL, 16);
534 if (1&tvalue) {
535 ipmiio = stdout;
536 }
537 if (2&tvalue) {
538 ipmidbus = stdout;
539 }
540 if (4&tvalue) {
541 ipmicmddetails = stdout;
542 }
543 break;
544 case 'h':
545 case '?':
546 print_usage();
547 return 1;
548 }
Chris Austen0ba649e2015-10-13 12:28:13 -0500549
550
Chris Austen0ba649e2015-10-13 12:28:13 -0500551 /* Connect to system bus */
552 r = sd_bus_open_system(&bus);
553 if (r < 0) {
554 fprintf(stderr, "Failed to connect to system bus: %s\n",
555 strerror(-r));
556 goto finish;
557 }
vishwabmcba0bd5f2015-09-30 16:50:23 +0530558
Andrew Geissler93c679b2017-04-02 10:06:43 -0500559 /* Get an sd event handler */
560 r = sd_event_default(&events);
561 if (r < 0)
562 {
563 log<level::ERR>("Failure to create sd_event handler",
564 entry("ERROR=%s", strerror(-r)));
565 goto finish;
566 }
567
Vishwanatha Subbanna3eb117a2017-07-12 16:13:49 +0530568 // Now create the Host Bound Command manager. Need sdbusplus
569 // to use the generated bindings
570 sdbusp = std::make_unique<sdbusplus::bus::bus>(bus);
571 cmdManager = std::make_unique<phosphor::host::command::Manager>(
572 *sdbusp, events);
Andrew Geissler93c679b2017-04-02 10:06:43 -0500573
Chris Austen30195fa2015-11-13 14:39:19 -0600574 // Register all the handlers that provider implementation to IPMI commands.
575 ipmi_register_callback_handlers(HOST_IPMI_LIB_PATH);
576
vishwa36993272015-11-20 12:43:49 -0600577 // Watch for BT messages
vishwab9f559a2016-01-13 01:53:08 -0600578 r = sd_bus_add_match(bus, &ipmid_slot, FILTER, handle_ipmi_command, NULL);
Chris Austen0ba649e2015-10-13 12:28:13 -0500579 if (r < 0) {
580 fprintf(stderr, "Failed: sd_bus_add_match: %s : %s\n", strerror(-r), FILTER);
581 goto finish;
582 }
vishwabmcba0bd5f2015-09-30 16:50:23 +0530583
Andrew Geissler93c679b2017-04-02 10:06:43 -0500584 // Attach the bus to sd_event to service user requests
585 sd_bus_attach_event(bus, events, SD_EVENT_PRIORITY_NORMAL);
586
Deepak Kodihalli84b3a082017-07-21 23:44:44 -0500587 {
588 using namespace internal;
589 using namespace internal::cache;
590 sdbusplus::bus::bus dbus{bus};
591 objects = std::make_unique<settings::Objects>(
592 dbus,
593 std::vector<settings::Interface>({restrictionModeIntf}));
594 // Initialize restricted mode
595 cache_restricted_mode();
596 // Wait for changes on Restricted mode
597 sdbusplus::bus::match_t restrictedModeMatch(
598 dbus,
599 sdbusRule::propertiesChanged(
600 objects->map.at(restrictionModeIntf), restrictionModeIntf),
601 handle_restricted_mode_change);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530602
Deepak Kodihalli84b3a082017-07-21 23:44:44 -0500603 for (;;) {
604 /* Process requests */
605 r = sd_event_run(events, (uint64_t)-1);
606 if (r < 0)
607 {
608 log<level::ERR>("Failure in processing request",
609 entry("ERROR=%s", strerror(-r)));
610 goto finish;
611 }
Chris Austen0ba649e2015-10-13 12:28:13 -0500612 }
613 }
614
615finish:
Andrew Geissler93c679b2017-04-02 10:06:43 -0500616 sd_event_unref(events);
617 sd_bus_detach_event(bus);
vishwab9f559a2016-01-13 01:53:08 -0600618 sd_bus_slot_unref(ipmid_slot);
Chris Austen0ba649e2015-10-13 12:28:13 -0500619 sd_bus_unref(bus);
620 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
621
vishwabmcba0bd5f2015-09-30 16:50:23 +0530622}