summaryrefslogtreecommitdiffstats
path: root/main.cpp
diff options
context:
space:
mode:
authorTom Joseph <tomjoseph@in.ibm.com>2016-08-29 08:17:59 -0500
committerTom Joseph <tomjoseph@in.ibm.com>2017-01-09 17:04:10 +0530
commitc35524e7cf49b26e0ee2a16c6f4529c5be047e91 (patch)
tree885b27283e26e53e275f1bd9bd659a7f6bfcb7cf /main.cpp
parentd8be3364964d91f9e02e5eef261fc4260251a714 (diff)
downloadphosphor-net-ipmid-c35524e7cf49b26e0ee2a16c6f4529c5be047e91.tar.gz
phosphor-net-ipmid-c35524e7cf49b26e0ee2a16c6f4529c5be047e91.zip
IPMI Main Handler
This patch contains the entry point for the IPMI RMCP Server. It registers the session setup commands and start the IPMI event handler. Resolves openbmc/openbmc#429 Change-Id: I98a615eef9becb29964f8ec93e59d061bfcdfac3 Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
Diffstat (limited to 'main.cpp')
-rw-r--r--main.cpp193
1 files changed, 193 insertions, 0 deletions
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..0fae8a7
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,193 @@
+#include "main.hpp"
+#include <assert.h>
+#include <dlfcn.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#include <iostream>
+#include <tuple>
+
+#include <systemd/sd-bus.h>
+#include <systemd/sd-daemon.h>
+#include <systemd/sd-event.h>
+
+#include <host-ipmid/ipmid-api.h>
+#include "comm_module.hpp"
+#include "command_table.hpp"
+#include "message.hpp"
+#include "message_handler.hpp"
+#include "sessions_manager.hpp"
+#include "socket_channel.hpp"
+
+// Tuple of Global Singletons
+session::Manager manager;
+command::Table table;
+std::tuple<session::Manager&, command::Table&> singletonPool(manager, table);
+
+sd_bus* bus = nullptr;
+
+/*
+ * @brief Required by apphandler IPMI Provider Library
+ */
+sd_bus* ipmid_get_sd_bus_connection()
+{
+ return bus;
+}
+
+/*
+ * TODO : The plan is to refactor the event loop to support adding multiple
+ * file descriptors and event handlers for implementing the Serial Over LAN.
+ *
+ * A class would abstract the features provided by the sd_event_loop
+ */
+
+namespace eventloop
+{
+
+static int io_handler(sd_event_source* es, int fd, uint32_t revents,
+ void* userdata)
+{
+ std::shared_ptr<udpsocket::Channel> channelPtr;
+ struct timeval timeout;
+ timeout.tv_sec = SELECT_CALL_TIMEOUT;
+ timeout.tv_usec = 0;
+
+ channelPtr.reset(new udpsocket::Channel(fd, timeout));
+
+ // Initialize the Message Handler with the socket channel
+ message::Handler msgHandler(channelPtr);
+
+ // Read the incoming IPMI packet
+ std::unique_ptr<message::Message> inMessage;
+ try
+ {
+ inMessage = msgHandler.receive();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Reading & Parsing the incoming IPMI message failed\n";
+ std::cerr << e.what() << "\n";
+ return 0;
+ }
+
+ // Execute the Command
+ auto outMessage = msgHandler.executeCommand(*inMessage.get());
+ if (outMessage == nullptr)
+ {
+ std::cerr << "Execution of IPMI command failed\n";
+ return 0;
+ }
+
+ // Send the response IPMI Message
+ msgHandler.send(*outMessage.get());
+
+ return 0;
+}
+
+int startEventLoop()
+{
+ struct sockaddr_in6 in {};
+
+ sd_event_source* event_source = nullptr;
+ sd_event* event = nullptr;
+ int fd = -1, r;
+ sigset_t ss;
+
+ r = sd_event_default(&event);
+ if (r < 0)
+ {
+ goto finish;
+ }
+
+ if (sigemptyset(&ss) < 0 || sigaddset(&ss, SIGTERM) < 0 ||
+ sigaddset(&ss, SIGINT) < 0)
+ {
+ r = -errno;
+ goto finish;
+ }
+
+ /* Block SIGTERM first, so that the event loop can handle it */
+ if (sigprocmask(SIG_BLOCK, &ss, nullptr) < 0)
+ {
+ r = -errno;
+ goto finish;
+ }
+
+ /* Let's make use of the default handler and "floating" reference features
+ * of sd_event_add_signal() */
+ r = sd_event_add_signal(event, nullptr, SIGTERM, nullptr, nullptr);
+ if (r < 0)
+ {
+ goto finish;
+ }
+
+ r = sd_event_add_signal(event, nullptr, SIGINT, nullptr, nullptr);
+ if (r < 0)
+ {
+ goto finish;
+ }
+
+ fd = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
+ if (fd < 0)
+ {
+ r = -errno;
+ goto finish;
+ }
+
+ in.sin6_family = AF_INET6;
+ in.sin6_port = htons(IPMI_STD_PORT);
+
+ if (bind(fd, (struct sockaddr*)&in, sizeof(in)) < 0)
+ {
+ r = -errno;
+ goto finish;
+ }
+
+ r = sd_event_add_io(event, &event_source, fd, EPOLLIN, io_handler, nullptr);
+ if (r < 0)
+ {
+ goto finish;
+ }
+
+ r = sd_event_loop(event);
+
+finish:
+ event_source = sd_event_source_unref(event_source);
+ event = sd_event_unref(event);
+
+ if (fd >= 0)
+ {
+ (void) close(fd);
+ }
+
+ if (r < 0)
+ {
+ fprintf(stderr, "Failure: %s\n", strerror(-r));
+ }
+
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+} // namespace eventloop
+
+int main(int i_argc, char* i_argv[])
+{
+ // Connect to system bus
+ auto rc = sd_bus_open_system(&bus);
+ if (rc < 0)
+ {
+ std::cerr << "Failed to connect to system bus:" << strerror(-rc) <<"\n";
+ goto finish;
+ }
+
+ // Register the phosphor-net-ipmid session setup commands
+ command::sessionSetupCommands();
+
+ // Start Event Loop
+ return eventloop::startEventLoop();
+
+finish:
+ sd_bus_unref(bus);
+
+ return 0;
+}
OpenPOWER on IntegriCloud