diff options
-rw-r--r-- | Makefile.am | 40 | ||||
-rw-r--r-- | README.md | 9 | ||||
-rwxr-xr-x | bootstrap.sh | 18 | ||||
-rw-r--r-- | configure.ac | 30 | ||||
-rw-r--r-- | main.cpp | 193 | ||||
-rw-r--r-- | socket_channel.cpp | 2 | ||||
-rw-r--r-- | socket_channel.hpp | 4 |
7 files changed, 293 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..fb28cad --- /dev/null +++ b/Makefile.am @@ -0,0 +1,40 @@ +sbin_PROGRAMS = \ + netipmid + +netipmid_SOURCES = \ + endian.hpp \ + socket_channel.hpp \ + socket_channel.cpp \ + message.hpp \ + auth_algo.hpp \ + auth_algo.cpp \ + session.hpp \ + session.cpp \ + sessions_manager.hpp \ + sessions_manager.cpp \ + message_parsers.hpp \ + message_parsers.cpp \ + message_handler.hpp \ + message_handler.cpp \ + command_table.hpp \ + command_table.cpp \ + command/channel_auth.hpp \ + command/channel_auth.cpp \ + command/guid.hpp \ + command/guid.cpp \ + command/open_session.hpp \ + command/open_session.cpp \ + command/rakp12.hpp \ + command/rakp12.cpp \ + command/rakp34.hpp \ + command/rakp34.cpp \ + command/session_cmds.hpp \ + command/session_cmds.cpp \ + comm_module.hpp \ + comm_module.cpp \ + main.hpp \ + main.cpp \ + +netipmid_LDFLAGS = $(SYSTEMD_LIBS) $(CRYPTO_LIBS) $(libmapper_LIBS) +netipmid_CXXFLAGS = $(SYSTEMD_CFLAGS) $(libmapper_CFLAGS) + diff --git a/README.md b/README.md new file mode 100644 index 0000000..a352eed --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +## To Build +``` +To build this package, do the following steps: + + 1. ./bootstrap.sh + 2. ./configure ${CONFIGURE_FLAGS} + 3. make + +To full clean the repository again run `./bootstrap.sh clean`. diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100755 index 0000000..50b75b7 --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +AUTOCONF_FILES="Makefile.in aclocal.m4 ar-lib autom4te.cache compile \ + config.guess config.h.in config.sub configure depcomp install-sh \ + ltmain.sh missing *libtool test-driver" + +case $1 in + clean) + test -f Makefile && make maintainer-clean + for file in ${AUTOCONF_FILES}; do + find -name "$file" | xargs -r rm -rf + done + exit 0 + ;; +esac + +autoreconf -i +echo 'Run "./configure ${CONFIGURE_FLAGS} && make"' diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..1b12c59 --- /dev/null +++ b/configure.ac @@ -0,0 +1,30 @@ +# Initialization +AC_PREREQ([2.69]) +AC_INIT([phosphor-net-ipmid], [1.0], [https://github.com/openbmc/phosphor-net-ipmid/issues]) +AC_CONFIG_HEADERS([config.h]) +AM_INIT_AUTOMAKE([subdir-objects -Wall -Werror foreign dist-xz]) +AM_SILENT_RULES([yes]) + +# Checks for programs. +AC_PROG_CXX +AM_PROG_AR +AC_PROG_INSTALL +AC_PROG_MAKE_SET + +# Surpress the --with-libtool-sysroot error +LT_INIT + +# Checks for typedefs, structures, and compiler characteristics. +AX_CXX_COMPILE_STDCXX_14([noext]) +AX_APPEND_COMPILE_FLAGS([-Wall -Werror], [CXXFLAGS]) + +# Checks for libraries. +PKG_CHECK_MODULES([SYSTEMD], [libsystemd >= 221]) +PKG_CHECK_MODULES([CRYPTO], [libcrypto >= 1.0.2g], ,[AC_MSG_ERROR([can't find openssl libcrypto])]) +AC_CHECK_LIB([mapper], [mapper_get_service], ,[AC_MSG_ERROR([Could not find libmapper...openbmc/phosphor-objmgr package required])]) + +# Checks for header files. +AC_CHECK_HEADER(systemd/sd-bus.h, ,[AC_MSG_ERROR([Could not find systemd/sd-bus.h...systemd developement package required])]) + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT 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; +} diff --git a/socket_channel.cpp b/socket_channel.cpp index 4a6d827..a29ef8d 100644 --- a/socket_channel.cpp +++ b/socket_channel.cpp @@ -15,7 +15,7 @@ namespace udpsocket std::string Channel::getRemoteAddress() const { char tmp[INET_ADDRSTRLEN] = { 0 }; - inet_ntop(AF_INET, &address.inAddr.sin_addr, tmp, sizeof(tmp)); + inet_ntop(AF_INET6, &address.inAddr.sin6_addr, tmp, sizeof(tmp)); return std::string(tmp); } diff --git a/socket_channel.hpp b/socket_channel.hpp index de95bfd..d5f140e 100644 --- a/socket_channel.hpp +++ b/socket_channel.hpp @@ -24,7 +24,7 @@ class Channel union { sockaddr sockAddr; - sockaddr_in inAddr; + sockaddr_in6 inAddr; }; size_t addrSize; }; @@ -65,7 +65,7 @@ class Channel */ auto getPort() const { - return address.inAddr.sin_port; + return address.inAddr.sin6_port; } /** |