#include #include #include #include #include #include #include #if __has_include() #include #elif __has_include() #include namespace std { // splice experimental::filesystem into std namespace filesystem = std::experimental::filesystem; } #else # error filesystem not available #endif #include "app/channel.hpp" #include "host-ipmid/ipmid-api.h" #include "ipmid.hpp" #include "timer.hpp" #include "transporthandler.hpp" #include "utils.hpp" #include "net.hpp" #include #include #include "xyz/openbmc_project/Common/error.hpp" #define SYSTEMD_NETWORKD_DBUS 1 #ifdef SYSTEMD_NETWORKD_DBUS #include #include #endif extern std::unique_ptr networkTimer; const int SIZE_MAC = 18; //xx:xx:xx:xx:xx:xx constexpr auto ipv4Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv4"; std::map> channelConfig; using namespace phosphor::logging; using namespace sdbusplus::xyz::openbmc_project::Common::Error; namespace fs = std::filesystem; void register_netfn_transport_functions() __attribute__((constructor)); struct ChannelConfig_t* getChannelConfig(int channel) { auto item = channelConfig.find(channel); if (item == channelConfig.end()) { channelConfig[channel] = std::make_unique(); } return channelConfig[channel].get(); } // 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, int channel) { ipmi_ret_t rc = IPMI_CC_OK; sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection()); auto ethdevice = ipmi::network::ChanneltoEthernet(channel); // if ethdevice is an empty string they weren't expecting this channel. if (ethdevice.empty()) { // TODO: return error from getNetworkData() return IPMI_CC_INVALID_FIELD_REQUEST; } auto ethIP = ethdevice + "/" + ipmi::network::IP_TYPE; auto channelConf = getChannelConfig(channel); try { switch (lan_param) { case LAN_PARM_IP: { std::string ipaddress; if (channelConf->lan_set_in_progress == SET_COMPLETE) { try { auto ipObjectInfo = ipmi::getIPObject( bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIP); auto properties = ipmi::getAllDbusProperties( bus, ipObjectInfo.second, ipObjectInfo.first, ipmi::network::IP_INTERFACE); ipaddress = properties["Address"].get(); } // ignore the exception, as it is a valid condition that // the system is not configured with any IP. catch (InternalFailure& e) { // nothing to do. } } else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS) { ipaddress = channelConf->ipaddr; } inet_pton(AF_INET, ipaddress.c_str(), reinterpret_cast(data)); } break; case LAN_PARM_IPSRC: { std::string networkInterfacePath; if (channelConf->lan_set_in_progress == SET_COMPLETE) { try { ipmi::ObjectTree ancestorMap; // if the system is having ip object,then // get the IP object. auto ipObject = ipmi::getDbusObject( bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIP); // Get the parent interface of the IP object. try { ipmi::InterfaceList interfaces; interfaces.emplace_back( ipmi::network::ETHERNET_INTERFACE); 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("Unable to get the parent interface", entry("PATH=%s", ipObject.first.c_str()), entry("INTERFACE=%s", ipmi::network::ETHERNET_INTERFACE)); break; } // for an ip object there would be single parent // interface. networkInterfacePath = ancestorMap.begin()->first; } catch (InternalFailure& e) { // 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, ethdevice); networkInterfacePath = networkInterfaceObject.first; } auto variant = ipmi::getDbusProperty( bus, ipmi::network::SERVICE, networkInterfacePath, ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled"); auto dhcpEnabled = variant.get(); // As per IPMI spec 2=>DHCP, 1=STATIC auto ipsrc = dhcpEnabled ? ipmi::network::IPOrigin::DHCP : ipmi::network::IPOrigin::STATIC; memcpy(data, &ipsrc, ipmi::network::IPSRC_SIZE_BYTE); } else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS) { memcpy(data, &(channelConf->ipsrc), ipmi::network::IPSRC_SIZE_BYTE); } } break; case LAN_PARM_SUBNET: { unsigned long mask {}; if (channelConf->lan_set_in_progress == SET_COMPLETE) { try { auto ipObjectInfo = ipmi::getIPObject( 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(); mask = ipmi::network::MASK_32_BIT; mask = htonl(mask << (ipmi::network::BITS_32 - prefix)); } // ignore the exception, as it is a valid condition that // the system is not configured with any IP. catch (InternalFailure& e) { // nothing to do } memcpy(data, &mask, ipmi::network::IPV4_ADDRESS_SIZE_BYTE); } else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS) { inet_pton(AF_INET, channelConf->netmask.c_str(), reinterpret_cast(data)); } } break; case LAN_PARM_GATEWAY: { std::string gateway; if (channelConf->lan_set_in_progress == SET_COMPLETE) { try { 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>(); } // ignore the exception, as it is a valid condition that // the system is not configured with any IP. catch (InternalFailure& e) { // nothing to do } } else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS) { gateway = channelConf->gateway; } inet_pton(AF_INET, gateway.c_str(), reinterpret_cast(data)); } break; case LAN_PARM_MAC: { std::string macAddress; if (channelConf->lan_set_in_progress == SET_COMPLETE) { auto macObjectInfo = ipmi::getDbusObject( bus, ipmi::network::MAC_INTERFACE, ipmi::network::ROOT, ethdevice); auto variant = ipmi::getDbusProperty( bus, macObjectInfo.second, macObjectInfo.first, ipmi::network::MAC_INTERFACE, "MACAddress"); macAddress = variant.get(); } else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS) { macAddress = channelConf->macAddress; } sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT, (data), (data + 1), (data + 2), (data + 3), (data + 4), (data + 5)); } break; case LAN_PARM_VLAN: { uint16_t vlanID {}; if (channelConf->lan_set_in_progress == SET_COMPLETE) { try { auto ipObjectInfo = ipmi::getIPObject( bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ipmi::network::IP_TYPE); vlanID = static_cast( ipmi::network::getVLAN(ipObjectInfo.first)); vlanID = htole16(vlanID); if (vlanID) { //Enable the 16th bit vlanID |= htole16(ipmi::network::VLAN_ENABLE_MASK); } } // ignore the exception, as it is a valid condition that // the system is not configured with any IP. catch (InternalFailure& e) { // nothing to do } memcpy(data, &vlanID, ipmi::network::VLAN_SIZE_BYTE); } else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS) { memcpy(data, &(channelConf->vlanID), ipmi::network::VLAN_SIZE_BYTE); } } break; default: rc = IPMI_CC_PARM_OUT_OF_RANGE; } } catch (InternalFailure& e) { commit(); rc = IPMI_CC_UNSPECIFIED_ERROR; return rc; } return rc; } namespace cipher { std::vector getCipherList() { std::vector cipherList; std::ifstream jsonFile(configFile); if (!jsonFile.is_open()) { log("Channel Cipher suites file not found"); elog(); } auto data = Json::parse(jsonFile, nullptr, false); if (data.is_discarded()) { log("Parsing channel cipher suites JSON failed"); elog(); } // Byte 1 is reserved cipherList.push_back(0x00); for (const auto& record : data) { cipherList.push_back(record.value(cipher, 0)); } return cipherList; } } //namespace cipher ipmi_ret_t ipmi_transport_wildcard(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) { // Status code. ipmi_ret_t rc = IPMI_CC_INVALID; *data_len = 0; return rc; } 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) { ipmi_ret_t rc = IPMI_CC_OK; *data_len = 0; using namespace std::chrono_literals; // time to wait before applying the network changes. constexpr auto networkTimeout = 10000000us; // 10 sec char ipaddr[INET_ADDRSTRLEN]; char netmask[INET_ADDRSTRLEN]; char gateway[INET_ADDRSTRLEN]; auto reqptr = reinterpret_cast(request); sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection()); // channel number is the lower nibble int channel = reqptr->channel & CHANNEL_MASK; auto ethdevice = ipmi::network::ChanneltoEthernet(channel); if (ethdevice.empty()) { return IPMI_CC_INVALID_FIELD_REQUEST; } auto channelConf = getChannelConfig(channel); 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]); channelConf->ipaddr.assign(ipaddr); } break; case LAN_PARM_IPSRC: { uint8_t ipsrc{}; memcpy(&ipsrc, reqptr->data, ipmi::network::IPSRC_SIZE_BYTE); channelConf->ipsrc = static_cast(ipsrc); } 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, ethdevice); ipmi::setDbusProperty(bus, macObjectInfo.second, macObjectInfo.first, ipmi::network::MAC_INTERFACE, "MACAddress", std::string(mac)); channelConf->macAddress = mac; } 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]); channelConf->netmask.assign(netmask); } break; 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]); channelConf->gateway.assign(gateway); } break; case LAN_PARM_VLAN: { uint16_t vlan {}; memcpy(&vlan, reqptr->data, ipmi::network::VLAN_SIZE_BYTE); // We are not storing the enable bit // We assume that ipmitool always send enable // bit as 1. vlan = le16toh(vlan); channelConf->vlanID = vlan; } break; case LAN_PARM_INPROGRESS: { if (reqptr->data[0] == SET_COMPLETE) { channelConf->lan_set_in_progress = SET_COMPLETE; log("Network data from Cache", entry("PREFIX=%s", channelConf->netmask.c_str()), entry("ADDRESS=%s", channelConf->ipaddr.c_str()), entry("GATEWAY=%s", channelConf->gateway.c_str()), entry("VLAN=%d", channelConf->vlanID)); if (!networkTimer) { log("Network timer is not instantiated"); return IPMI_CC_UNSPECIFIED_ERROR; } // start/restart the timer networkTimer->startTimer(networkTimeout); } else if (reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress { channelConf->lan_set_in_progress = SET_IN_PROGRESS; channelConf->flush = true; } } break; default: { rc = IPMI_CC_PARM_NOT_SUPPORTED; } } return rc; } 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) { ipmi_ret_t rc = IPMI_CC_OK; *data_len = 0; const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0 get_lan_t *reqptr = (get_lan_t*) request; // channel number is the lower nibble int channel = reqptr->rev_channel & CHANNEL_MASK; if (reqptr->rev_channel & 0x80) // Revision is bit 7 { // Only current revision was requested *data_len = sizeof(current_revision); memcpy(response, ¤t_revision, *data_len); return IPMI_CC_OK; } static std::vector cipherList; static auto listInit = false; if (!listInit) { try { cipherList = cipher::getCipherList(); listInit = true; } catch (const std::exception &e) { return IPMI_CC_UNSPECIFIED_ERROR; } } auto ethdevice = ipmi::network::ChanneltoEthernet(channel); if (ethdevice.empty()) { return IPMI_CC_INVALID_FIELD_REQUEST; } auto channelConf = getChannelConfig(channel); if (reqptr->parameter == LAN_PARM_INPROGRESS) { uint8_t buf[] = {current_revision, channelConf->lan_set_in_progress}; *data_len = sizeof(buf); memcpy(response, &buf, *data_len); } else if (reqptr->parameter == LAN_PARM_AUTHSUPPORT) { uint8_t buf[] = {current_revision,0x04}; *data_len = sizeof(buf); memcpy(response, &buf, *data_len); } else if (reqptr->parameter == LAN_PARM_AUTHENABLES) { uint8_t buf[] = {current_revision,0x04,0x04,0x04,0x04,0x04}; *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) || (reqptr->parameter == LAN_PARM_MAC)) { 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], channel) == IPMI_CC_OK) { 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 { rc = IPMI_CC_UNSPECIFIED_ERROR; } } else if (reqptr->parameter == LAN_PARM_VLAN) { uint8_t buf[ipmi::network::VLAN_SIZE_BYTE + 1] = {}; *data_len = sizeof(current_revision); memcpy(buf, ¤t_revision, *data_len); if (getNetworkData(reqptr->parameter, &buf[1], channel) == IPMI_CC_OK) { *data_len = sizeof(buf); memcpy(response, &buf, *data_len); } } else if (reqptr->parameter == LAN_PARM_IPSRC) { uint8_t buff[ipmi::network::IPSRC_SIZE_BYTE + 1] = {}; *data_len = sizeof(current_revision); memcpy(buff, ¤t_revision, *data_len); if (getNetworkData(reqptr->parameter, &buff[1], channel) == IPMI_CC_OK) { *data_len = sizeof(buff); memcpy(response, &buff, *data_len); } } else if (reqptr->parameter == CIPHER_SUITE_COUNT) { *(static_cast(response)) = current_revision; // Byte 1 is reserved byte and does not indicate a cipher suite ID, so // no of cipher suite entry count is one less than the size of the // vector auto count = static_cast(cipherList.size() - 1); *(static_cast(response) + 1) = count; *data_len = sizeof(current_revision) + sizeof(count); } else if (reqptr->parameter == CIPHER_SUITE_ENTRIES) { *(static_cast(response)) = current_revision; // Byte 1 is reserved std::copy_n(cipherList.data(), cipherList.size(), static_cast(response) + 1); *data_len = sizeof(current_revision) + static_cast(cipherList.size()); } else { log("Unsupported parameter", entry("PARAMETER=0x%x", reqptr->parameter)); rc = IPMI_CC_PARM_NOT_SUPPORTED; } return rc; } void applyChanges(int channel) { std::string ipaddress; std::string gateway; uint8_t prefix {}; uint32_t vlanID {}; std::string networkInterfacePath; ipmi::DbusObjectInfo ipObject; ipmi::DbusObjectInfo systemObject; auto ethdevice = ipmi::network::ChanneltoEthernet(channel); if (ethdevice.empty()) { log("Unable to get the interface name", entry("CHANNEL=%d", channel)); return; } auto ethIp = ethdevice + "/" + ipmi::network::IP_TYPE; auto channelConf = getChannelConfig(channel); try { sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection()); log("Network data from Cache", entry("PREFIX=%s", channelConf->netmask.c_str()), entry("ADDRESS=%s", channelConf->ipaddr.c_str()), entry("GATEWAY=%s", channelConf->gateway.c_str()), entry("VLAN=%d", channelConf->vlanID), entry("IPSRC=%d", channelConf->ipsrc)); if (channelConf->vlanID != ipmi::network::VLAN_ID_MASK) { //get the first twelve bits which is vlan id //not interested in rest of the bits. channelConf->vlanID = le32toh(channelConf->vlanID); vlanID = channelConf->vlanID & ipmi::network::VLAN_ID_MASK; } // if the asked ip src is DHCP then not interested in // any given data except vlan. if (channelConf->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::getIPObject(bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIp); // 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("Unable to get the parent interface", entry("PATH=%s", ipObject.first.c_str()), entry("INTERFACE=%s", ipmi::network::ETHERNET_INTERFACE)); commit(); channelConf->clear(); return; } 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, ethdevice); 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(); // if ip address source is not given then get the ip source mode // from the system so that it can be applied later. if (channelConf->ipsrc == ipmi::network::IPOrigin::UNSPECIFIED) { channelConf->ipsrc = (enableDHCP) ? ipmi::network::IPOrigin::DHCP : ipmi::network::IPOrigin::STATIC; } // 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 ((!channelConf->ipaddr.empty() && !channelConf->netmask.empty() && !channelConf->gateway.empty()) || (enableDHCP)) // configured system interface mode = DHCP { //convert mask into prefix ipaddress = channelConf->ipaddr; prefix = ipmi::network::toPrefix(AF_INET, channelConf->netmask); gateway = channelConf->gateway; } 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 = channelConf->ipaddr.empty() ? properties["Address"].get() : channelConf->ipaddr; prefix = channelConf->netmask.empty() ? properties["PrefixLength"].get() : ipmi::network::toPrefix(AF_INET, channelConf->netmask); } catch (InternalFailure& e) { log("Failed to get IP object which matches", entry("INTERFACE=%s", ipmi::network::IP_INTERFACE), entry("MATCH=%s", ethIp.c_str())); } auto systemProperties = ipmi::getAllDbusProperties( bus, systemObject.second, systemObject.first, ipmi::network::SYSTEMCONFIG_INTERFACE); gateway = channelConf->gateway.empty() ? systemProperties["DefaultGateway"].get() : channelConf->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, ethdevice); // 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, ethIp); if (vlanID) { ipmi::network::createVLAN(bus, ipmi::network::SERVICE, ipmi::network::ROOT, ethdevice, vlanID); auto networkInterfaceObject = ipmi::getDbusObject( bus, ipmi::network::VLAN_INTERFACE, ipmi::network::ROOT); networkInterfacePath = networkInterfaceObject.first; } if (channelConf->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("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", channelConf->ipsrc)); commit(); } channelConf->clear(); } void commitNetworkChanges() { for (const auto &channel : channelConfig) { if (channel.second->flush) { applyChanges(channel.first); } } } void createNetworkTimer() { if (!networkTimer) { std::function networkTimerCallback( std::bind(&commitNetworkChanges)); networkTimer = std::make_unique( ipmid_get_sd_event_connection(), networkTimerCallback); } } void register_netfn_transport_functions() { // As this timer is only for transport handler // so creating it here. createNetworkTimer(); // ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL, ipmi_transport_wildcard, PRIVILEGE_USER); // ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_LAN, NULL, ipmi_transport_set_lan, PRIVILEGE_ADMIN); // ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL, ipmi_transport_get_lan, PRIVILEGE_OPERATOR); return; }