diff options
author | Ratan Gupta <ratagupt@in.ibm.com> | 2017-07-27 07:07:48 +0530 |
---|---|---|
committer | Ratan Gupta <ratagupt@in.ibm.com> | 2017-08-13 06:46:22 +0530 |
commit | b8e9955db5216a0b170a2fb99125d1f22bb9d1c0 (patch) | |
tree | 122efef97394c3af93b4dc4bbc35fdef2a24c129 | |
parent | 8c31d237f67caa5698fca5aedd449f8c98f0b0c0 (diff) | |
download | phosphor-host-ipmid-b8e9955db5216a0b170a2fb99125d1f22bb9d1c0.tar.gz phosphor-host-ipmid-b8e9955db5216a0b170a2fb99125d1f22bb9d1c0.zip |
Move LAN handling commands to the new xyz interfaces
Change-Id: I4631c79c171883e5f0d531cfb5957a09496e4b3a
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
-rw-r--r-- | apphandler.cpp | 221 | ||||
-rw-r--r-- | transporthandler.cpp | 524 | ||||
-rw-r--r-- | transporthandler.hpp (renamed from transporthandler.h) | 24 | ||||
-rw-r--r-- | types.hpp | 5 | ||||
-rw-r--r-- | utils.cpp | 169 | ||||
-rw-r--r-- | utils.hpp | 87 |
6 files changed, 681 insertions, 349 deletions
diff --git a/apphandler.cpp b/apphandler.cpp index 6759462..7b30edd 100644 --- a/apphandler.cpp +++ b/apphandler.cpp @@ -1,6 +1,9 @@ #include "apphandler.h" #include "host-ipmid/ipmid-api.h" #include "ipmid.hpp" +#include "types.hpp" +#include "utils.hpp" + #include <stdio.h> #include <string.h> #include <stdint.h> @@ -8,7 +11,12 @@ #include <mapper.h> #include <array> #include <arpa/inet.h> -#include "transporthandler.h" +#include "transporthandler.hpp" + +#include <phosphor-logging/log.hpp> +#include <phosphor-logging/elog-errors.hpp> +#include "xyz/openbmc_project/Common/error.hpp" + extern sd_bus *bus; @@ -16,8 +24,13 @@ 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; +using namespace sdbusplus::xyz::openbmc_project::Common::Error; + // Offset in get device id command. typedef struct { @@ -508,114 +521,146 @@ finish: return rc; } -extern struct channel_config_t channel_config; +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 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; - sd_bus *bus = ipmid_get_sd_bus_connection(); - sd_bus_message *reply = nullptr; - sd_bus_error error = SD_BUS_ERROR_NULL; - int r = 0; - char *app = nullptr; - int family = 0; - unsigned char prefixlen = 0; - char* ipaddr = nullptr; - uint32_t mask = 0xFFFFFFFF; - char* gateway = nullptr; - char tmp_netmask[INET_ADDRSTRLEN]; + std::string ipaddress; + std::string gateway; + uint8_t prefix {}; // Todo: parse the request data if needed. // Using Set Channel cmd to apply changes of Set Lan Cmd. + try + { - r = mapper_get_service(bus, app_obj, &app); - if (r < 0) { - fprintf(stderr, "Failed to get %s bus name: %s\n", - app_obj, strerror(-r)); - rc = IPMI_CC_UNSPECIFIED_ERROR; - goto finish; - } + sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection()); - r = sd_bus_call_method(bus, app, app_obj, app_ifc, "GetAddress4", &error, - &reply, "s", app_nwinterface); - if (r < 0) { - fprintf(stderr, "Failed to call Get Method: %s\n", strerror(-r)); - rc = IPMI_CC_UNSPECIFIED_ERROR; - goto finish; - } + 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())); - r = sd_bus_message_read(reply, "iyss", - &family, &prefixlen, &ipaddr, &gateway); - if (r < 0) { - fprintf(stderr, "Failed to get a response: %s\n", strerror(-r)); - rc = IPMI_CC_RESPONSE_ERROR; - goto finish; - } + auto systemObject = ipmi::getDbusObject(bus, + ipmi::network::SYSTEMCONFIG_INTERFACE, + ipmi::network::ROOT); - printf("N/W data from Cache: %s:%s:%s\n", - channel_config.new_ipaddr.c_str(), - channel_config.new_netmask.c_str(), - channel_config.new_gateway.c_str()); + // TODO Currently IPMI supports single interface,need to handle + // Multiple interface through + // https://github.com/openbmc/openbmc/issues/2138 - if(channel_config.new_ipaddr.empty()) { - channel_config.new_ipaddr.assign(ipaddr); - } + auto networkInterfaceObject = ipmi::getDbusObject( + bus, + ipmi::network::ETHERNET_INTERFACE, + ipmi::network::ROOT, + ipmi::network::INTERFACE); - if(channel_config.new_netmask.empty()) { - mask = htonl(mask<<(32-prefixlen)); - uint8_t* p = (uint8_t*)&mask; - snprintf(tmp_netmask, INET_ADDRSTRLEN, "%d.%d.%d.%d", - *p, *(p+1), *(p+2), *(p+3)); - channel_config.new_netmask.assign(tmp_netmask); - } - if(channel_config.new_gateway.empty()) { - channel_config.new_gateway.assign(gateway); + // check wthether user has given all the data + if (!channelConfig.ipaddr.empty() && + !channelConfig.netmask.empty() && + !channelConfig.gateway.empty()) + { + //convert mask into prefix + ipaddress = channelConfig.ipaddr; + prefix = ipmi::network::toPrefix(AF_INET, channelConfig.netmask); + gateway = channelConfig.gateway; + } + else + { + // gets 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 ipObjectInfo = ipmi::getDbusObject(bus, + ipmi::network::IP_INTERFACE, + ipmi::network::ROOT, + ipmi::network::IP_TYPE); + + auto properties = ipmi::getAllDbusProperties(bus, + ipObjectInfo.second, + ipObjectInfo.first, + ipmi::network::IP_INTERFACE); + + ipaddress = channelConfig.ipaddr.empty() ? + std::move(properties["Address"].get<std::string>()) : + 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() ? + std::move(systemProperties["DefaultGateway"].get<std::string>()) : + channelConfig.gateway; + + } + + // Currently network manager doesn't support purging of all the + // ip addresses 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 + + //delete all the ipv4 addresses + + ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT, + ipmi::network::IP_INTERFACE, + ipmi::network::IP_TYPE); + + ipmi::network::createIP(bus, networkInterfaceObject.second, + networkInterfaceObject.first, + ipv4Protocol, ipaddress, prefix); + + ipmi::setDbusProperty(bus, systemObject.second, systemObject.first, + ipmi::network::SYSTEMCONFIG_INTERFACE, + "DefaultGateway", gateway); + } + catch (InternalFailure& e) + { + log<level::ERR>("Failed to set network data", + entry("PREFIX=%d", prefix), + entry("ADDRESS=%s", ipaddress), + entry("GATEWAY=%s", gateway)); - printf("N/W data from HW %s:%d:%s:%s\n", - family==AF_INET?"IPv4":"IPv6", prefixlen, ipaddr,gateway); - printf("N/W data from Cache: %s:%s:%s\n", - channel_config.new_ipaddr.c_str(), - channel_config.new_netmask.c_str(), - channel_config.new_gateway.c_str()); - - r = sd_bus_call_method(bus, // On the System Bus - app, // Service to contact - app_obj, // Object path - app_ifc, // Interface name - "SetAddress4", // Method to be called - &error, // object to return error - &reply, // Response message on success - "ssss", // input message (Interface, - // IP Address, Netmask, Gateway) - app_nwinterface, // eth0 - channel_config.new_ipaddr.c_str(), - channel_config.new_netmask.c_str(), - channel_config.new_gateway.c_str()); - if(r < 0) { - fprintf(stderr, "Failed to set network data %s:%s:%s %s\n", - channel_config.new_ipaddr.c_str(), - channel_config.new_netmask.c_str(), - channel_config.new_gateway.c_str(), - error.message); + commit<InternalFailure>(); rc = IPMI_CC_UNSPECIFIED_ERROR; } - channel_config.new_ipaddr.clear(); - channel_config.new_netmask.clear(); - channel_config.new_gateway.clear(); - -finish: - sd_bus_error_free(&error); - reply = sd_bus_message_unref(reply); - free(app); - + channelConfig.clear(); return rc; } diff --git a/transporthandler.cpp b/transporthandler.cpp index 9cbae11..4de9400 100644 --- a/transporthandler.cpp +++ b/transporthandler.cpp @@ -6,7 +6,12 @@ #include "host-ipmid/ipmid-api.h" #include "ipmid.hpp" -#include "transporthandler.h" +#include "transporthandler.hpp" +#include "utils.hpp" + +#include <phosphor-logging/log.hpp> +#include <phosphor-logging/elog-errors.hpp> +#include "xyz/openbmc_project/Common/error.hpp" #define SYSTEMD_NETWORKD_DBUS 1 @@ -23,7 +28,7 @@ const char *nwinterface = "eth0"; const int SIZE_MAC = 18; //xx:xx:xx:xx:xx:xx -struct channel_config_t channel_config; +struct ChannelConfig_t channelConfig; const uint8_t SET_COMPLETE = 0; const uint8_t SET_IN_PROGRESS = 1; @@ -33,104 +38,158 @@ const uint8_t SET_IN_PROGRESS_RESERVED = 3; //Reserved // Status of Set-In-Progress Parameter (# 0) uint8_t lan_set_in_progress = SET_COMPLETE; - +using namespace phosphor::logging; +using namespace sdbusplus::xyz::openbmc_project::Common::Error; void register_netfn_transport_functions() __attribute__((constructor)); -// Helper Function to get IP Address/NetMask/Gateway from Network Manager or +// Helper Function to get IP Address/NetMask/Gateway/MAC Address from Network Manager or // Cache based on Set-In-Progress State -ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t * data) +ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data) { - sd_bus *bus = ipmid_get_sd_bus_connection(); - sd_bus_message *reply = NULL; - sd_bus_error error = SD_BUS_ERROR_NULL; - int family; - unsigned char prefixlen; - char* ipaddr = NULL; - unsigned long mask = 0xFFFFFFFF; - char* gateway = NULL; - int r = 0; ipmi_ret_t rc = IPMI_CC_OK; - char *app = NULL; - - r = mapper_get_service(bus, obj, &app); - if (r < 0) { - fprintf(stderr, "Failed to get %s bus name: %s\n", - obj, strerror(-r)); - rc = IPMI_CC_UNSPECIFIED_ERROR; - goto cleanup; - } - r = sd_bus_call_method(bus, app, obj, ifc, "GetAddress4", &error, - &reply, "s", nwinterface); - if(r < 0) - { - fprintf(stderr, "Failed to call Get Method: %s\n", strerror(-r)); - rc = IPMI_CC_UNSPECIFIED_ERROR; - goto cleanup; - } - - r = sd_bus_message_read(reply, "iyss", - &family, &prefixlen, &ipaddr, &gateway); - if(r < 0) - { - fprintf(stderr, "Failed to get a response: %s\n", strerror(-rc)); - rc = IPMI_CC_RESPONSE_ERROR; - goto cleanup; - } - - printf("N/W data from HW %s:%d:%s:%s\n", - family==AF_INET?"IPv4":"IPv6", prefixlen, ipaddr,gateway); - printf("N/W data from Cache: %s:%s:%s\n", - channel_config.new_ipaddr.c_str(), - channel_config.new_netmask.c_str(), - channel_config.new_gateway.c_str()); - - if(lan_param == LAN_PARM_IP) + sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection()); + try { - if(lan_set_in_progress == SET_COMPLETE) - { - std::string ipaddrstr(ipaddr); - inet_pton(AF_INET, ipaddrstr.c_str(),(void *)data); - } - else if(lan_set_in_progress == SET_IN_PROGRESS) + switch (lan_param) { - inet_pton(AF_INET, channel_config.new_ipaddr.c_str(), (void *)data); + case LAN_PARM_IP: + { + std::string ipaddress; + if (lan_set_in_progress == SET_COMPLETE) + { + auto ipObjectInfo = ipmi::getDbusObject( + bus, + ipmi::network::IP_INTERFACE, + ipmi::network::ROOT, + ipmi::network::IP_TYPE); + + auto properties = ipmi::getAllDbusProperties( + bus, + ipObjectInfo.second, + ipObjectInfo.first, + ipmi::network::IP_INTERFACE); + + ipaddress = properties["Address"].get<std::string>(); + } + else if (lan_set_in_progress == SET_IN_PROGRESS) + { + ipaddress = channelConfig.ipaddr; + } + + inet_pton(AF_INET, ipaddress.c_str(), + reinterpret_cast<void*>(data)); + } + break; + + case LAN_PARM_SUBNET: + { + if (lan_set_in_progress == SET_COMPLETE) + { + auto ipObjectInfo = ipmi::getDbusObject( + bus, + ipmi::network::IP_INTERFACE, + ipmi::network::ROOT, + ipmi::network::IP_TYPE); + + auto properties = ipmi::getAllDbusProperties( + bus, + ipObjectInfo.second, + ipObjectInfo.first, + ipmi::network::IP_INTERFACE); + + auto prefix = properties["PrefixLength"].get<uint8_t>(); + unsigned long mask = ipmi::network::MASK_32_BIT; + mask = htonl(mask << (ipmi::network::BITS_32 - prefix)); + memcpy(data, &mask, ipmi::network::IPV4_ADDRESS_SIZE_BYTE); + } + else if (lan_set_in_progress == SET_IN_PROGRESS) + { + inet_pton(AF_INET, channelConfig.netmask.c_str(), + reinterpret_cast<void*>(data)); + + } + + } + break; + + case LAN_PARM_GATEWAY: + { + std::string gateway; + + if (lan_set_in_progress == SET_COMPLETE) + { + auto systemObject = ipmi::getDbusObject( + bus, + ipmi::network::SYSTEMCONFIG_INTERFACE, + ipmi::network::ROOT); + + auto systemProperties = ipmi::getAllDbusProperties( + bus, + systemObject.second, + systemObject.first, + ipmi::network::SYSTEMCONFIG_INTERFACE); + + gateway = systemProperties["DefaultGateway"].get< + std::string>(); + + } + else if (lan_set_in_progress == SET_IN_PROGRESS) + { + gateway = channelConfig.gateway; + } + + inet_pton(AF_INET, gateway.c_str(), + reinterpret_cast<void*>(data)); + + } + break; + + case LAN_PARM_MAC: + { + std::string macAddress; + if (lan_set_in_progress == SET_COMPLETE) + { + auto macObjectInfo = ipmi::getDbusObject( + bus, + ipmi::network::MAC_INTERFACE, + ipmi::network::ROOT); + + auto variant = ipmi::getDbusProperty( + bus, + macObjectInfo.second, + macObjectInfo.first, + ipmi::network::MAC_INTERFACE, + "MACAddress"); + + macAddress = variant.get<std::string>(); + + } + else if (lan_set_in_progress == SET_IN_PROGRESS) + { + macAddress = channelConfig.macAddress; + } + + sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT, + (data), + (data + 1), + (data + 2), + (data + 3), + (data + 4), + (data + 5)); + } + break; + + default: + rc = IPMI_CC_PARM_OUT_OF_RANGE; } } - else if(lan_param == LAN_PARM_SUBNET) - { - if(lan_set_in_progress == SET_COMPLETE) - { - mask = htonl(mask<<(32-prefixlen)); - memcpy(data, &mask, 4); - } - else if(lan_set_in_progress == SET_IN_PROGRESS) - { - inet_pton(AF_INET, channel_config.new_netmask.c_str(), (void *)data); - } - } - else if(lan_param == LAN_PARM_GATEWAY) + catch (InternalFailure& e) { - if(lan_set_in_progress == SET_COMPLETE) - { - std::string gatewaystr(gateway); - inet_pton(AF_INET, gatewaystr.c_str(), (void *)data); - } - else if(lan_set_in_progress == SET_IN_PROGRESS) - { - inet_pton(AF_INET, channel_config.new_gateway.c_str(),(void *)data); - } - } - else - { - rc = IPMI_CC_PARM_OUT_OF_RANGE; + commit<InternalFailure>(); + rc = IPMI_CC_UNSPECIFIED_ERROR; + return rc; } - -cleanup: - sd_bus_error_free(&error); - reply = sd_bus_message_unref(reply); - free(app); - return rc; } @@ -145,120 +204,144 @@ ipmi_ret_t ipmi_transport_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd, return rc; } -struct set_lan_t { +struct set_lan_t +{ uint8_t channel; uint8_t parameter; uint8_t data[8]; // Per IPMI spec, not expecting more than this size -} __attribute__ ((packed)); - -ipmi_ret_t ipmi_transport_set_lan(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) +} __attribute__((packed)); + +ipmi_ret_t ipmi_transport_set_lan(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; *data_len = 0; - sd_bus *bus = ipmid_get_sd_bus_connection(); - sd_bus_message *reply = nullptr; - sd_bus_error error = SD_BUS_ERROR_NULL; - int r = 0; - char *app = nullptr; - - char tmp_ipaddr[INET_ADDRSTRLEN]; - char tmp_netmask[INET_ADDRSTRLEN]; - char tmp_gateway[INET_ADDRSTRLEN]; - - printf("IPMI SET_LAN\n"); - - set_lan_t *reqptr = (set_lan_t*) request; - - if (reqptr->parameter == LAN_PARM_IP) { - snprintf(tmp_ipaddr, INET_ADDRSTRLEN, "%d.%d.%d.%d", - reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]); - channel_config.new_ipaddr.assign(tmp_ipaddr); - } else if (reqptr->parameter == LAN_PARM_MAC) { - char mac[SIZE_MAC]; - - snprintf(mac, SIZE_MAC, "%02x:%02x:%02x:%02x:%02x:%02x", - reqptr->data[0], - reqptr->data[1], - reqptr->data[2], - reqptr->data[3], - reqptr->data[4], - reqptr->data[5]); - - r = mapper_get_service(bus, obj, &app); - if (r < 0) { - fprintf(stderr, "Failed to get %s bus name: %s\n", - obj, strerror(-r)); - goto finish; + + char ipaddr[INET_ADDRSTRLEN]; + char netmask[INET_ADDRSTRLEN]; + char gateway[INET_ADDRSTRLEN]; + + auto reqptr = reinterpret_cast<const set_lan_t*>(request); + sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection()); + + switch (reqptr->parameter) + { + case LAN_PARM_IP: + { + snprintf(ipaddr, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT, + reqptr->data[0], reqptr->data[1], + reqptr->data[2], reqptr->data[3]); + + channelConfig.ipaddr.assign(ipaddr); + } - r = sd_bus_call_method(bus, app, obj, ifc, "SetHwAddress", &error, - &reply, "ss", nwinterface, mac); - if (r < 0) { - fprintf(stderr, "Failed to call the method: %s\n", strerror(-r)); - rc = IPMI_CC_UNSPECIFIED_ERROR; + break; + + case LAN_PARM_MAC: + { + char mac[SIZE_MAC]; + + snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT, + reqptr->data[0], + reqptr->data[1], + reqptr->data[2], + reqptr->data[3], + reqptr->data[4], + reqptr->data[5]); + + auto macObjectInfo = ipmi::getDbusObject( + bus, + ipmi::network::MAC_INTERFACE, + ipmi::network::ROOT, + ipmi::network::INTERFACE); + + ipmi::setDbusProperty(bus, + macObjectInfo.second, + macObjectInfo.first, + ipmi::network::MAC_INTERFACE, + "MACAddress", + std::string(mac)); + + channelConfig.macAddress = mac; + } - } else if (reqptr->parameter == LAN_PARM_SUBNET) - { - snprintf(tmp_netmask, INET_ADDRSTRLEN, "%d.%d.%d.%d", - reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]); - channel_config.new_netmask.assign(tmp_netmask); - } else if (reqptr->parameter == LAN_PARM_GATEWAY) - { - snprintf(tmp_gateway, INET_ADDRSTRLEN, "%d.%d.%d.%d", - reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]); - channel_config.new_gateway.assign(tmp_gateway); - } else if (reqptr->parameter == LAN_PARM_INPROGRESS) - { - if(reqptr->data[0] == SET_COMPLETE) { - lan_set_in_progress = SET_COMPLETE; + break; + + case LAN_PARM_SUBNET: + { + snprintf(netmask, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT, + reqptr->data[0], reqptr->data[1], + reqptr->data[2], reqptr->data[3]); + channelConfig.netmask.assign(netmask); + } + break; - printf("N/W data from Cache: %s:%s:%s\n", - channel_config.new_ipaddr.c_str(), - channel_config.new_netmask.c_str(), - channel_config.new_gateway.c_str()); - printf("Use Set Channel Access command to apply them\n"); + case LAN_PARM_GATEWAY: + { + snprintf(gateway, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT, + reqptr->data[0], reqptr->data[1], + reqptr->data[2], reqptr->data[3]); + channelConfig.gateway.assign(gateway); + + } + break; - } else if(reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress + case LAN_PARM_INPROGRESS: { - lan_set_in_progress = SET_IN_PROGRESS; + if (reqptr->data[0] == SET_COMPLETE) + { + lan_set_in_progress = SET_COMPLETE; + + 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())); + + log<level::INFO>("Use Set Channel Access command to apply"); + + } + else if (reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress + { + lan_set_in_progress = SET_IN_PROGRESS; + } + + } + break; + + default: + { + log<level::ERR>("Unsupported parameter", + entry("PARAMETER=0x%x", reqptr->parameter)); + rc = IPMI_CC_PARM_NOT_SUPPORTED; } - } else - { - fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter); - rc = IPMI_CC_PARM_NOT_SUPPORTED; - } -finish: - sd_bus_error_free(&error); - reply = sd_bus_message_unref(reply); - free(app); + } return rc; } -struct get_lan_t { +struct get_lan_t +{ uint8_t rev_channel; uint8_t parameter; uint8_t parameter_set; uint8_t parameter_block; -} __attribute__ ((packed)); - -ipmi_ret_t ipmi_transport_get_lan(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) +} __attribute__((packed)); + +ipmi_ret_t ipmi_transport_get_lan(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; *data_len = 0; - sd_bus *bus = ipmid_get_sd_bus_connection(); - sd_bus_message *reply = NULL; - sd_bus_error error = SD_BUS_ERROR_NULL; - int r = 0; const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0 - int i = 0; - char *app = NULL; - - printf("IPMI GET_LAN\n"); get_lan_t *reqptr = (get_lan_t*) request; @@ -270,9 +353,6 @@ ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd, return IPMI_CC_OK; } - // TODO Use dbus interface once available. For now use ip cmd. - // TODO Add the rest of the parameters, like gateway - if (reqptr->parameter == LAN_PARM_INPROGRESS) { uint8_t buf[] = {current_revision, lan_set_in_progress}; @@ -291,16 +371,26 @@ ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd, *data_len = sizeof(buf); memcpy(response, &buf, *data_len); } - else if ((reqptr->parameter == LAN_PARM_IP) || (reqptr->parameter == LAN_PARM_SUBNET) || (reqptr->parameter == LAN_PARM_GATEWAY)) + else if ((reqptr->parameter == LAN_PARM_IP) || + (reqptr->parameter == LAN_PARM_SUBNET) || + (reqptr->parameter == LAN_PARM_GATEWAY) || + (reqptr->parameter == LAN_PARM_MAC)) { - uint8_t buf[5]; + uint8_t buf[ipmi::network::MAC_ADDRESS_SIZE_BYTE + 1]; *data_len = sizeof(current_revision); memcpy(buf, ¤t_revision, *data_len); - if(getNetworkData(reqptr->parameter, &buf[1]) == IPMI_CC_OK) + if (getNetworkData(reqptr->parameter, &buf[1]) == IPMI_CC_OK) { - *data_len = sizeof(buf); + if (reqptr->parameter == LAN_PARM_MAC) + { + *data_len = sizeof(buf); + } + else + { + *data_len = ipmi::network::IPV4_ADDRESS_SIZE_BYTE + 1; + } memcpy(response, &buf, *data_len); } else @@ -308,75 +398,13 @@ ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd, rc = IPMI_CC_UNSPECIFIED_ERROR; } } - else if (reqptr->parameter == LAN_PARM_MAC) - { - //string to parse: link/ether xx:xx:xx:xx:xx:xx - uint8_t buf[7]; - char *eaddr1 = NULL; - - r = mapper_get_service(bus, obj, &app); - if (r < 0) { - fprintf(stderr, "Failed to get %s bus name: %s\n", - obj, strerror(-r)); - goto cleanup; - } - r = sd_bus_call_method(bus, app, obj, ifc, "GetHwAddress", &error, - &reply, "s", nwinterface); - if(r < 0) - { - fprintf(stderr, "Failed to call Get Method: %s\n", strerror(-r)); - rc = IPMI_CC_UNSPECIFIED_ERROR; - goto cleanup; - } - - r = sd_bus_message_read(reply, "s", &eaddr1); - if (r < 0) - { - fprintf(stderr, "Failed to get a response: %s", strerror(-r)); - rc = IPMI_CC_UNSPECIFIED_ERROR; - goto cleanup; - } - if (eaddr1 == NULL) - { - fprintf(stderr, "Failed to get a valid response: %s", strerror(-r)); - rc = IPMI_CC_UNSPECIFIED_ERROR; - goto cleanup; - } - - memcpy((void*)&buf[0], ¤t_revision, 1); - - char *tokptr = NULL; - char* digit = strtok_r(eaddr1, ":", &tokptr); - if (digit == NULL) - { - fprintf(stderr, "Unexpected MAC format: %s", eaddr1); - rc = IPMI_CC_RESPONSE_ERROR; - goto cleanup; - } - - i=0; - while (digit != NULL) - { - int resp_byte = strtoul(digit, NULL, 16); - memcpy((void*)&buf[i+1], &resp_byte, 1); - i++; - digit = strtok_r(NULL, ":", &tokptr); - } - - *data_len = sizeof(buf); - memcpy(response, &buf, *data_len); - } else { - fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter); + log<level::ERR>("Unsupported parameter", + entry("PARAMETER=0x%x", reqptr->parameter)); rc = IPMI_CC_PARM_NOT_SUPPORTED; } -cleanup: - sd_bus_error_free(&error); - reply = sd_bus_message_unref(reply); - free(app); - return rc; } diff --git a/transporthandler.h b/transporthandler.hpp index 171a636..f1fd410 100644 --- a/transporthandler.h +++ b/transporthandler.hpp @@ -1,5 +1,6 @@ -#ifndef __HOST_IPMI_TRANSPORT_HANDLER_H__ -#define __HOST_IPMI_TRANSPORT_HANDLER_H__ +#pragma once + +#include <string> // IPMI commands for Transport net functions. enum ipmi_netfn_storage_cmds @@ -24,10 +25,17 @@ static const int LAN_PARM_MAC = 5; static const int LAN_PARM_SUBNET = 6; static const int LAN_PARM_GATEWAY = 12; -struct channel_config_t { - std::string new_ipaddr; - std::string new_netmask; - std::string new_gateway; +struct ChannelConfig_t +{ + std::string ipaddr; + std::string netmask; + std::string gateway; + std::string macAddress; + void clear() + { + ipaddr.clear(); + netmask.clear(); + gateway.clear(); + macAddress.clear(); + } }; - -#endif @@ -22,6 +22,7 @@ using Value = sdbusplus::message::variant<bool, uint8_t, int16_t, int64_t, uint64_t, std::string>; using PropertyMap = std::map<DbusProperty, Value>; + using ObjectTree = std::map<DbusObjectPath, std::map<DbusService, std::vector<DbusInterface>>>; @@ -106,5 +107,9 @@ constexpr auto IPV6_ADDRESS_SIZE_BYTE = 16; constexpr auto DEFAULT_MAC_ADDRESS = "00:00:00:00:00:00"; constexpr auto DEFAULT_ADDRESS = "0.0.0.0"; +constexpr auto MAC_ADDRESS_SIZE_BYTE = 6; +constexpr auto BITS_32 = 32; +constexpr auto MASK_32_BIT = 0xFFFFFFFF; + }//namespace network }//namespace ipmi @@ -1,9 +1,12 @@ #include "utils.hpp" -#include "host-ipmid/ipmid-api.h" #include <phosphor-logging/log.hpp> #include <phosphor-logging/elog-errors.hpp> #include "xyz/openbmc_project/Common/error.hpp" +#include <arpa/inet.h> +#include <dirent.h> +#include <net/if.h> + namespace ipmi { @@ -203,7 +206,171 @@ std::string getService(sdbusplus::bus::bus& bus, return mapperResponse.begin()->first; } +ipmi::ObjectTree getAllDbusObjects(sdbusplus::bus::bus& bus, + const std::string& serviceRoot, + const std::string& interface, + const std::string& match) +{ + std::vector<std::string> interfaces; + interfaces.emplace_back(interface); + + auto depth = 0; + + auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME, + MAPPER_OBJ, + MAPPER_INTF, + "GetSubTree"); + + mapperCall.append(serviceRoot, depth, interfaces); + + auto mapperReply = bus.call(mapperCall); + if (mapperReply.is_method_error()) + { + log<level::ERR>("Error in mapper call", + entry("SERVICEROOT=%s",serviceRoot.c_str()), + entry("INTERFACE=%s", interface.c_str())); + + elog<InternalFailure>(); + } + + ObjectTree objectTree; + mapperReply.read(objectTree); + + for (auto it = objectTree.begin(); it != objectTree.end();) + { + if (it->first.find(match) == std::string::npos) + { + it = objectTree.erase(it); + } + else + { + ++it; + } + } + + return objectTree; +} + +void deleteAllDbusObjects(sdbusplus::bus::bus& bus, + const std::string& serviceRoot, + const std::string& interface, + const std::string& match) +{ + try + { + auto objectTree = getAllDbusObjects(bus, serviceRoot, interface, match); + + for (auto& object : objectTree) + { + method_no_args::callDbusMethod(bus, + object.second.begin()->first, + object.first, + DELETE_INTERFACE, "Delete"); + } + } + catch (InternalFailure& e) + { + log<level::INFO>("Unable to delete the objects having", + entry("INTERFACE=%s", interface.c_str()), + entry("SERVICE=%s", serviceRoot.c_str())); + } +} + + +namespace method_no_args +{ + +void callDbusMethod(sdbusplus::bus::bus& bus, + const std::string& service, + const std::string& objPath, + const std::string& interface, + const std::string& method) + +{ + auto busMethod = bus.new_method_call( + service.c_str(), + objPath.c_str(), + interface.c_str(), + method.c_str()); + + auto reply = bus.call(busMethod); + + if (reply.is_method_error()) + { + log<level::ERR>("Failed to execute method", + entry("METHOD=%s", method.c_str()), + entry("PATH=%s", objPath.c_str()), + entry("INTERFACE=%s", interface.c_str())); + elog<InternalFailure>(); + } +} + +}// namespace method_no_args + +namespace network +{ + +void createIP(sdbusplus::bus::bus& bus, + const std::string& service, + const std::string& objPath, + const std::string& protocolType, + const std::string& ipaddress, + uint8_t prefix) +{ + std::string gateway = ""; + + auto busMethod = bus.new_method_call( + service.c_str(), + objPath.c_str(), + IP_CREATE_INTERFACE, + "IP"); + + busMethod.append(protocolType, ipaddress, prefix, gateway); + + auto reply = bus.call(busMethod); + + if (reply.is_method_error()) + { + log<level::ERR>("Failed to excute method", + entry("METHOD=%s", "IP"), + entry("PATH=%s", objPath.c_str())); + elog<InternalFailure>(); + } + +} + +uint8_t toPrefix(int addressFamily, const std::string& subnetMask) +{ + if (addressFamily == AF_INET6) + { + return 0; + } + + uint32_t buff {}; + + auto rc = inet_pton(addressFamily, subnetMask.c_str(), &buff); + if (rc <= 0) + { + log<level::ERR>("inet_pton failed:", + entry("SUBNETMASK=%s", subnetMask)); + return 0; + } + + buff = be32toh(buff); + // total no of bits - total no of leading zero == total no of ones + if (((sizeof(buff) * 8) - (__builtin_ctz(buff))) == __builtin_popcount(buff)) + { + return __builtin_popcount(buff); + } + else + { + log<level::ERR>("Invalid Mask", + entry("SUBNETMASK=%s", subnetMask)); + return 0; + } +} +} // namespace network } // namespace ipmi @@ -12,16 +12,14 @@ constexpr auto MAPPER_INTF = "xyz.openbmc_project.ObjectMapper"; constexpr auto ROOT = "/"; constexpr auto HOST_MATCH = "host0"; -constexpr auto PROP_INTF = "org.freedesktop.DBus.Properties"; -constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP"; -constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress"; +constexpr auto PROP_INTF = "org.freedesktop.DBus.Properties"; +constexpr auto DELETE_INTERFACE = "xyz.openbmc_project.Object.Delete"; constexpr auto METHOD_GET = "Get"; constexpr auto METHOD_GET_ALL = "GetAll"; constexpr auto METHOD_SET = "Set"; - /** * @brief Get the DBUS Service name for the input dbus path * @@ -90,6 +88,87 @@ void setDbusProperty(sdbusplus::bus::bus& bus, const std::string& property, const Value& value); +/** @brief Gets all the dbus objects from the given service root + * which matches the object identifier. + * @param[in] bus - DBUS Bus Object. + * @param[in] serviceRoot - Service root path. + * @param[in] interface - Dbus interface. + * @param[in] match - Identifier for a path. + * @returns map of object path and service info. + */ +ObjectTree getAllDbusObjects(sdbusplus::bus::bus& bus, + const std::string& serviceRoot, + const std::string& interface, + const std::string& match); + +/** @brief Deletes all the dbus objects from the given service root + which matches the object identifier. + * @param[in] bus - DBUS Bus Object. + * @param[in] serviceRoot - Service root path. + * @param[in] interface - Dbus interface. + * @param[in] match - Identifier for object. + */ +void deleteAllDbusObjects(sdbusplus::bus::bus& bus, + const std::string& serviceRoot, + const std::string& interface, + const std::string& match = {}); + +namespace method_no_args +{ + +/** @brief Calls the Dbus method which waits for response. + * @param[in] bus - DBUS Bus Object. + * @param[in] service - Dbus service name. + * @param[in] objPath - Dbus object path. + * @param[in] interface - Dbus interface. + * @param[in] method - Dbus method. + */ +void callDbusMethod(sdbusplus::bus::bus& bus, + const std::string& service, + const std::string& objPath, + const std::string& interface, + const std::string& method); + +} //namespace method_no_args + +namespace network +{ + +constexpr auto ROOT = "/xyz/openbmc_project/network"; +constexpr auto NETWORK_SERVICE = "xyz.openbmc_project.Network"; +constexpr auto INTERFACE = "eth0"; +constexpr auto IP_TYPE = "ipv4"; +constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP"; +constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress"; +constexpr auto SYSTEMCONFIG_INTERFACE = "xyz.openbmc_project.Network.SystemConfiguration"; +constexpr auto ETHERNET_INTERFACE = "xyz.openbmc_project.Network.EthernetInterface"; +constexpr auto IP_CREATE_INTERFACE = "xyz.openbmc_project.Network.IP.Create"; + +/* @brief converts the given subnet into prefix notation. + * @param[in] addressFamily - IP address family(AF_INET/AF_INET6). + * @param[in] mask - Subnet Mask. + * @returns prefix. + */ +uint8_t toPrefix(int addressFamily, const std::string& subnetMask); + + +/** @brief Sets the ip on the system. + * @param[in] bus - DBUS Bus Object. + * @param[in] service - Dbus service name. + * @param[in] objPath - Dbus object path. + * @param[in] protocolType - Protocol type + * @param[in] ipaddress - IPaddress. + * @param[in] prefix - Prefix length. + */ +void createIP(sdbusplus::bus::bus& bus, + const std::string& service, + const std::string& objPath, + const std::string& protocolType, + const std::string& ipaddress, + uint8_t prefix); + +}//namespace network + } // namespace ipmi |