1*40e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 2*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation 470141561SBorawski.Lukasz #pragma once 570141561SBorawski.Lukasz 63ccb3adbSEd Tanous #include "app.hpp" 73ccb3adbSEd Tanous #include "dbus_utility.hpp" 83a8a0088SKowalski, Kamil #include "error_messages.hpp" 9539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 103ccb3adbSEd Tanous #include "query.hpp" 11b4bec66bSAbhishek Patel #include "redfish_util.hpp" 123ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 133ccb3adbSEd Tanous #include "utils/json_utils.hpp" 143ccb3adbSEd Tanous #include "utils/stl_utils.hpp" 1570141561SBorawski.Lukasz 16e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 17253f11b8SEd Tanous #include <boost/url/format.hpp> 181e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp> 191214b7e7SGunnar Mills 20e99073f5SGeorge Liu #include <array> 211214b7e7SGunnar Mills #include <optional> 22e99073f5SGeorge Liu #include <string_view> 23abf2add6SEd Tanous #include <variant> 240eebcefbSJishnu CM #include <vector> 255f4c798dSJiaqing Zhao 261abe55efSEd Tanous namespace redfish 271abe55efSEd Tanous { 2870141561SBorawski.Lukasz 297e860f15SJohn Edward Broadbent void getNTPProtocolEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp); 307e860f15SJohn Edward Broadbent std::string getHostName(); 317e860f15SJohn Edward Broadbent 325c3e9272SAbhishek Patel static constexpr std::string_view sshServiceName = "dropbear"; 335c3e9272SAbhishek Patel static constexpr std::string_view httpsServiceName = "bmcweb"; 345c3e9272SAbhishek Patel static constexpr std::string_view ipmiServiceName = "phosphor-ipmi-net"; 355c3e9272SAbhishek Patel 365c3e9272SAbhishek Patel // Mapping from Redfish NetworkProtocol key name to backend service that hosts 375c3e9272SAbhishek Patel // that protocol. 385c3e9272SAbhishek Patel static constexpr std::array<std::pair<std::string_view, std::string_view>, 3> 395c3e9272SAbhishek Patel networkProtocolToDbus = {{{"SSH", sshServiceName}, 4069320d54SJiaqing Zhao {"HTTPS", httpsServiceName}, 4169320d54SJiaqing Zhao {"IPMI", ipmiServiceName}}}; 423a8a0088SKowalski, Kamil 43711ac7a9SEd Tanous inline void extractNTPServersAndDomainNamesData( 44711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 450eebcefbSJishnu CM std::vector<std::string>& ntpData, std::vector<std::string>& dynamicNtpData, 460eebcefbSJishnu CM std::vector<std::string>& dnData) 4720e6ea5dSraviteja-b { 4881ce609eSEd Tanous for (const auto& obj : dbusData) 4920e6ea5dSraviteja-b { 5020e6ea5dSraviteja-b for (const auto& ifacePair : obj.second) 5120e6ea5dSraviteja-b { 520a052baaSGeorge Liu if (ifacePair.first != 5320e6ea5dSraviteja-b "xyz.openbmc_project.Network.EthernetInterface") 5420e6ea5dSraviteja-b { 550a052baaSGeorge Liu continue; 560a052baaSGeorge Liu } 570a052baaSGeorge Liu 5820e6ea5dSraviteja-b for (const auto& propertyPair : ifacePair.second) 5920e6ea5dSraviteja-b { 60fcd2682aSEd Tanous if (propertyPair.first == "StaticNTPServers") 6120e6ea5dSraviteja-b { 6220e6ea5dSraviteja-b const std::vector<std::string>* ntpServers = 638d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 6420e6ea5dSraviteja-b &propertyPair.second); 6520e6ea5dSraviteja-b if (ntpServers != nullptr) 6620e6ea5dSraviteja-b { 67c251fe81SJian Zhang ntpData.insert(ntpData.end(), ntpServers->begin(), 68c251fe81SJian Zhang ntpServers->end()); 6920e6ea5dSraviteja-b } 7020e6ea5dSraviteja-b } 710eebcefbSJishnu CM else if (propertyPair.first == "NTPServers") 720eebcefbSJishnu CM { 730eebcefbSJishnu CM const std::vector<std::string>* dynamicNtpServers = 740eebcefbSJishnu CM std::get_if<std::vector<std::string>>( 750eebcefbSJishnu CM &propertyPair.second); 760eebcefbSJishnu CM if (dynamicNtpServers != nullptr) 770eebcefbSJishnu CM { 780eebcefbSJishnu CM dynamicNtpData = *dynamicNtpServers; 790eebcefbSJishnu CM } 800eebcefbSJishnu CM } 81d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 82d24bfc7aSJennifer Lee { 83d24bfc7aSJennifer Lee const std::vector<std::string>* domainNames = 848d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 85d24bfc7aSJennifer Lee &propertyPair.second); 86d24bfc7aSJennifer Lee if (domainNames != nullptr) 87d24bfc7aSJennifer Lee { 88c251fe81SJian Zhang dnData.insert(dnData.end(), domainNames->begin(), 89c251fe81SJian Zhang domainNames->end()); 90d24bfc7aSJennifer Lee } 91d24bfc7aSJennifer Lee } 9220e6ea5dSraviteja-b } 9320e6ea5dSraviteja-b } 9420e6ea5dSraviteja-b } 950225b87bSEd Tanous stl_utils::removeDuplicate(ntpData); 96c251fe81SJian Zhang stl_utils::removeDuplicate(dnData); 9720e6ea5dSraviteja-b } 9820e6ea5dSraviteja-b 9920e6ea5dSraviteja-b template <typename CallbackFunc> 10020e6ea5dSraviteja-b void getEthernetIfaceData(CallbackFunc&& callback) 10120e6ea5dSraviteja-b { 1025eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1035eb468daSGeorge Liu dbus::utility::getManagedObjects( 1045eb468daSGeorge Liu "xyz.openbmc_project.Network", path, 1058cb2c024SEd Tanous [callback = std::forward<CallbackFunc>(callback)]( 1068b24275dSEd Tanous const boost::system::error_code& ec, 107711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData) { 10820e6ea5dSraviteja-b std::vector<std::string> ntpServers; 1090eebcefbSJishnu CM std::vector<std::string> dynamicNtpServers; 110d24bfc7aSJennifer Lee std::vector<std::string> domainNames; 11120e6ea5dSraviteja-b 1128b24275dSEd Tanous if (ec) 11320e6ea5dSraviteja-b { 1140eebcefbSJishnu CM callback(false, ntpServers, dynamicNtpServers, domainNames); 11520e6ea5dSraviteja-b return; 11620e6ea5dSraviteja-b } 11720e6ea5dSraviteja-b 118bd79bce8SPatrick Williams extractNTPServersAndDomainNamesData(dbusData, ntpServers, 1190eebcefbSJishnu CM dynamicNtpServers, domainNames); 12020e6ea5dSraviteja-b 1210eebcefbSJishnu CM callback(true, ntpServers, dynamicNtpServers, domainNames); 1225eb468daSGeorge Liu }); 123271584abSEd Tanous } 12420e6ea5dSraviteja-b 1255c3e9272SAbhishek Patel inline void afterNetworkPortRequest( 1265c3e9272SAbhishek Patel const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1275c3e9272SAbhishek Patel const boost::system::error_code& ec, 1285c3e9272SAbhishek Patel const std::vector<std::tuple<std::string, std::string, bool>>& socketData) 1295c3e9272SAbhishek Patel { 1305c3e9272SAbhishek Patel if (ec) 1315c3e9272SAbhishek Patel { 1325c3e9272SAbhishek Patel messages::internalError(asyncResp->res); 1335c3e9272SAbhishek Patel return; 1345c3e9272SAbhishek Patel } 1355c3e9272SAbhishek Patel for (const auto& data : socketData) 1365c3e9272SAbhishek Patel { 1375c3e9272SAbhishek Patel const std::string& socketPath = get<0>(data); 1385c3e9272SAbhishek Patel const std::string& protocolName = get<1>(data); 1395c3e9272SAbhishek Patel bool isProtocolEnabled = get<2>(data); 1405c3e9272SAbhishek Patel 1415c3e9272SAbhishek Patel asyncResp->res.jsonValue[protocolName]["ProtocolEnabled"] = 1425c3e9272SAbhishek Patel isProtocolEnabled; 1435c3e9272SAbhishek Patel asyncResp->res.jsonValue[protocolName]["Port"] = nullptr; 1445c3e9272SAbhishek Patel getPortNumber(socketPath, [asyncResp, protocolName]( 1455c3e9272SAbhishek Patel const boost::system::error_code& ec2, 1465c3e9272SAbhishek Patel int portNumber) { 1475c3e9272SAbhishek Patel if (ec2) 1485c3e9272SAbhishek Patel { 1495c3e9272SAbhishek Patel messages::internalError(asyncResp->res); 1505c3e9272SAbhishek Patel return; 1515c3e9272SAbhishek Patel } 1525c3e9272SAbhishek Patel asyncResp->res.jsonValue[protocolName]["Port"] = portNumber; 1535c3e9272SAbhishek Patel }); 1545c3e9272SAbhishek Patel } 1555c3e9272SAbhishek Patel } 1565c3e9272SAbhishek Patel 1574f48d5f6SEd Tanous inline void getNetworkData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 15872048780SAbhishek Patel const crow::Request& req) 1591abe55efSEd Tanous { 1603e72c202SNinad Palsule if (req.session == nullptr) 1613e72c202SNinad Palsule { 1623e72c202SNinad Palsule messages::internalError(asyncResp->res); 1633e72c202SNinad Palsule return; 1643e72c202SNinad Palsule } 1653e72c202SNinad Palsule 166e9f71672SEd Tanous asyncResp->res.addHeader( 167e9f71672SEd Tanous boost::beast::http::field::link, 168e9f71672SEd Tanous "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/NetworkProtocol.json>; rel=describedby"); 1690f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1700eebcefbSJishnu CM "#ManagerNetworkProtocol.v1_9_0.ManagerNetworkProtocol"; 1710f74e643SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 172253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/NetworkProtocol", 173253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 1740f74e643SEd Tanous asyncResp->res.jsonValue["Id"] = "NetworkProtocol"; 1750f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Network Protocol"; 1760f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = "Manager Network Service"; 177539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK; 178539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["HealthRollup"] = resource::Health::OK; 179539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled; 1800f74e643SEd Tanous 18161932318SXiaochao Ma // HTTP is Mandatory attribute as per OCP Baseline Profile - v1.0.0, 182818ea7b8SJoshi-Mansi // but from security perspective it is not recommended to use. 183818ea7b8SJoshi-Mansi // Hence using protocolEnabled as false to make it OCP and security-wise 184818ea7b8SJoshi-Mansi // compliant 1855c3e9272SAbhishek Patel asyncResp->res.jsonValue["HTTP"]["Port"] = nullptr; 186818ea7b8SJoshi-Mansi asyncResp->res.jsonValue["HTTP"]["ProtocolEnabled"] = false; 187818ea7b8SJoshi-Mansi 1881ee2db7fSAndrew Geissler // The ProtocolEnabled of the following protocols is determined by 1891ee2db7fSAndrew Geissler // inspecting the state of associated systemd sockets. If these protocols 1901ee2db7fSAndrew Geissler // have been disabled, then the systemd socket unit files will not be found 1911ee2db7fSAndrew Geissler // and the protocols will not be returned in this Redfish query. Set some 1921ee2db7fSAndrew Geissler // defaults to ensure something is always returned. 1931ee2db7fSAndrew Geissler for (const auto& nwkProtocol : networkProtocolToDbus) 1941ee2db7fSAndrew Geissler { 1951ee2db7fSAndrew Geissler asyncResp->res.jsonValue[nwkProtocol.first]["Port"] = nullptr; 1961ee2db7fSAndrew Geissler asyncResp->res.jsonValue[nwkProtocol.first]["ProtocolEnabled"] = false; 1971ee2db7fSAndrew Geissler } 1981ee2db7fSAndrew Geissler 199d24bfc7aSJennifer Lee std::string hostName = getHostName(); 200d24bfc7aSJennifer Lee 201d24bfc7aSJennifer Lee asyncResp->res.jsonValue["HostName"] = hostName; 2023a8a0088SKowalski, Kamil 20320e6ea5dSraviteja-b getNTPProtocolEnabled(asyncResp); 20420e6ea5dSraviteja-b 205bd79bce8SPatrick Williams getEthernetIfaceData([hostName, asyncResp]( 206bd79bce8SPatrick Williams const bool& success, 20702cad96eSEd Tanous const std::vector<std::string>& ntpServers, 2080eebcefbSJishnu CM const std::vector<std::string>& dynamicNtpServers, 209d24bfc7aSJennifer Lee const std::vector<std::string>& domainNames) { 21020e6ea5dSraviteja-b if (!success) 21120e6ea5dSraviteja-b { 2120a052baaSGeorge Liu messages::resourceNotFound(asyncResp->res, "ManagerNetworkProtocol", 2130a052baaSGeorge Liu "NetworkProtocol"); 21420e6ea5dSraviteja-b return; 21520e6ea5dSraviteja-b } 21620e6ea5dSraviteja-b asyncResp->res.jsonValue["NTP"]["NTPServers"] = ntpServers; 2170eebcefbSJishnu CM asyncResp->res.jsonValue["NTP"]["NetworkSuppliedServers"] = 2180eebcefbSJishnu CM dynamicNtpServers; 21926f6976fSEd Tanous if (!hostName.empty()) 220d24bfc7aSJennifer Lee { 221f23b7296SEd Tanous std::string fqdn = hostName; 22226f6976fSEd Tanous if (!domainNames.empty()) 223d24bfc7aSJennifer Lee { 224f23b7296SEd Tanous fqdn += "."; 225f23b7296SEd Tanous fqdn += domainNames[0]; 226d24bfc7aSJennifer Lee } 2272c70f800SEd Tanous asyncResp->res.jsonValue["FQDN"] = std::move(fqdn); 228d24bfc7aSJennifer Lee } 22920e6ea5dSraviteja-b }); 23020e6ea5dSraviteja-b 23172048780SAbhishek Patel Privileges effectiveUserPrivileges = 2323e72c202SNinad Palsule redfish::getUserPrivileges(*req.session); 23372048780SAbhishek Patel 23472048780SAbhishek Patel // /redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates is 23572048780SAbhishek Patel // something only ConfigureManager can access then only display when 23672048780SAbhishek Patel // the user has permissions ConfigureManager 23772048780SAbhishek Patel if (isOperationAllowedWithPrivileges({{"ConfigureManager"}}, 23872048780SAbhishek Patel effectiveUserPrivileges)) 23972048780SAbhishek Patel { 2401476687dSEd Tanous asyncResp->res.jsonValue["HTTPS"]["Certificates"]["@odata.id"] = 241253f11b8SEd Tanous boost::urls::format( 242253f11b8SEd Tanous "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates", 243253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 24470141561SBorawski.Lukasz } 24570141561SBorawski.Lukasz 2465c3e9272SAbhishek Patel getPortStatusAndPath(std::span(networkProtocolToDbus), 2475c3e9272SAbhishek Patel std::bind_front(afterNetworkPortRequest, asyncResp)); 248b4bec66bSAbhishek Patel } // namespace redfish 249501be32bSraviteja-b 2508e157735SEd Tanous inline void afterSetNTP(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2518e157735SEd Tanous const boost::system::error_code& ec) 25220e6ea5dSraviteja-b { 2538e157735SEd Tanous if (ec) 25420e6ea5dSraviteja-b { 2558e157735SEd Tanous BMCWEB_LOG_DEBUG("Failed to set elapsed time. DBUS response error {}", 2568e157735SEd Tanous ec); 2578e157735SEd Tanous messages::internalError(asyncResp->res); 2588e157735SEd Tanous return; 25920e6ea5dSraviteja-b } 2608e157735SEd Tanous asyncResp->res.result(boost::beast::http::status::no_content); 26120e6ea5dSraviteja-b } 26220e6ea5dSraviteja-b 2638e157735SEd Tanous inline void handleNTPProtocolEnabled( 2648e157735SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool ntpEnabled) 2658e157735SEd Tanous { 2668e157735SEd Tanous bool interactive = false; 2678e157735SEd Tanous auto callback = [asyncResp](const boost::system::error_code& ec) { 2688e157735SEd Tanous afterSetNTP(asyncResp, ec); 2698e157735SEd Tanous }; 2708e157735SEd Tanous crow::connections::systemBus->async_method_call( 2718e157735SEd Tanous std::move(callback), "org.freedesktop.timedate1", 2728e157735SEd Tanous "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "SetNTP", 2738e157735SEd Tanous ntpEnabled, interactive); 27420e6ea5dSraviteja-b } 27520e6ea5dSraviteja-b 276ed4de7a8SEd Tanous // Redfish states that ip addresses can be 277ed4de7a8SEd Tanous // string, to set a value 278ed4de7a8SEd Tanous // null, to delete the value 279ed4de7a8SEd Tanous // object_t, empty json object, to ignore the value 280ed4de7a8SEd Tanous using IpAddress = 281ed4de7a8SEd Tanous std::variant<std::string, nlohmann::json::object_t, std::nullptr_t>; 282ed4de7a8SEd Tanous 2834f48d5f6SEd Tanous inline void 284287ece64SGeorge Liu handleNTPServersPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 285ed4de7a8SEd Tanous const std::vector<IpAddress>& ntpServerObjects, 286b9e15228SEd Tanous std::vector<std::string> currentNtpServers) 28720e6ea5dSraviteja-b { 288b9e15228SEd Tanous std::vector<std::string>::iterator currentNtpServer = 289b9e15228SEd Tanous currentNtpServers.begin(); 290b9e15228SEd Tanous for (size_t index = 0; index < ntpServerObjects.size(); index++) 291287ece64SGeorge Liu { 292ed4de7a8SEd Tanous const IpAddress& ntpServer = ntpServerObjects[index]; 293ed4de7a8SEd Tanous if (std::holds_alternative<std::nullptr_t>(ntpServer)) 294b9e15228SEd Tanous { 295b9e15228SEd Tanous // Can't delete an item that doesn't exist 296b9e15228SEd Tanous if (currentNtpServer == currentNtpServers.end()) 297b9e15228SEd Tanous { 298bd79bce8SPatrick Williams messages::propertyValueNotInList( 299bd79bce8SPatrick Williams asyncResp->res, "null", 300bd79bce8SPatrick Williams "NTP/NTPServers/" + std::to_string(index)); 301b9e15228SEd Tanous 302287ece64SGeorge Liu return; 303287ece64SGeorge Liu } 304b9e15228SEd Tanous currentNtpServer = currentNtpServers.erase(currentNtpServer); 305b9e15228SEd Tanous continue; 306b9e15228SEd Tanous } 307b9e15228SEd Tanous const nlohmann::json::object_t* ntpServerObject = 308ed4de7a8SEd Tanous std::get_if<nlohmann::json::object_t>(&ntpServer); 309b9e15228SEd Tanous if (ntpServerObject != nullptr) 310b9e15228SEd Tanous { 311b9e15228SEd Tanous if (!ntpServerObject->empty()) 312b9e15228SEd Tanous { 313ed4de7a8SEd Tanous messages::propertyValueNotInList( 314ed4de7a8SEd Tanous asyncResp->res, *ntpServerObject, 315ed4de7a8SEd Tanous "NTP/NTPServers/" + std::to_string(index)); 316b9e15228SEd Tanous return; 317b9e15228SEd Tanous } 318b9e15228SEd Tanous // Can't retain an item that doesn't exist 319b9e15228SEd Tanous if (currentNtpServer == currentNtpServers.end()) 320b9e15228SEd Tanous { 321ed4de7a8SEd Tanous messages::propertyValueOutOfRange( 322ed4de7a8SEd Tanous asyncResp->res, *ntpServerObject, 323ed4de7a8SEd Tanous "NTP/NTPServers/" + std::to_string(index)); 324b9e15228SEd Tanous 325b9e15228SEd Tanous return; 326b9e15228SEd Tanous } 327b9e15228SEd Tanous // empty objects should leave the NtpServer unmodified 328b9e15228SEd Tanous currentNtpServer++; 329b9e15228SEd Tanous continue; 330b9e15228SEd Tanous } 331b9e15228SEd Tanous 332ed4de7a8SEd Tanous const std::string* ntpServerStr = std::get_if<std::string>(&ntpServer); 333b9e15228SEd Tanous if (ntpServerStr == nullptr) 334b9e15228SEd Tanous { 335ed4de7a8SEd Tanous messages::internalError(asyncResp->res); 336b9e15228SEd Tanous return; 337b9e15228SEd Tanous } 338b9e15228SEd Tanous if (currentNtpServer == currentNtpServers.end()) 339b9e15228SEd Tanous { 340b9e15228SEd Tanous // if we're at the end of the list, append to the end 341b9e15228SEd Tanous currentNtpServers.push_back(*ntpServerStr); 342b9e15228SEd Tanous currentNtpServer = currentNtpServers.end(); 343b9e15228SEd Tanous continue; 344b9e15228SEd Tanous } 345b9e15228SEd Tanous *currentNtpServer = *ntpServerStr; 346b9e15228SEd Tanous currentNtpServer++; 347b9e15228SEd Tanous } 348b9e15228SEd Tanous 349b9e15228SEd Tanous // Any remaining array elements should be removed 350b9e15228SEd Tanous currentNtpServers.erase(currentNtpServer, currentNtpServers.end()); 351287ece64SGeorge Liu 352e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> ethInterfaces = { 353e99073f5SGeorge Liu "xyz.openbmc_project.Network.EthernetInterface"}; 354e99073f5SGeorge Liu dbus::utility::getSubTree( 355e99073f5SGeorge Liu "/xyz/openbmc_project", 0, ethInterfaces, 356b9e15228SEd Tanous [asyncResp, currentNtpServers]( 3572138483cSGeorge Liu const boost::system::error_code& ec, 358b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 3590a052baaSGeorge Liu if (ec) 3600a052baaSGeorge Liu { 36162598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 3620a052baaSGeorge Liu messages::internalError(asyncResp->res); 3630a052baaSGeorge Liu return; 3640a052baaSGeorge Liu } 3650a052baaSGeorge Liu 3660a052baaSGeorge Liu for (const auto& [objectPath, serviceMap] : subtree) 3670a052baaSGeorge Liu { 3680a052baaSGeorge Liu for (const auto& [service, interfaces] : serviceMap) 3690a052baaSGeorge Liu { 3700a052baaSGeorge Liu for (const auto& interface : interfaces) 3710a052baaSGeorge Liu { 3720a052baaSGeorge Liu if (interface != 3730a052baaSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface") 3740a052baaSGeorge Liu { 3750a052baaSGeorge Liu continue; 3760a052baaSGeorge Liu } 3770a052baaSGeorge Liu 378e93abac6SGinu George setDbusProperty(asyncResp, "NTP/NTPServers/", service, 379bd79bce8SPatrick Williams objectPath, interface, 380bd79bce8SPatrick Williams "StaticNTPServers", currentNtpServers); 38120e6ea5dSraviteja-b } 3820a052baaSGeorge Liu } 3830a052baaSGeorge Liu } 384e99073f5SGeorge Liu }); 3850a052baaSGeorge Liu } 38620e6ea5dSraviteja-b 3874f48d5f6SEd Tanous inline void 3884f48d5f6SEd Tanous handleProtocolEnabled(const bool protocolEnabled, 389e5a99777SAlbert Zhang const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 39069320d54SJiaqing Zhao const std::string& netBasePath) 39167a78d87STom Joseph { 392e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 393e99073f5SGeorge Liu "xyz.openbmc_project.Control.Service.Attributes"}; 394e99073f5SGeorge Liu dbus::utility::getSubTree( 395e99073f5SGeorge Liu "/xyz/openbmc_project/control/service", 0, interfaces, 396e5a99777SAlbert Zhang [protocolEnabled, asyncResp, 3972138483cSGeorge Liu netBasePath](const boost::system::error_code& ec, 398b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 39967a78d87STom Joseph if (ec) 40067a78d87STom Joseph { 40167a78d87STom Joseph messages::internalError(asyncResp->res); 40267a78d87STom Joseph return; 40367a78d87STom Joseph } 40467a78d87STom Joseph 40567a78d87STom Joseph for (const auto& entry : subtree) 40667a78d87STom Joseph { 40718f8f608SEd Tanous if (entry.first.starts_with(netBasePath)) 40867a78d87STom Joseph { 40987c44966SAsmitha Karunanithi setDbusProperty( 410e93abac6SGinu George asyncResp, "IPMI/ProtocolEnabled", 411e93abac6SGinu George entry.second.begin()->first, entry.first, 412bd79bce8SPatrick Williams "xyz.openbmc_project.Control.Service.Attributes", 413bd79bce8SPatrick Williams "Running", protocolEnabled); 41487c44966SAsmitha Karunanithi setDbusProperty( 415e93abac6SGinu George asyncResp, "IPMI/ProtocolEnabled", 416e93abac6SGinu George entry.second.begin()->first, entry.first, 417bd79bce8SPatrick Williams "xyz.openbmc_project.Control.Service.Attributes", 418bd79bce8SPatrick Williams "Enabled", protocolEnabled); 41967a78d87STom Joseph } 42067a78d87STom Joseph } 421e99073f5SGeorge Liu }); 42267a78d87STom Joseph } 42367a78d87STom Joseph 4244f48d5f6SEd Tanous inline std::string getHostName() 425501be32bSraviteja-b { 4267e860f15SJohn Edward Broadbent std::string hostName; 4278d1b46d7Szhanghch05 428d3a9e084SEd Tanous std::array<char, HOST_NAME_MAX> hostNameCStr{}; 4297e860f15SJohn Edward Broadbent if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0) 4307e860f15SJohn Edward Broadbent { 4317e860f15SJohn Edward Broadbent hostName = hostNameCStr.data(); 4327e860f15SJohn Edward Broadbent } 4337e860f15SJohn Edward Broadbent return hostName; 4347e860f15SJohn Edward Broadbent } 4357e860f15SJohn Edward Broadbent 4364f48d5f6SEd Tanous inline void 4374f48d5f6SEd Tanous getNTPProtocolEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 4387e860f15SJohn Edward Broadbent { 439deae6a78SEd Tanous dbus::utility::getProperty<bool>( 440deae6a78SEd Tanous "org.freedesktop.timedate1", "/org/freedesktop/timedate1", 441deae6a78SEd Tanous "org.freedesktop.timedate1", "NTP", 4428e157735SEd Tanous [asyncResp](const boost::system::error_code& ec, bool enabled) { 4438b24275dSEd Tanous if (ec) 4447e860f15SJohn Edward Broadbent { 4458e157735SEd Tanous BMCWEB_LOG_WARNING( 4468e157735SEd Tanous "Failed to get NTP status, assuming not supported"); 4477e860f15SJohn Edward Broadbent return; 4487e860f15SJohn Edward Broadbent } 4497e860f15SJohn Edward Broadbent 4508e157735SEd Tanous asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = enabled; 4511e1e598dSJonathan Doman }); 4527e860f15SJohn Edward Broadbent } 4537e860f15SJohn Edward Broadbent 4545c3e9272SAbhishek Patel inline std::string encodeServiceObjectPath(std::string_view serviceName) 45569320d54SJiaqing Zhao { 45669320d54SJiaqing Zhao sdbusplus::message::object_path objPath( 45769320d54SJiaqing Zhao "/xyz/openbmc_project/control/service"); 45869320d54SJiaqing Zhao objPath /= serviceName; 45969320d54SJiaqing Zhao return objPath.str; 46069320d54SJiaqing Zhao } 46169320d54SJiaqing Zhao 4620f55d946SEd Tanous inline void handleBmcNetworkProtocolHead( 463e9f71672SEd Tanous crow::App& app, const crow::Request& req, 464e9f71672SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 465e9f71672SEd Tanous { 466e9f71672SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 467e9f71672SEd Tanous { 468e9f71672SEd Tanous return; 469e9f71672SEd Tanous } 470e9f71672SEd Tanous asyncResp->res.addHeader( 471e9f71672SEd Tanous boost::beast::http::field::link, 472e9f71672SEd Tanous "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/ManagerNetworkProtocol.json>; rel=describedby"); 473e9f71672SEd Tanous } 474e9f71672SEd Tanous 475e634b34cSEd Tanous inline void handleManagersNetworkProtocolPatch( 476e634b34cSEd Tanous App& app, const crow::Request& req, 477253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 478253f11b8SEd Tanous const std::string& managerId) 4797e860f15SJohn Edward Broadbent { 4803ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 48145ca1b86SEd Tanous { 48245ca1b86SEd Tanous return; 48345ca1b86SEd Tanous } 484253f11b8SEd Tanous 485253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 486253f11b8SEd Tanous { 487253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 488253f11b8SEd Tanous return; 489253f11b8SEd Tanous } 490253f11b8SEd Tanous 491501be32bSraviteja-b std::optional<std::string> newHostName; 492ed4de7a8SEd Tanous 493ed4de7a8SEd Tanous std::optional<std::vector<IpAddress>> ntpServerObjects; 4945f4c798dSJiaqing Zhao std::optional<bool> ntpEnabled; 4955f4c798dSJiaqing Zhao std::optional<bool> ipmiEnabled; 4965f4c798dSJiaqing Zhao std::optional<bool> sshEnabled; 497501be32bSraviteja-b 4985f4c798dSJiaqing Zhao if (!json_util::readJsonPatch( 499afc474aeSMyung Bae req, asyncResp->res, // 500afc474aeSMyung Bae "HostName", newHostName, // 501afc474aeSMyung Bae "NTP/NTPServers", ntpServerObjects, // 502afc474aeSMyung Bae "NTP/ProtocolEnabled", ntpEnabled, // 503afc474aeSMyung Bae "IPMI/ProtocolEnabled", ipmiEnabled, // 504afc474aeSMyung Bae "SSH/ProtocolEnabled", sshEnabled // 505afc474aeSMyung Bae )) 506501be32bSraviteja-b { 507501be32bSraviteja-b return; 508501be32bSraviteja-b } 509cf05f9dcSJohnathan Mantey 5108d1b46d7Szhanghch05 asyncResp->res.result(boost::beast::http::status::no_content); 511501be32bSraviteja-b if (newHostName) 512501be32bSraviteja-b { 5132db77d34SJohnathan Mantey messages::propertyNotWritable(asyncResp->res, "HostName"); 51444fad2aaSEd Tanous return; 515cf05f9dcSJohnathan Mantey } 516cf05f9dcSJohnathan Mantey 51720e6ea5dSraviteja-b if (ntpEnabled) 51820e6ea5dSraviteja-b { 5198e157735SEd Tanous handleNTPProtocolEnabled(asyncResp, *ntpEnabled); 52020e6ea5dSraviteja-b } 521b9e15228SEd Tanous if (ntpServerObjects) 52220e6ea5dSraviteja-b { 523b9e15228SEd Tanous getEthernetIfaceData( 524b9e15228SEd Tanous [asyncResp, ntpServerObjects]( 525e634b34cSEd Tanous const bool success, std::vector<std::string>& currentNtpServers, 5260eebcefbSJishnu CM const std::vector<std::string>& /*dynamicNtpServers*/, 527b9e15228SEd Tanous const std::vector<std::string>& /*domainNames*/) { 528b9e15228SEd Tanous if (!success) 529b9e15228SEd Tanous { 530b9e15228SEd Tanous messages::internalError(asyncResp->res); 531b9e15228SEd Tanous return; 532b9e15228SEd Tanous } 533b9e15228SEd Tanous handleNTPServersPatch(asyncResp, *ntpServerObjects, 534b9e15228SEd Tanous std::move(currentNtpServers)); 535b9e15228SEd Tanous }); 53620e6ea5dSraviteja-b } 53767a78d87STom Joseph 5385f4c798dSJiaqing Zhao if (ipmiEnabled) 53967a78d87STom Joseph { 540e5a99777SAlbert Zhang handleProtocolEnabled( 5415f4c798dSJiaqing Zhao *ipmiEnabled, asyncResp, 54269320d54SJiaqing Zhao encodeServiceObjectPath(std::string(ipmiServiceName) + '@')); 543e5a99777SAlbert Zhang } 544e5a99777SAlbert Zhang 5455f4c798dSJiaqing Zhao if (sshEnabled) 546e5a99777SAlbert Zhang { 54769320d54SJiaqing Zhao handleProtocolEnabled(*sshEnabled, asyncResp, 54869320d54SJiaqing Zhao encodeServiceObjectPath(sshServiceName)); 54967a78d87STom Joseph } 550e634b34cSEd Tanous } 551e634b34cSEd Tanous 552af20dd1cSEd Tanous inline void handleManagersNetworkProtocolHead( 553e634b34cSEd Tanous App& app, const crow::Request& req, 554253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 555253f11b8SEd Tanous const std::string& managerId) 556e634b34cSEd Tanous { 557e634b34cSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 558e634b34cSEd Tanous { 559e634b34cSEd Tanous return; 560e634b34cSEd Tanous } 561af20dd1cSEd Tanous asyncResp->res.addHeader( 562af20dd1cSEd Tanous boost::beast::http::field::link, 563af20dd1cSEd Tanous "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/ManagerNetworkProtocol.json>; rel=describedby"); 564253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 565253f11b8SEd Tanous { 566253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 567253f11b8SEd Tanous return; 568253f11b8SEd Tanous } 569af20dd1cSEd Tanous } 570af20dd1cSEd Tanous 571af20dd1cSEd Tanous inline void handleManagersNetworkProtocolGet( 572af20dd1cSEd Tanous App& app, const crow::Request& req, 573253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 574253f11b8SEd Tanous const std::string& managerId) 575af20dd1cSEd Tanous { 576253f11b8SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 577253f11b8SEd Tanous { 578253f11b8SEd Tanous return; 579253f11b8SEd Tanous } 580253f11b8SEd Tanous asyncResp->res.addHeader( 581253f11b8SEd Tanous boost::beast::http::field::link, 582253f11b8SEd Tanous "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/ManagerNetworkProtocol.json>; rel=describedby"); 583253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 584253f11b8SEd Tanous { 585253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 586253f11b8SEd Tanous return; 587253f11b8SEd Tanous } 588253f11b8SEd Tanous 589e634b34cSEd Tanous getNetworkData(asyncResp, req); 590e634b34cSEd Tanous } 591e634b34cSEd Tanous 592e634b34cSEd Tanous inline void requestRoutesNetworkProtocol(App& app) 593e634b34cSEd Tanous { 594253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/NetworkProtocol/") 595e634b34cSEd Tanous .privileges(redfish::privileges::patchManagerNetworkProtocol) 596e634b34cSEd Tanous .methods(boost::beast::http::verb::patch)( 597e634b34cSEd Tanous std::bind_front(handleManagersNetworkProtocolPatch, std::ref(app))); 5987e860f15SJohn Edward Broadbent 599253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/NetworkProtocol/") 600e9f71672SEd Tanous .privileges(redfish::privileges::headManagerNetworkProtocol) 601e9f71672SEd Tanous .methods(boost::beast::http::verb::head)( 602af20dd1cSEd Tanous std::bind_front(handleManagersNetworkProtocolHead, std::ref(app))); 603e9f71672SEd Tanous 604253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/NetworkProtocol/") 605ed398213SEd Tanous .privileges(redfish::privileges::getManagerNetworkProtocol) 6067e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 607e634b34cSEd Tanous std::bind_front(handleManagersNetworkProtocolGet, std::ref(app))); 608cf05f9dcSJohnathan Mantey } 60970141561SBorawski.Lukasz 61070141561SBorawski.Lukasz } // namespace redfish 611