diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | app/channel.cpp | 428 | ||||
-rw-r--r-- | app/channel.hpp | 59 | ||||
-rw-r--r-- | apphandler.cpp | 397 | ||||
-rw-r--r-- | apphandler.h | 20 |
5 files changed, 490 insertions, 415 deletions
diff --git a/Makefile.am b/Makefile.am index 9eef999..d4f43db 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,6 +49,7 @@ fru-read-gen.cpp: libapphandlerdir = ${libdir}/ipmid-providers libapphandler_LTLIBRARIES = libapphandler.la libapphandler_la_SOURCES = \ + app/channel.cpp \ app/watchdog.cpp \ apphandler.cpp \ sensorhandler.cpp \ diff --git a/app/channel.cpp b/app/channel.cpp new file mode 100644 index 0000000..72f1571 --- /dev/null +++ b/app/channel.cpp @@ -0,0 +1,428 @@ +#include "channel.hpp" +#include "types.hpp" +#include "transporthandler.hpp" +#include "utils.hpp" + +#include <string> +#include <arpa/inet.h> + +#include <phosphor-logging/log.hpp> +#include <phosphor-logging/elog-errors.hpp> +#include "xyz/openbmc_project/Common/error.hpp" + +extern struct ChannelConfig_t channelConfig; + +constexpr auto ipv4Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv4"; + +using namespace phosphor::logging; +using namespace sdbusplus::xyz::openbmc_project::Common::Error; + +/** @struct GetChannelAccessRequest + * + * IPMI payload for Get Channel access command request. + */ +struct GetChannelAccessRequest +{ + uint8_t channelNumber; //!< Channel number. + uint8_t volatileSetting; //!< Get non-volatile or the volatile setting. +} __attribute__((packed)); + +/** @struct GetChannelAccessResponse + * + * IPMI payload for Get Channel access command response. + */ +struct GetChannelAccessResponse +{ + uint8_t settings; //!< Channel settings. + uint8_t privilegeLimit; //!< Channel privilege level limit. +} __attribute__((packed)); + +ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, + ipmi_cmd_t cmd, + ipmi_request_t request, + ipmi_response_t response, + ipmi_data_len_t data_len, + ipmi_context_t context) +{ + ipmi_ret_t rc = IPMI_CC_OK; + + std::string ipaddress; + std::string gateway; + uint8_t prefix {}; + uint32_t vlanID {}; + std::string networkInterfacePath; + ipmi::DbusObjectInfo ipObject; + ipmi::DbusObjectInfo systemObject; + + // Todo: parse the request data if needed. + // Using Set Channel cmd to apply changes of Set Lan Cmd. + try + { + sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection()); + + log<level::INFO>("Network data from Cache", + entry("PREFIX=%s", channelConfig.netmask.c_str()), + entry("ADDRESS=%s", channelConfig.ipaddr.c_str()), + entry("GATEWAY=%s", channelConfig.gateway.c_str()), + entry("VLAN=%d", channelConfig.vlanID), + entry("IPSRC=%d", channelConfig.ipsrc)); + + if (channelConfig.vlanID != ipmi::network::VLAN_ID_MASK) + { + //get the first twelve bits which is vlan id + //not interested in rest of the bits. + channelConfig.vlanID = le32toh(channelConfig.vlanID); + vlanID = channelConfig.vlanID & ipmi::network::VLAN_ID_MASK; + } + + // if the asked ip src is DHCP then not interested in + // any given data except vlan. + if (channelConfig.ipsrc != ipmi::network::IPOrigin::DHCP) + { + // always get the system object + systemObject = ipmi::getDbusObject( + bus, + ipmi::network::SYSTEMCONFIG_INTERFACE, + ipmi::network::ROOT); + + // the below code is to determine the mode of the interface + // as the handling is same, if the system is configured with + // DHCP or user has given all the data. + try + { + ipmi::ObjectTree ancestorMap; + + ipmi::InterfaceList interfaces { + ipmi::network::ETHERNET_INTERFACE }; + + // if the system is having ip object,then + // get the IP object. + ipObject = ipmi::getDbusObject(bus, + ipmi::network::IP_INTERFACE, + ipmi::network::ROOT, + ipmi::network::IP_TYPE); + + // Get the parent interface of the IP object. + try + { + ancestorMap = ipmi::getAllAncestors(bus, + ipObject.first, + std::move(interfaces)); + } + catch (InternalFailure& e) + { + // if unable to get the parent interface + // then commit the error and return. + log<level::ERR>("Unable to get the parent interface", + entry("PATH=%s", ipObject.first.c_str()), + entry("INTERFACE=%s", + ipmi::network::ETHERNET_INTERFACE)); + commit<InternalFailure>(); + rc = IPMI_CC_UNSPECIFIED_ERROR; + channelConfig.clear(); + return rc; + } + + networkInterfacePath = ancestorMap.begin()->first; + } + catch (InternalFailure& e) + { + // TODO Currently IPMI supports single interface,need to handle + // Multiple interface through + // https://github.com/openbmc/openbmc/issues/2138 + + // if there is no ip configured on the system,then + // get the network interface object. + auto networkInterfaceObject = ipmi::getDbusObject( + bus, + ipmi::network::ETHERNET_INTERFACE, + ipmi::network::ROOT, + ipmi::network::INTERFACE); + + networkInterfacePath = std::move(networkInterfaceObject.first); + } + + // get the configured mode on the system. + auto enableDHCP = ipmi::getDbusProperty( + bus, + ipmi::network::SERVICE, + networkInterfacePath, + ipmi::network::ETHERNET_INTERFACE, + "DHCPEnabled").get<bool>(); + + // check whether user has given all the data + // or the configured system interface is dhcp enabled, + // in both of the cases get the values from the cache. + if ((!channelConfig.ipaddr.empty() && + !channelConfig.netmask.empty() && + !channelConfig.gateway.empty()) || + (enableDHCP)) // configured system interface mode = DHCP + { + //convert mask into prefix + ipaddress = channelConfig.ipaddr; + prefix = ipmi::network::toPrefix(AF_INET, channelConfig.netmask); + gateway = channelConfig.gateway; + if (channelConfig.vlanID != ipmi::network::VLAN_ID_MASK) + { + //get the first twelve bits which is vlan id + //not interested in rest of the bits. + channelConfig.vlanID = le32toh(channelConfig.vlanID); + vlanID = channelConfig.vlanID & ipmi::network::VLAN_ID_MASK; + } + else + { + vlanID = ipmi::network::getVLAN(networkInterfacePath); + } + + } + else // asked ip src = static and configured system src = static + // or partially given data. + { + // We have partial filled cache so get the remaining + // info from the system. + + // Get the network data from the system as user has + // not given all the data then use the data fetched from the + // system but it is implementation dependent,IPMI spec doesn't + // force it. + + // if system is not having any ip object don't throw error, + try + { + auto properties = ipmi::getAllDbusProperties( + bus, + ipObject.second, + ipObject.first, + ipmi::network::IP_INTERFACE); + + ipaddress = channelConfig.ipaddr.empty() ? + ipmi::getIPAddress(bus, + ipmi::network::IP_INTERFACE, + ipmi::network::ROOT, + ipmi::network::IP_TYPE) : + channelConfig.ipaddr; + + prefix = channelConfig.netmask.empty() ? + properties["PrefixLength"].get<uint8_t>() : + ipmi::network::toPrefix(AF_INET, + channelConfig.netmask); + + } + catch (InternalFailure& e) + { + log<level::INFO>("Failed to get IP object which matches", + entry("INTERFACE=%s", ipmi::network::IP_INTERFACE), + entry("MATCH=%s", ipmi::network::IP_TYPE)); + } + + auto systemProperties = ipmi::getAllDbusProperties( + bus, + systemObject.second, + systemObject.first, + ipmi::network::SYSTEMCONFIG_INTERFACE); + + gateway = channelConfig.gateway.empty() ? + systemProperties["DefaultGateway"].get<std::string>() : + channelConfig.gateway; + + } + } + + // Currently network manager doesn't support purging of all the + // ip addresses and the vlan interfaces from the parent interface, + // TODO once the support is there, will make the change here. + // https://github.com/openbmc/openbmc/issues/2141. + + // TODO Currently IPMI supports single interface,need to handle + // Multiple interface through + // https://github.com/openbmc/openbmc/issues/2138 + + // instead of deleting all the vlan interfaces and + // all the ipv4 address,we will call reset method. + //delete all the vlan interfaces + + ipmi::deleteAllDbusObjects(bus, + ipmi::network::ROOT, + ipmi::network::VLAN_INTERFACE); + + // set the interface mode to static + auto networkInterfaceObject = ipmi::getDbusObject( + bus, + ipmi::network::ETHERNET_INTERFACE, + ipmi::network::ROOT, + ipmi::network::INTERFACE); + + // setting the physical interface mode to static. + ipmi::setDbusProperty(bus, + ipmi::network::SERVICE, + networkInterfaceObject.first, + ipmi::network::ETHERNET_INTERFACE, + "DHCPEnabled", + false); + + networkInterfacePath = networkInterfaceObject.first; + + //delete all the ipv4 addresses + ipmi::deleteAllDbusObjects(bus, + ipmi::network::ROOT, + ipmi::network::IP_INTERFACE, + ipmi::network::IP_TYPE); + + if (vlanID) + { + ipmi::network::createVLAN(bus, + ipmi::network::SERVICE, + ipmi::network::ROOT, + ipmi::network::INTERFACE, + vlanID); + + auto networkInterfaceObject = ipmi::getDbusObject( + bus, + ipmi::network::VLAN_INTERFACE, + ipmi::network::ROOT); + + networkInterfacePath = networkInterfaceObject.first; + } + + if (channelConfig.ipsrc == ipmi::network::IPOrigin::DHCP) + { + ipmi::setDbusProperty(bus, + ipmi::network::SERVICE, + networkInterfacePath, + ipmi::network::ETHERNET_INTERFACE, + "DHCPEnabled", + true); + } + else + { + //change the mode to static + ipmi::setDbusProperty(bus, + ipmi::network::SERVICE, + networkInterfacePath, + ipmi::network::ETHERNET_INTERFACE, + "DHCPEnabled", + false); + + if (!ipaddress.empty()) + { + ipmi::network::createIP(bus, + ipmi::network::SERVICE, + networkInterfacePath, + ipv4Protocol, + ipaddress, + prefix); + } + + if (!gateway.empty()) + { + ipmi::setDbusProperty(bus, + systemObject.second, + systemObject.first, + ipmi::network::SYSTEMCONFIG_INTERFACE, + "DefaultGateway", + std::string(gateway)); + } + } + + } + catch (InternalFailure& e) + { + log<level::ERR>("Failed to set network data", + entry("PREFIX=%d", prefix), + entry("ADDRESS=%s", ipaddress.c_str()), + entry("GATEWAY=%s", gateway.c_str()), + entry("VLANID=%d", vlanID), + entry("IPSRC=%d", channelConfig.ipsrc)); + + commit<InternalFailure>(); + rc = IPMI_CC_UNSPECIFIED_ERROR; + } + + channelConfig.clear(); + return rc; +} + +ipmi_ret_t ipmi_get_channel_access(ipmi_netfn_t netfn, ipmi_cmd_t cmd, + ipmi_request_t request, ipmi_response_t response, + ipmi_data_len_t data_len, ipmi_context_t context) +{ + auto requestData = reinterpret_cast<const GetChannelAccessRequest*> + (request); + std::vector<uint8_t> outPayload(sizeof(GetChannelAccessResponse)); + auto responseData = reinterpret_cast<GetChannelAccessResponse*> + (outPayload.data()); + + // Channel 1 is arbitrarily assigned to ETH0 channel + constexpr auto channelOne = 0x01; + + /* + * The value Eh is used as a way to identify the current channel that + * the command is being received from. + */ + constexpr auto channelE = 0x0E; + + if (requestData->channelNumber != channelOne && + requestData->channelNumber != channelE) + { + *data_len = 0; + return IPMI_CC_INVALID_FIELD_REQUEST; + } + + /* + * [7:6] - reserved + * [5] - 1b = Alerting disabled + * [4] - 1b = per message authentication disabled + * [3] - 0b = User level authentication enabled + * [2:0] - 2h = always available + */ + constexpr auto channelSetting = 0x32; + + responseData->settings = channelSetting; + //Defaulting the channel privilege to administrator level. + responseData->privilegeLimit = PRIVILEGE_ADMIN; + + *data_len = outPayload.size(); + memcpy(response, outPayload.data(), *data_len); + + return IPMI_CC_OK; +} + +// ATTENTION: This ipmi function is very hardcoded on purpose +// OpenBMC does not fully support IPMI. This command is useful +// to have around because it enables testing of interfaces with +// the IPMI tool. +#define GET_CHANNEL_INFO_CHANNEL_OFFSET 0 +// IPMI Table 6-2 +#define IPMI_CHANNEL_TYPE_IPMB 1 +// IPMI Table 6-3 +#define IPMI_CHANNEL_MEDIUM_TYPE_OTHER 6 + +ipmi_ret_t ipmi_app_channel_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd, + ipmi_request_t request, ipmi_response_t response, + ipmi_data_len_t data_len, ipmi_context_t context) +{ + ipmi_ret_t rc = IPMI_CC_OK; + uint8_t resp[] = { + 1, + IPMI_CHANNEL_MEDIUM_TYPE_OTHER, + IPMI_CHANNEL_TYPE_IPMB, + 1,0x41,0xA7,0x00,0,0}; + uint8_t *p = (uint8_t*) request; + + printf("IPMI APP GET CHANNEL INFO\n"); + + // The supported channels numbers are 1 and 8. + // Channel Number E is used as way to identify the current channel + // that the command is being is received from. + if (*p == 0xe || *p == 1 || *p == 8) { + + *data_len = sizeof(resp); + memcpy(response, resp, *data_len); + + } else { + rc = IPMI_CC_PARM_OUT_OF_RANGE; + *data_len = 0; + } + + return rc; +} diff --git a/app/channel.hpp b/app/channel.hpp new file mode 100644 index 0000000..1391d62 --- /dev/null +++ b/app/channel.hpp @@ -0,0 +1,59 @@ +#include "ipmid.hpp" + +/** @brief The set channel access IPMI command. + * + * @param[in] netfn + * @param[in] cmd + * @param[in] request + * @param[in,out] response + * @param[out] data_len + * @param[in] context + * + * @return IPMI_CC_OK on success, non-zero otherwise. + */ +ipmi_ret_t ipmi_set_channel_access( + ipmi_netfn_t netfn, + ipmi_cmd_t cmd, + ipmi_request_t request, + ipmi_response_t response, + ipmi_data_len_t data_len, + ipmi_context_t context); + +/** @brief The get channel access IPMI command. + * + * @param[in] netfn + * @param[in] cmd + * @param[in] request + * @param[in,out] response + * @param[out] data_len + * @param[in] context + * + * @return IPMI_CC_OK on success, non-zero otherwise. + */ +ipmi_ret_t ipmi_get_channel_access( + ipmi_netfn_t netfn, + ipmi_cmd_t cmd, + ipmi_request_t request, + ipmi_response_t response, + ipmi_data_len_t data_len, + ipmi_context_t context); + +/** @brief The get channel info IPMI command. + * + * @param[in] netfn + * @param[in] cmd + * @param[in] request + * @param[in,out] response + * @param[out] data_len + * @param[in] context + * + * @return IPMI_CC_OK on success, non-zero otherwise. + */ +ipmi_ret_t ipmi_app_channel_info( + ipmi_netfn_t netfn, + ipmi_cmd_t cmd, + ipmi_request_t request, + ipmi_response_t response, + ipmi_data_len_t data_len, + ipmi_context_t context); + diff --git a/apphandler.cpp b/apphandler.cpp index f1cd2dd..1655144 100644 --- a/apphandler.cpp +++ b/apphandler.cpp @@ -1,4 +1,5 @@ #include "apphandler.h" +#include "app/channel.hpp" #include "app/watchdog.hpp" #include "host-ipmid/ipmid-api.h" #include "ipmid.hpp" @@ -27,8 +28,6 @@ constexpr auto app_obj = "/org/openbmc/NetworkManager/Interface"; constexpr auto app_ifc = "org.openbmc.NetworkManager"; constexpr auto app_nwinterface = "eth0"; -constexpr auto ipv4Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv4"; - void register_netfn_app_functions() __attribute__((constructor)); using namespace phosphor::logging; @@ -366,398 +365,6 @@ ipmi_ret_t ipmi_app_get_bt_capabilities(ipmi_netfn_t netfn, ipmi_cmd_t cmd, return rc; } -extern struct ChannelConfig_t channelConfig; - -ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, - ipmi_cmd_t cmd, - ipmi_request_t request, - ipmi_response_t response, - ipmi_data_len_t data_len, - ipmi_context_t context) -{ - ipmi_ret_t rc = IPMI_CC_OK; - - std::string ipaddress; - std::string gateway; - uint8_t prefix {}; - uint32_t vlanID {}; - std::string networkInterfacePath; - ipmi::DbusObjectInfo ipObject; - ipmi::DbusObjectInfo systemObject; - - // Todo: parse the request data if needed. - // Using Set Channel cmd to apply changes of Set Lan Cmd. - try - { - sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection()); - - log<level::INFO>("Network data from Cache", - entry("PREFIX=%s", channelConfig.netmask.c_str()), - entry("ADDRESS=%s", channelConfig.ipaddr.c_str()), - entry("GATEWAY=%s", channelConfig.gateway.c_str()), - entry("VLAN=%d", channelConfig.vlanID), - entry("IPSRC=%d", channelConfig.ipsrc)); - - if (channelConfig.vlanID != ipmi::network::VLAN_ID_MASK) - { - //get the first twelve bits which is vlan id - //not interested in rest of the bits. - channelConfig.vlanID = le32toh(channelConfig.vlanID); - vlanID = channelConfig.vlanID & ipmi::network::VLAN_ID_MASK; - } - - // if the asked ip src is DHCP then not interested in - // any given data except vlan. - if (channelConfig.ipsrc != ipmi::network::IPOrigin::DHCP) - { - // always get the system object - systemObject = ipmi::getDbusObject( - bus, - ipmi::network::SYSTEMCONFIG_INTERFACE, - ipmi::network::ROOT); - - // the below code is to determine the mode of the interface - // as the handling is same, if the system is configured with - // DHCP or user has given all the data. - try - { - ipmi::ObjectTree ancestorMap; - - ipmi::InterfaceList interfaces { - ipmi::network::ETHERNET_INTERFACE }; - - // if the system is having ip object,then - // get the IP object. - ipObject = ipmi::getDbusObject(bus, - ipmi::network::IP_INTERFACE, - ipmi::network::ROOT, - ipmi::network::IP_TYPE); - - // Get the parent interface of the IP object. - try - { - ancestorMap = ipmi::getAllAncestors(bus, - ipObject.first, - std::move(interfaces)); - } - catch (InternalFailure& e) - { - // if unable to get the parent interface - // then commit the error and return. - log<level::ERR>("Unable to get the parent interface", - entry("PATH=%s", ipObject.first.c_str()), - entry("INTERFACE=%s", - ipmi::network::ETHERNET_INTERFACE)); - commit<InternalFailure>(); - rc = IPMI_CC_UNSPECIFIED_ERROR; - channelConfig.clear(); - return rc; - } - - networkInterfacePath = ancestorMap.begin()->first; - } - catch (InternalFailure& e) - { - // TODO Currently IPMI supports single interface,need to handle - // Multiple interface through - // https://github.com/openbmc/openbmc/issues/2138 - - // if there is no ip configured on the system,then - // get the network interface object. - auto networkInterfaceObject = ipmi::getDbusObject( - bus, - ipmi::network::ETHERNET_INTERFACE, - ipmi::network::ROOT, - ipmi::network::INTERFACE); - - networkInterfacePath = std::move(networkInterfaceObject.first); - } - - // get the configured mode on the system. - auto enableDHCP = ipmi::getDbusProperty( - bus, - ipmi::network::SERVICE, - networkInterfacePath, - ipmi::network::ETHERNET_INTERFACE, - "DHCPEnabled").get<bool>(); - - // check whether user has given all the data - // or the configured system interface is dhcp enabled, - // in both of the cases get the values from the cache. - if ((!channelConfig.ipaddr.empty() && - !channelConfig.netmask.empty() && - !channelConfig.gateway.empty()) || - (enableDHCP)) // configured system interface mode = DHCP - { - //convert mask into prefix - ipaddress = channelConfig.ipaddr; - prefix = ipmi::network::toPrefix(AF_INET, channelConfig.netmask); - gateway = channelConfig.gateway; - if (channelConfig.vlanID != ipmi::network::VLAN_ID_MASK) - { - //get the first twelve bits which is vlan id - //not interested in rest of the bits. - channelConfig.vlanID = le32toh(channelConfig.vlanID); - vlanID = channelConfig.vlanID & ipmi::network::VLAN_ID_MASK; - } - else - { - vlanID = ipmi::network::getVLAN(networkInterfacePath); - } - - } - else // asked ip src = static and configured system src = static - // or partially given data. - { - // We have partial filled cache so get the remaining - // info from the system. - - // Get the network data from the system as user has - // not given all the data then use the data fetched from the - // system but it is implementation dependent,IPMI spec doesn't - // force it. - - // if system is not having any ip object don't throw error, - try - { - auto properties = ipmi::getAllDbusProperties( - bus, - ipObject.second, - ipObject.first, - ipmi::network::IP_INTERFACE); - - ipaddress = channelConfig.ipaddr.empty() ? - ipmi::getIPAddress(bus, - ipmi::network::IP_INTERFACE, - ipmi::network::ROOT, - ipmi::network::IP_TYPE) : - channelConfig.ipaddr; - - prefix = channelConfig.netmask.empty() ? - properties["PrefixLength"].get<uint8_t>() : - ipmi::network::toPrefix(AF_INET, - channelConfig.netmask); - - } - catch (InternalFailure& e) - { - log<level::INFO>("Failed to get IP object which matches", - entry("INTERFACE=%s", ipmi::network::IP_INTERFACE), - entry("MATCH=%s", ipmi::network::IP_TYPE)); - } - - auto systemProperties = ipmi::getAllDbusProperties( - bus, - systemObject.second, - systemObject.first, - ipmi::network::SYSTEMCONFIG_INTERFACE); - - gateway = channelConfig.gateway.empty() ? - systemProperties["DefaultGateway"].get<std::string>() : - channelConfig.gateway; - - } - } - - // Currently network manager doesn't support purging of all the - // ip addresses and the vlan interfaces from the parent interface, - // TODO once the support is there, will make the change here. - // https://github.com/openbmc/openbmc/issues/2141. - - // TODO Currently IPMI supports single interface,need to handle - // Multiple interface through - // https://github.com/openbmc/openbmc/issues/2138 - - // instead of deleting all the vlan interfaces and - // all the ipv4 address,we will call reset method. - //delete all the vlan interfaces - - ipmi::deleteAllDbusObjects(bus, - ipmi::network::ROOT, - ipmi::network::VLAN_INTERFACE); - - // set the interface mode to static - auto networkInterfaceObject = ipmi::getDbusObject( - bus, - ipmi::network::ETHERNET_INTERFACE, - ipmi::network::ROOT, - ipmi::network::INTERFACE); - - // setting the physical interface mode to static. - ipmi::setDbusProperty(bus, - ipmi::network::SERVICE, - networkInterfaceObject.first, - ipmi::network::ETHERNET_INTERFACE, - "DHCPEnabled", - false); - - networkInterfacePath = networkInterfaceObject.first; - - //delete all the ipv4 addresses - ipmi::deleteAllDbusObjects(bus, - ipmi::network::ROOT, - ipmi::network::IP_INTERFACE, - ipmi::network::IP_TYPE); - - if (vlanID) - { - ipmi::network::createVLAN(bus, - ipmi::network::SERVICE, - ipmi::network::ROOT, - ipmi::network::INTERFACE, - vlanID); - - auto networkInterfaceObject = ipmi::getDbusObject( - bus, - ipmi::network::VLAN_INTERFACE, - ipmi::network::ROOT); - - networkInterfacePath = networkInterfaceObject.first; - } - - if (channelConfig.ipsrc == ipmi::network::IPOrigin::DHCP) - { - ipmi::setDbusProperty(bus, - ipmi::network::SERVICE, - networkInterfacePath, - ipmi::network::ETHERNET_INTERFACE, - "DHCPEnabled", - true); - } - else - { - //change the mode to static - ipmi::setDbusProperty(bus, - ipmi::network::SERVICE, - networkInterfacePath, - ipmi::network::ETHERNET_INTERFACE, - "DHCPEnabled", - false); - - if (!ipaddress.empty()) - { - ipmi::network::createIP(bus, - ipmi::network::SERVICE, - networkInterfacePath, - ipv4Protocol, - ipaddress, - prefix); - } - - if (!gateway.empty()) - { - ipmi::setDbusProperty(bus, - systemObject.second, - systemObject.first, - ipmi::network::SYSTEMCONFIG_INTERFACE, - "DefaultGateway", - std::string(gateway)); - } - } - - } - catch (InternalFailure& e) - { - log<level::ERR>("Failed to set network data", - entry("PREFIX=%d", prefix), - entry("ADDRESS=%s", ipaddress.c_str()), - entry("GATEWAY=%s", gateway.c_str()), - entry("VLANID=%d", vlanID), - entry("IPSRC=%d", channelConfig.ipsrc)); - - commit<InternalFailure>(); - rc = IPMI_CC_UNSPECIFIED_ERROR; - } - - channelConfig.clear(); - return rc; -} - -ipmi_ret_t getChannelAccess(ipmi_netfn_t netfn, ipmi_cmd_t cmd, - ipmi_request_t request, ipmi_response_t response, - ipmi_data_len_t data_len, ipmi_context_t context) -{ - auto requestData = reinterpret_cast<const GetChannelAccessRequest*> - (request); - std::vector<uint8_t> outPayload(sizeof(GetChannelAccessResponse)); - auto responseData = reinterpret_cast<GetChannelAccessResponse*> - (outPayload.data()); - - // Channel 1 is arbitrarily assigned to ETH0 channel - constexpr auto channelOne = 0x01; - - /* - * The value Eh is used as a way to identify the current channel that - * the command is being received from. - */ - constexpr auto channelE = 0x0E; - - if (requestData->channelNumber != channelOne && - requestData->channelNumber != channelE) - { - *data_len = 0; - return IPMI_CC_INVALID_FIELD_REQUEST; - } - - /* - * [7:6] - reserved - * [5] - 1b = Alerting disabled - * [4] - 1b = per message authentication disabled - * [3] - 0b = User level authentication enabled - * [2:0] - 2h = always available - */ - constexpr auto channelSetting = 0x32; - - responseData->settings = channelSetting; - //Defaulting the channel privilege to administrator level. - responseData->privilegeLimit = PRIVILEGE_ADMIN; - - *data_len = outPayload.size(); - memcpy(response, outPayload.data(), *data_len); - - return IPMI_CC_OK; -} - -// ATTENTION: This ipmi function is very hardcoded on purpose -// OpenBMC does not fully support IPMI. This command is useful -// to have around because it enables testing of interfaces with -// the IPMI tool. -#define GET_CHANNEL_INFO_CHANNEL_OFFSET 0 -// IPMI Table 6-2 -#define IPMI_CHANNEL_TYPE_IPMB 1 -// IPMI Table 6-3 -#define IPMI_CHANNEL_MEDIUM_TYPE_OTHER 6 - -ipmi_ret_t ipmi_app_channel_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd, - ipmi_request_t request, ipmi_response_t response, - ipmi_data_len_t data_len, ipmi_context_t context) -{ - ipmi_ret_t rc = IPMI_CC_OK; - uint8_t resp[] = { - 1, - IPMI_CHANNEL_MEDIUM_TYPE_OTHER, - IPMI_CHANNEL_TYPE_IPMB, - 1,0x41,0xA7,0x00,0,0}; - uint8_t *p = (uint8_t*) request; - - printf("IPMI APP GET CHANNEL INFO\n"); - - // The supported channels numbers are 1 and 8. - // Channel Number E is used as way to identify the current channel - // that the command is being is received from. - if (*p == 0xe || *p == 1 || *p == 8) { - - *data_len = sizeof(resp); - memcpy(response, resp, *data_len); - - } else { - rc = IPMI_CC_PARM_OUT_OF_RANGE; - *data_len = 0; - } - - return rc; -} - ipmi_ret_t ipmi_app_wildcard_handler(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request, ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context) @@ -826,7 +433,7 @@ void register_netfn_app_functions() // <Get Channel Access> printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_CHANNEL_ACCESS); ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHANNEL_ACCESS, NULL, - getChannelAccess, PRIVILEGE_USER); + ipmi_get_channel_access, PRIVILEGE_USER); // <Get Channel Info Command> printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_CHAN_INFO); diff --git a/apphandler.h b/apphandler.h index 497b24b..72997d9 100644 --- a/apphandler.h +++ b/apphandler.h @@ -19,24 +19,4 @@ enum ipmi_netfn_app_cmds IPMI_CMD_GET_CHAN_INFO = 0x42, }; -/** @struct GetChannelAccessRequest - * - * IPMI payload for Get Channel access command request. - */ -struct GetChannelAccessRequest -{ - uint8_t channelNumber; //!< Channel number. - uint8_t volatileSetting; //!< Get non-volatile or the volatile setting. -} __attribute__((packed)); - -/** @struct GetChannelAccessResponse - * - * IPMI payload for Get Channel access command response. - */ -struct GetChannelAccessResponse -{ - uint8_t settings; //!< Channel settings. - uint8_t privilegeLimit; //!< Channel privilege level limit. -} __attribute__((packed)); - #endif |