170141561SBorawski.Lukasz /* 270141561SBorawski.Lukasz // Copyright (c) 2018 Intel Corporation 370141561SBorawski.Lukasz // 470141561SBorawski.Lukasz // Licensed under the Apache License, Version 2.0 (the "License"); 570141561SBorawski.Lukasz // you may not use this file except in compliance with the License. 670141561SBorawski.Lukasz // You may obtain a copy of the License at 770141561SBorawski.Lukasz // 870141561SBorawski.Lukasz // http://www.apache.org/licenses/LICENSE-2.0 970141561SBorawski.Lukasz // 1070141561SBorawski.Lukasz // Unless required by applicable law or agreed to in writing, software 1170141561SBorawski.Lukasz // distributed under the License is distributed on an "AS IS" BASIS, 1270141561SBorawski.Lukasz // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1370141561SBorawski.Lukasz // See the License for the specific language governing permissions and 1470141561SBorawski.Lukasz // limitations under the License. 1570141561SBorawski.Lukasz */ 1670141561SBorawski.Lukasz #pragma once 1770141561SBorawski.Lukasz 183ccb3adbSEd Tanous #include "app.hpp" 193ccb3adbSEd Tanous #include "dbus_utility.hpp" 203a8a0088SKowalski, Kamil #include "error_messages.hpp" 213ccb3adbSEd Tanous #include "query.hpp" 22b4bec66bSAbhishek Patel #include "redfish_util.hpp" 233ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 243ccb3adbSEd Tanous #include "utils/json_utils.hpp" 253ccb3adbSEd Tanous #include "utils/stl_utils.hpp" 2670141561SBorawski.Lukasz 27e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 28253f11b8SEd Tanous #include <boost/url/format.hpp> 291e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp> 301214b7e7SGunnar Mills 31e99073f5SGeorge Liu #include <array> 321214b7e7SGunnar Mills #include <optional> 33e99073f5SGeorge Liu #include <string_view> 34abf2add6SEd Tanous #include <variant> 355f4c798dSJiaqing Zhao 361abe55efSEd Tanous namespace redfish 371abe55efSEd Tanous { 3870141561SBorawski.Lukasz 397e860f15SJohn Edward Broadbent void getNTPProtocolEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp); 407e860f15SJohn Edward Broadbent std::string getHostName(); 417e860f15SJohn Edward Broadbent 425c3e9272SAbhishek Patel static constexpr std::string_view sshServiceName = "dropbear"; 435c3e9272SAbhishek Patel static constexpr std::string_view httpsServiceName = "bmcweb"; 445c3e9272SAbhishek Patel static constexpr std::string_view ipmiServiceName = "phosphor-ipmi-net"; 455c3e9272SAbhishek Patel 465c3e9272SAbhishek Patel // Mapping from Redfish NetworkProtocol key name to backend service that hosts 475c3e9272SAbhishek Patel // that protocol. 485c3e9272SAbhishek Patel static constexpr std::array<std::pair<std::string_view, std::string_view>, 3> 495c3e9272SAbhishek Patel networkProtocolToDbus = {{{"SSH", sshServiceName}, 5069320d54SJiaqing Zhao {"HTTPS", httpsServiceName}, 5169320d54SJiaqing Zhao {"IPMI", ipmiServiceName}}}; 523a8a0088SKowalski, Kamil 53711ac7a9SEd Tanous inline void extractNTPServersAndDomainNamesData( 54711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 55532d7697SGunnar Mills std::vector<std::string>& ntpData, std::vector<std::string>& dnData) 5620e6ea5dSraviteja-b { 5781ce609eSEd Tanous for (const auto& obj : dbusData) 5820e6ea5dSraviteja-b { 5920e6ea5dSraviteja-b for (const auto& ifacePair : obj.second) 6020e6ea5dSraviteja-b { 610a052baaSGeorge Liu if (ifacePair.first != 6220e6ea5dSraviteja-b "xyz.openbmc_project.Network.EthernetInterface") 6320e6ea5dSraviteja-b { 640a052baaSGeorge Liu continue; 650a052baaSGeorge Liu } 660a052baaSGeorge Liu 6720e6ea5dSraviteja-b for (const auto& propertyPair : ifacePair.second) 6820e6ea5dSraviteja-b { 69fcd2682aSEd Tanous if (propertyPair.first == "StaticNTPServers") 7020e6ea5dSraviteja-b { 7120e6ea5dSraviteja-b const std::vector<std::string>* ntpServers = 728d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 7320e6ea5dSraviteja-b &propertyPair.second); 7420e6ea5dSraviteja-b if (ntpServers != nullptr) 7520e6ea5dSraviteja-b { 76c251fe81SJian Zhang ntpData.insert(ntpData.end(), ntpServers->begin(), 77c251fe81SJian Zhang ntpServers->end()); 7820e6ea5dSraviteja-b } 7920e6ea5dSraviteja-b } 80d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 81d24bfc7aSJennifer Lee { 82d24bfc7aSJennifer Lee const std::vector<std::string>* domainNames = 838d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 84d24bfc7aSJennifer Lee &propertyPair.second); 85d24bfc7aSJennifer Lee if (domainNames != nullptr) 86d24bfc7aSJennifer Lee { 87c251fe81SJian Zhang dnData.insert(dnData.end(), domainNames->begin(), 88c251fe81SJian Zhang domainNames->end()); 89d24bfc7aSJennifer Lee } 90d24bfc7aSJennifer Lee } 9120e6ea5dSraviteja-b } 9220e6ea5dSraviteja-b } 9320e6ea5dSraviteja-b } 940225b87bSEd Tanous stl_utils::removeDuplicate(ntpData); 95c251fe81SJian Zhang stl_utils::removeDuplicate(dnData); 9620e6ea5dSraviteja-b } 9720e6ea5dSraviteja-b 9820e6ea5dSraviteja-b template <typename CallbackFunc> 9920e6ea5dSraviteja-b void getEthernetIfaceData(CallbackFunc&& callback) 10020e6ea5dSraviteja-b { 1015eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1025eb468daSGeorge Liu dbus::utility::getManagedObjects( 1035eb468daSGeorge Liu "xyz.openbmc_project.Network", path, 1048cb2c024SEd Tanous [callback = std::forward<CallbackFunc>(callback)]( 1058b24275dSEd Tanous const boost::system::error_code& ec, 106711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData) { 10720e6ea5dSraviteja-b std::vector<std::string> ntpServers; 108d24bfc7aSJennifer Lee std::vector<std::string> domainNames; 10920e6ea5dSraviteja-b 1108b24275dSEd Tanous if (ec) 11120e6ea5dSraviteja-b { 112532d7697SGunnar Mills callback(false, ntpServers, domainNames); 11320e6ea5dSraviteja-b return; 11420e6ea5dSraviteja-b } 11520e6ea5dSraviteja-b 116532d7697SGunnar Mills extractNTPServersAndDomainNamesData(dbusData, ntpServers, domainNames); 11720e6ea5dSraviteja-b 118532d7697SGunnar Mills callback(true, ntpServers, domainNames); 1195eb468daSGeorge Liu }); 120271584abSEd Tanous } 12120e6ea5dSraviteja-b 1225c3e9272SAbhishek Patel inline void afterNetworkPortRequest( 1235c3e9272SAbhishek Patel const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1245c3e9272SAbhishek Patel const boost::system::error_code& ec, 1255c3e9272SAbhishek Patel const std::vector<std::tuple<std::string, std::string, bool>>& socketData) 1265c3e9272SAbhishek Patel { 1275c3e9272SAbhishek Patel if (ec) 1285c3e9272SAbhishek Patel { 1295c3e9272SAbhishek Patel messages::internalError(asyncResp->res); 1305c3e9272SAbhishek Patel return; 1315c3e9272SAbhishek Patel } 1325c3e9272SAbhishek Patel for (const auto& data : socketData) 1335c3e9272SAbhishek Patel { 1345c3e9272SAbhishek Patel const std::string& socketPath = get<0>(data); 1355c3e9272SAbhishek Patel const std::string& protocolName = get<1>(data); 1365c3e9272SAbhishek Patel bool isProtocolEnabled = get<2>(data); 1375c3e9272SAbhishek Patel 1385c3e9272SAbhishek Patel asyncResp->res.jsonValue[protocolName]["ProtocolEnabled"] = 1395c3e9272SAbhishek Patel isProtocolEnabled; 1405c3e9272SAbhishek Patel asyncResp->res.jsonValue[protocolName]["Port"] = nullptr; 1415c3e9272SAbhishek Patel getPortNumber(socketPath, [asyncResp, protocolName]( 1425c3e9272SAbhishek Patel const boost::system::error_code& ec2, 1435c3e9272SAbhishek Patel int portNumber) { 1445c3e9272SAbhishek Patel if (ec2) 1455c3e9272SAbhishek Patel { 1465c3e9272SAbhishek Patel messages::internalError(asyncResp->res); 1475c3e9272SAbhishek Patel return; 1485c3e9272SAbhishek Patel } 1495c3e9272SAbhishek Patel asyncResp->res.jsonValue[protocolName]["Port"] = portNumber; 1505c3e9272SAbhishek Patel }); 1515c3e9272SAbhishek Patel } 1525c3e9272SAbhishek Patel } 1535c3e9272SAbhishek Patel 1544f48d5f6SEd Tanous inline void getNetworkData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 15572048780SAbhishek Patel const crow::Request& req) 1561abe55efSEd Tanous { 1573e72c202SNinad Palsule if (req.session == nullptr) 1583e72c202SNinad Palsule { 1593e72c202SNinad Palsule messages::internalError(asyncResp->res); 1603e72c202SNinad Palsule return; 1613e72c202SNinad Palsule } 1623e72c202SNinad Palsule 163e9f71672SEd Tanous asyncResp->res.addHeader( 164e9f71672SEd Tanous boost::beast::http::field::link, 165e9f71672SEd Tanous "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/NetworkProtocol.json>; rel=describedby"); 1660f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 167532d7697SGunnar Mills "#ManagerNetworkProtocol.v1_5_0.ManagerNetworkProtocol"; 1680f74e643SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 169253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/NetworkProtocol", 170253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 1710f74e643SEd Tanous asyncResp->res.jsonValue["Id"] = "NetworkProtocol"; 1720f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Network Protocol"; 1730f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = "Manager Network Service"; 1740f74e643SEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = "OK"; 1750f74e643SEd Tanous asyncResp->res.jsonValue["Status"]["HealthRollup"] = "OK"; 1760f74e643SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 1770f74e643SEd Tanous 17861932318SXiaochao Ma // HTTP is Mandatory attribute as per OCP Baseline Profile - v1.0.0, 179818ea7b8SJoshi-Mansi // but from security perspective it is not recommended to use. 180818ea7b8SJoshi-Mansi // Hence using protocolEnabled as false to make it OCP and security-wise 181818ea7b8SJoshi-Mansi // compliant 1825c3e9272SAbhishek Patel asyncResp->res.jsonValue["HTTP"]["Port"] = nullptr; 183818ea7b8SJoshi-Mansi asyncResp->res.jsonValue["HTTP"]["ProtocolEnabled"] = false; 184818ea7b8SJoshi-Mansi 1851ee2db7fSAndrew Geissler // The ProtocolEnabled of the following protocols is determined by 1861ee2db7fSAndrew Geissler // inspecting the state of associated systemd sockets. If these protocols 1871ee2db7fSAndrew Geissler // have been disabled, then the systemd socket unit files will not be found 1881ee2db7fSAndrew Geissler // and the protocols will not be returned in this Redfish query. Set some 1891ee2db7fSAndrew Geissler // defaults to ensure something is always returned. 1901ee2db7fSAndrew Geissler for (const auto& nwkProtocol : networkProtocolToDbus) 1911ee2db7fSAndrew Geissler { 1921ee2db7fSAndrew Geissler asyncResp->res.jsonValue[nwkProtocol.first]["Port"] = nullptr; 1931ee2db7fSAndrew Geissler asyncResp->res.jsonValue[nwkProtocol.first]["ProtocolEnabled"] = false; 1941ee2db7fSAndrew Geissler } 1951ee2db7fSAndrew Geissler 196d24bfc7aSJennifer Lee std::string hostName = getHostName(); 197d24bfc7aSJennifer Lee 198d24bfc7aSJennifer Lee asyncResp->res.jsonValue["HostName"] = hostName; 1993a8a0088SKowalski, Kamil 20020e6ea5dSraviteja-b getNTPProtocolEnabled(asyncResp); 20120e6ea5dSraviteja-b 202002d39b4SEd Tanous getEthernetIfaceData( 203002d39b4SEd Tanous [hostName, asyncResp](const bool& success, 20402cad96eSEd Tanous const std::vector<std::string>& ntpServers, 205d24bfc7aSJennifer Lee const std::vector<std::string>& domainNames) { 20620e6ea5dSraviteja-b if (!success) 20720e6ea5dSraviteja-b { 2080a052baaSGeorge Liu messages::resourceNotFound(asyncResp->res, "ManagerNetworkProtocol", 2090a052baaSGeorge Liu "NetworkProtocol"); 21020e6ea5dSraviteja-b return; 21120e6ea5dSraviteja-b } 21220e6ea5dSraviteja-b asyncResp->res.jsonValue["NTP"]["NTPServers"] = ntpServers; 21326f6976fSEd Tanous if (!hostName.empty()) 214d24bfc7aSJennifer Lee { 215f23b7296SEd Tanous std::string fqdn = hostName; 21626f6976fSEd Tanous if (!domainNames.empty()) 217d24bfc7aSJennifer Lee { 218f23b7296SEd Tanous fqdn += "."; 219f23b7296SEd Tanous fqdn += domainNames[0]; 220d24bfc7aSJennifer Lee } 2212c70f800SEd Tanous asyncResp->res.jsonValue["FQDN"] = std::move(fqdn); 222d24bfc7aSJennifer Lee } 22320e6ea5dSraviteja-b }); 22420e6ea5dSraviteja-b 22572048780SAbhishek Patel Privileges effectiveUserPrivileges = 2263e72c202SNinad Palsule redfish::getUserPrivileges(*req.session); 22772048780SAbhishek Patel 22872048780SAbhishek Patel // /redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates is 22972048780SAbhishek Patel // something only ConfigureManager can access then only display when 23072048780SAbhishek Patel // the user has permissions ConfigureManager 23172048780SAbhishek Patel if (isOperationAllowedWithPrivileges({{"ConfigureManager"}}, 23272048780SAbhishek Patel effectiveUserPrivileges)) 23372048780SAbhishek Patel { 2341476687dSEd Tanous asyncResp->res.jsonValue["HTTPS"]["Certificates"]["@odata.id"] = 235253f11b8SEd Tanous boost::urls::format( 236253f11b8SEd Tanous "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates", 237253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 23870141561SBorawski.Lukasz } 23970141561SBorawski.Lukasz 2405c3e9272SAbhishek Patel getPortStatusAndPath(std::span(networkProtocolToDbus), 2415c3e9272SAbhishek Patel std::bind_front(afterNetworkPortRequest, asyncResp)); 242b4bec66bSAbhishek Patel } // namespace redfish 243501be32bSraviteja-b 2448e157735SEd Tanous inline void afterSetNTP(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2458e157735SEd Tanous const boost::system::error_code& ec) 24620e6ea5dSraviteja-b { 2478e157735SEd Tanous if (ec) 24820e6ea5dSraviteja-b { 2498e157735SEd Tanous BMCWEB_LOG_DEBUG("Failed to set elapsed time. DBUS response error {}", 2508e157735SEd Tanous ec); 2518e157735SEd Tanous messages::internalError(asyncResp->res); 2528e157735SEd Tanous return; 25320e6ea5dSraviteja-b } 2548e157735SEd Tanous asyncResp->res.result(boost::beast::http::status::no_content); 25520e6ea5dSraviteja-b } 25620e6ea5dSraviteja-b 2578e157735SEd Tanous inline void handleNTPProtocolEnabled( 2588e157735SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool ntpEnabled) 2598e157735SEd Tanous { 2608e157735SEd Tanous bool interactive = false; 2618e157735SEd Tanous auto callback = [asyncResp](const boost::system::error_code& ec) { 2628e157735SEd Tanous afterSetNTP(asyncResp, ec); 2638e157735SEd Tanous }; 2648e157735SEd Tanous crow::connections::systemBus->async_method_call( 2658e157735SEd Tanous std::move(callback), "org.freedesktop.timedate1", 2668e157735SEd Tanous "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "SetNTP", 2678e157735SEd Tanous ntpEnabled, interactive); 26820e6ea5dSraviteja-b } 26920e6ea5dSraviteja-b 270ed4de7a8SEd Tanous // Redfish states that ip addresses can be 271ed4de7a8SEd Tanous // string, to set a value 272ed4de7a8SEd Tanous // null, to delete the value 273ed4de7a8SEd Tanous // object_t, empty json object, to ignore the value 274ed4de7a8SEd Tanous using IpAddress = 275ed4de7a8SEd Tanous std::variant<std::string, nlohmann::json::object_t, std::nullptr_t>; 276ed4de7a8SEd Tanous 2774f48d5f6SEd Tanous inline void 278287ece64SGeorge Liu handleNTPServersPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 279ed4de7a8SEd Tanous const std::vector<IpAddress>& ntpServerObjects, 280b9e15228SEd Tanous std::vector<std::string> currentNtpServers) 28120e6ea5dSraviteja-b { 282b9e15228SEd Tanous std::vector<std::string>::iterator currentNtpServer = 283b9e15228SEd Tanous currentNtpServers.begin(); 284b9e15228SEd Tanous for (size_t index = 0; index < ntpServerObjects.size(); index++) 285287ece64SGeorge Liu { 286ed4de7a8SEd Tanous const IpAddress& ntpServer = ntpServerObjects[index]; 287ed4de7a8SEd Tanous if (std::holds_alternative<std::nullptr_t>(ntpServer)) 288b9e15228SEd Tanous { 289b9e15228SEd Tanous // Can't delete an item that doesn't exist 290b9e15228SEd Tanous if (currentNtpServer == currentNtpServers.end()) 291b9e15228SEd Tanous { 292b9e15228SEd Tanous messages::propertyValueNotInList(asyncResp->res, "null", 293b9e15228SEd Tanous "NTP/NTPServers/" + 294b9e15228SEd Tanous std::to_string(index)); 295b9e15228SEd Tanous 296287ece64SGeorge Liu return; 297287ece64SGeorge Liu } 298b9e15228SEd Tanous currentNtpServer = currentNtpServers.erase(currentNtpServer); 299b9e15228SEd Tanous continue; 300b9e15228SEd Tanous } 301b9e15228SEd Tanous const nlohmann::json::object_t* ntpServerObject = 302ed4de7a8SEd Tanous std::get_if<nlohmann::json::object_t>(&ntpServer); 303b9e15228SEd Tanous if (ntpServerObject != nullptr) 304b9e15228SEd Tanous { 305b9e15228SEd Tanous if (!ntpServerObject->empty()) 306b9e15228SEd Tanous { 307ed4de7a8SEd Tanous messages::propertyValueNotInList( 308ed4de7a8SEd Tanous asyncResp->res, *ntpServerObject, 309ed4de7a8SEd Tanous "NTP/NTPServers/" + std::to_string(index)); 310b9e15228SEd Tanous return; 311b9e15228SEd Tanous } 312b9e15228SEd Tanous // Can't retain an item that doesn't exist 313b9e15228SEd Tanous if (currentNtpServer == currentNtpServers.end()) 314b9e15228SEd Tanous { 315ed4de7a8SEd Tanous messages::propertyValueOutOfRange( 316ed4de7a8SEd Tanous asyncResp->res, *ntpServerObject, 317ed4de7a8SEd Tanous "NTP/NTPServers/" + std::to_string(index)); 318b9e15228SEd Tanous 319b9e15228SEd Tanous return; 320b9e15228SEd Tanous } 321b9e15228SEd Tanous // empty objects should leave the NtpServer unmodified 322b9e15228SEd Tanous currentNtpServer++; 323b9e15228SEd Tanous continue; 324b9e15228SEd Tanous } 325b9e15228SEd Tanous 326ed4de7a8SEd Tanous const std::string* ntpServerStr = std::get_if<std::string>(&ntpServer); 327b9e15228SEd Tanous if (ntpServerStr == nullptr) 328b9e15228SEd Tanous { 329ed4de7a8SEd Tanous messages::internalError(asyncResp->res); 330b9e15228SEd Tanous return; 331b9e15228SEd Tanous } 332b9e15228SEd Tanous if (currentNtpServer == currentNtpServers.end()) 333b9e15228SEd Tanous { 334b9e15228SEd Tanous // if we're at the end of the list, append to the end 335b9e15228SEd Tanous currentNtpServers.push_back(*ntpServerStr); 336b9e15228SEd Tanous currentNtpServer = currentNtpServers.end(); 337b9e15228SEd Tanous continue; 338b9e15228SEd Tanous } 339b9e15228SEd Tanous *currentNtpServer = *ntpServerStr; 340b9e15228SEd Tanous currentNtpServer++; 341b9e15228SEd Tanous } 342b9e15228SEd Tanous 343b9e15228SEd Tanous // Any remaining array elements should be removed 344b9e15228SEd Tanous currentNtpServers.erase(currentNtpServer, currentNtpServers.end()); 345287ece64SGeorge Liu 346e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> ethInterfaces = { 347e99073f5SGeorge Liu "xyz.openbmc_project.Network.EthernetInterface"}; 348e99073f5SGeorge Liu dbus::utility::getSubTree( 349e99073f5SGeorge Liu "/xyz/openbmc_project", 0, ethInterfaces, 350b9e15228SEd Tanous [asyncResp, currentNtpServers]( 3512138483cSGeorge Liu const boost::system::error_code& ec, 352b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 3530a052baaSGeorge Liu if (ec) 3540a052baaSGeorge Liu { 35562598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 3560a052baaSGeorge Liu messages::internalError(asyncResp->res); 3570a052baaSGeorge Liu return; 3580a052baaSGeorge Liu } 3590a052baaSGeorge Liu 3600a052baaSGeorge Liu for (const auto& [objectPath, serviceMap] : subtree) 3610a052baaSGeorge Liu { 3620a052baaSGeorge Liu for (const auto& [service, interfaces] : serviceMap) 3630a052baaSGeorge Liu { 3640a052baaSGeorge Liu for (const auto& interface : interfaces) 3650a052baaSGeorge Liu { 3660a052baaSGeorge Liu if (interface != 3670a052baaSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface") 3680a052baaSGeorge Liu { 3690a052baaSGeorge Liu continue; 3700a052baaSGeorge Liu } 3710a052baaSGeorge Liu 372*e93abac6SGinu George setDbusProperty(asyncResp, "NTP/NTPServers/", service, 373*e93abac6SGinu George objectPath, interface, "StaticNTPServers", 37487c44966SAsmitha Karunanithi currentNtpServers); 37520e6ea5dSraviteja-b } 3760a052baaSGeorge Liu } 3770a052baaSGeorge Liu } 378e99073f5SGeorge Liu }); 3790a052baaSGeorge Liu } 38020e6ea5dSraviteja-b 3814f48d5f6SEd Tanous inline void 3824f48d5f6SEd Tanous handleProtocolEnabled(const bool protocolEnabled, 383e5a99777SAlbert Zhang const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 38469320d54SJiaqing Zhao const std::string& netBasePath) 38567a78d87STom Joseph { 386e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 387e99073f5SGeorge Liu "xyz.openbmc_project.Control.Service.Attributes"}; 388e99073f5SGeorge Liu dbus::utility::getSubTree( 389e99073f5SGeorge Liu "/xyz/openbmc_project/control/service", 0, interfaces, 390e5a99777SAlbert Zhang [protocolEnabled, asyncResp, 3912138483cSGeorge Liu netBasePath](const boost::system::error_code& ec, 392b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 39367a78d87STom Joseph if (ec) 39467a78d87STom Joseph { 39567a78d87STom Joseph messages::internalError(asyncResp->res); 39667a78d87STom Joseph return; 39767a78d87STom Joseph } 39867a78d87STom Joseph 39967a78d87STom Joseph for (const auto& entry : subtree) 40067a78d87STom Joseph { 40118f8f608SEd Tanous if (entry.first.starts_with(netBasePath)) 40267a78d87STom Joseph { 40387c44966SAsmitha Karunanithi setDbusProperty( 404*e93abac6SGinu George asyncResp, "IPMI/ProtocolEnabled", 405*e93abac6SGinu George entry.second.begin()->first, entry.first, 406002d39b4SEd Tanous "xyz.openbmc_project.Control.Service.Attributes", "Running", 407*e93abac6SGinu George protocolEnabled); 40887c44966SAsmitha Karunanithi setDbusProperty( 409*e93abac6SGinu George asyncResp, "IPMI/ProtocolEnabled", 410*e93abac6SGinu George entry.second.begin()->first, entry.first, 411002d39b4SEd Tanous "xyz.openbmc_project.Control.Service.Attributes", "Enabled", 412*e93abac6SGinu George protocolEnabled); 41367a78d87STom Joseph } 41467a78d87STom Joseph } 415e99073f5SGeorge Liu }); 41667a78d87STom Joseph } 41767a78d87STom Joseph 4184f48d5f6SEd Tanous inline std::string getHostName() 419501be32bSraviteja-b { 4207e860f15SJohn Edward Broadbent std::string hostName; 4218d1b46d7Szhanghch05 422d3a9e084SEd Tanous std::array<char, HOST_NAME_MAX> hostNameCStr{}; 4237e860f15SJohn Edward Broadbent if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0) 4247e860f15SJohn Edward Broadbent { 4257e860f15SJohn Edward Broadbent hostName = hostNameCStr.data(); 4267e860f15SJohn Edward Broadbent } 4277e860f15SJohn Edward Broadbent return hostName; 4287e860f15SJohn Edward Broadbent } 4297e860f15SJohn Edward Broadbent 4304f48d5f6SEd Tanous inline void 4314f48d5f6SEd Tanous getNTPProtocolEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 4327e860f15SJohn Edward Broadbent { 4338e157735SEd Tanous sdbusplus::asio::getProperty<bool>( 4348e157735SEd Tanous *crow::connections::systemBus, "org.freedesktop.timedate1", 4358e157735SEd Tanous "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", 4368e157735SEd Tanous [asyncResp](const boost::system::error_code& ec, bool enabled) { 4378b24275dSEd Tanous if (ec) 4387e860f15SJohn Edward Broadbent { 4398e157735SEd Tanous BMCWEB_LOG_WARNING( 4408e157735SEd Tanous "Failed to get NTP status, assuming not supported"); 4417e860f15SJohn Edward Broadbent return; 4427e860f15SJohn Edward Broadbent } 4437e860f15SJohn Edward Broadbent 4448e157735SEd Tanous asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = enabled; 4451e1e598dSJonathan Doman }); 4467e860f15SJohn Edward Broadbent } 4477e860f15SJohn Edward Broadbent 4485c3e9272SAbhishek Patel inline std::string encodeServiceObjectPath(std::string_view serviceName) 44969320d54SJiaqing Zhao { 45069320d54SJiaqing Zhao sdbusplus::message::object_path objPath( 45169320d54SJiaqing Zhao "/xyz/openbmc_project/control/service"); 45269320d54SJiaqing Zhao objPath /= serviceName; 45369320d54SJiaqing Zhao return objPath.str; 45469320d54SJiaqing Zhao } 45569320d54SJiaqing Zhao 4560f55d946SEd Tanous inline void handleBmcNetworkProtocolHead( 457e9f71672SEd Tanous crow::App& app, const crow::Request& req, 458e9f71672SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 459e9f71672SEd Tanous { 460e9f71672SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 461e9f71672SEd Tanous { 462e9f71672SEd Tanous return; 463e9f71672SEd Tanous } 464e9f71672SEd Tanous asyncResp->res.addHeader( 465e9f71672SEd Tanous boost::beast::http::field::link, 466e9f71672SEd Tanous "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/ManagerNetworkProtocol.json>; rel=describedby"); 467e9f71672SEd Tanous } 468e9f71672SEd Tanous 469e634b34cSEd Tanous inline void handleManagersNetworkProtocolPatch( 470e634b34cSEd Tanous App& app, const crow::Request& req, 471253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 472253f11b8SEd Tanous const std::string& managerId) 4737e860f15SJohn Edward Broadbent { 4743ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 47545ca1b86SEd Tanous { 47645ca1b86SEd Tanous return; 47745ca1b86SEd Tanous } 478253f11b8SEd Tanous 479253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 480253f11b8SEd Tanous { 481253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 482253f11b8SEd Tanous return; 483253f11b8SEd Tanous } 484253f11b8SEd Tanous 485501be32bSraviteja-b std::optional<std::string> newHostName; 486ed4de7a8SEd Tanous 487ed4de7a8SEd Tanous std::optional<std::vector<IpAddress>> ntpServerObjects; 4885f4c798dSJiaqing Zhao std::optional<bool> ntpEnabled; 4895f4c798dSJiaqing Zhao std::optional<bool> ipmiEnabled; 4905f4c798dSJiaqing Zhao std::optional<bool> sshEnabled; 491501be32bSraviteja-b 4925f4c798dSJiaqing Zhao // clang-format off 4935f4c798dSJiaqing Zhao if (!json_util::readJsonPatch( 4945f4c798dSJiaqing Zhao req, asyncResp->res, 4955f4c798dSJiaqing Zhao "HostName", newHostName, 496b9e15228SEd Tanous "NTP/NTPServers", ntpServerObjects, 4975f4c798dSJiaqing Zhao "NTP/ProtocolEnabled", ntpEnabled, 4985f4c798dSJiaqing Zhao "IPMI/ProtocolEnabled", ipmiEnabled, 4995f4c798dSJiaqing Zhao "SSH/ProtocolEnabled", sshEnabled)) 500501be32bSraviteja-b { 501501be32bSraviteja-b return; 502501be32bSraviteja-b } 5035f4c798dSJiaqing Zhao // clang-format on 504cf05f9dcSJohnathan Mantey 5058d1b46d7Szhanghch05 asyncResp->res.result(boost::beast::http::status::no_content); 506501be32bSraviteja-b if (newHostName) 507501be32bSraviteja-b { 5082db77d34SJohnathan Mantey messages::propertyNotWritable(asyncResp->res, "HostName"); 50944fad2aaSEd Tanous return; 510cf05f9dcSJohnathan Mantey } 511cf05f9dcSJohnathan Mantey 51220e6ea5dSraviteja-b if (ntpEnabled) 51320e6ea5dSraviteja-b { 5148e157735SEd Tanous handleNTPProtocolEnabled(asyncResp, *ntpEnabled); 51520e6ea5dSraviteja-b } 516b9e15228SEd Tanous if (ntpServerObjects) 51720e6ea5dSraviteja-b { 518b9e15228SEd Tanous getEthernetIfaceData( 519b9e15228SEd Tanous [asyncResp, ntpServerObjects]( 520e634b34cSEd Tanous const bool success, std::vector<std::string>& currentNtpServers, 521b9e15228SEd Tanous const std::vector<std::string>& /*domainNames*/) { 522b9e15228SEd Tanous if (!success) 523b9e15228SEd Tanous { 524b9e15228SEd Tanous messages::internalError(asyncResp->res); 525b9e15228SEd Tanous return; 526b9e15228SEd Tanous } 527b9e15228SEd Tanous handleNTPServersPatch(asyncResp, *ntpServerObjects, 528b9e15228SEd Tanous std::move(currentNtpServers)); 529b9e15228SEd Tanous }); 53020e6ea5dSraviteja-b } 53167a78d87STom Joseph 5325f4c798dSJiaqing Zhao if (ipmiEnabled) 53367a78d87STom Joseph { 534e5a99777SAlbert Zhang handleProtocolEnabled( 5355f4c798dSJiaqing Zhao *ipmiEnabled, asyncResp, 53669320d54SJiaqing Zhao encodeServiceObjectPath(std::string(ipmiServiceName) + '@')); 537e5a99777SAlbert Zhang } 538e5a99777SAlbert Zhang 5395f4c798dSJiaqing Zhao if (sshEnabled) 540e5a99777SAlbert Zhang { 54169320d54SJiaqing Zhao handleProtocolEnabled(*sshEnabled, asyncResp, 54269320d54SJiaqing Zhao encodeServiceObjectPath(sshServiceName)); 54367a78d87STom Joseph } 544e634b34cSEd Tanous } 545e634b34cSEd Tanous 546af20dd1cSEd Tanous inline void handleManagersNetworkProtocolHead( 547e634b34cSEd Tanous App& app, const crow::Request& req, 548253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 549253f11b8SEd Tanous const std::string& managerId) 550e634b34cSEd Tanous { 551e634b34cSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 552e634b34cSEd Tanous { 553e634b34cSEd Tanous return; 554e634b34cSEd Tanous } 555af20dd1cSEd Tanous asyncResp->res.addHeader( 556af20dd1cSEd Tanous boost::beast::http::field::link, 557af20dd1cSEd Tanous "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/ManagerNetworkProtocol.json>; rel=describedby"); 558253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 559253f11b8SEd Tanous { 560253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 561253f11b8SEd Tanous return; 562253f11b8SEd Tanous } 563af20dd1cSEd Tanous } 564af20dd1cSEd Tanous 565af20dd1cSEd Tanous inline void handleManagersNetworkProtocolGet( 566af20dd1cSEd Tanous App& app, const crow::Request& req, 567253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 568253f11b8SEd Tanous const std::string& managerId) 569af20dd1cSEd Tanous { 570253f11b8SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 571253f11b8SEd Tanous { 572253f11b8SEd Tanous return; 573253f11b8SEd Tanous } 574253f11b8SEd Tanous asyncResp->res.addHeader( 575253f11b8SEd Tanous boost::beast::http::field::link, 576253f11b8SEd Tanous "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/ManagerNetworkProtocol.json>; rel=describedby"); 577253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 578253f11b8SEd Tanous { 579253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 580253f11b8SEd Tanous return; 581253f11b8SEd Tanous } 582253f11b8SEd Tanous 583e634b34cSEd Tanous getNetworkData(asyncResp, req); 584e634b34cSEd Tanous } 585e634b34cSEd Tanous 586e634b34cSEd Tanous inline void requestRoutesNetworkProtocol(App& app) 587e634b34cSEd Tanous { 588253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/NetworkProtocol/") 589e634b34cSEd Tanous .privileges(redfish::privileges::patchManagerNetworkProtocol) 590e634b34cSEd Tanous .methods(boost::beast::http::verb::patch)( 591e634b34cSEd Tanous std::bind_front(handleManagersNetworkProtocolPatch, std::ref(app))); 5927e860f15SJohn Edward Broadbent 593253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/NetworkProtocol/") 594e9f71672SEd Tanous .privileges(redfish::privileges::headManagerNetworkProtocol) 595e9f71672SEd Tanous .methods(boost::beast::http::verb::head)( 596af20dd1cSEd Tanous std::bind_front(handleManagersNetworkProtocolHead, std::ref(app))); 597e9f71672SEd Tanous 598253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/NetworkProtocol/") 599ed398213SEd Tanous .privileges(redfish::privileges::getManagerNetworkProtocol) 6007e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 601e634b34cSEd Tanous std::bind_front(handleManagersNetworkProtocolGet, std::ref(app))); 602cf05f9dcSJohnathan Mantey } 60370141561SBorawski.Lukasz 60470141561SBorawski.Lukasz } // namespace redfish 605