140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 340e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation 470141561SBorawski.Lukasz #pragma once 570141561SBorawski.Lukasz 6d7857201SEd Tanous #include "bmcweb_config.h" 7d7857201SEd Tanous 83ccb3adbSEd Tanous #include "app.hpp" 9d7857201SEd Tanous #include "async_resp.hpp" 103ccb3adbSEd Tanous #include "dbus_utility.hpp" 113a8a0088SKowalski, Kamil #include "error_messages.hpp" 12539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 13d7857201SEd Tanous #include "http_request.hpp" 144d7b5ddbSMalik Akbar Hashemi Rafsanjani #include "identity.hpp" 15d7857201SEd Tanous #include "logging.hpp" 16d7857201SEd Tanous #include "privileges.hpp" 173ccb3adbSEd Tanous #include "query.hpp" 18b4bec66bSAbhishek Patel #include "redfish_util.hpp" 193ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 20d7857201SEd Tanous #include "utils/dbus_utils.hpp" 213ccb3adbSEd Tanous #include "utils/json_utils.hpp" 223ccb3adbSEd Tanous #include "utils/stl_utils.hpp" 2370141561SBorawski.Lukasz 24d7857201SEd Tanous #include <boost/beast/http/field.hpp> 25d7857201SEd Tanous #include <boost/beast/http/status.hpp> 26d7857201SEd Tanous #include <boost/beast/http/verb.hpp> 27e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 28253f11b8SEd Tanous #include <boost/url/format.hpp> 29d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp> 301214b7e7SGunnar Mills 31e99073f5SGeorge Liu #include <array> 32d7857201SEd Tanous #include <cstddef> 33d7857201SEd Tanous #include <functional> 34d7857201SEd Tanous #include <memory> 351214b7e7SGunnar Mills #include <optional> 36d7857201SEd Tanous #include <string> 37e99073f5SGeorge Liu #include <string_view> 38d7857201SEd Tanous #include <tuple> 39d7857201SEd Tanous #include <utility> 40abf2add6SEd Tanous #include <variant> 410eebcefbSJishnu CM #include <vector> 425f4c798dSJiaqing Zhao 431abe55efSEd Tanous namespace redfish 441abe55efSEd Tanous { 4570141561SBorawski.Lukasz 467e860f15SJohn Edward Broadbent void getNTPProtocolEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp); 477e860f15SJohn Edward Broadbent 485c3e9272SAbhishek Patel static constexpr std::string_view sshServiceName = "dropbear"; 495c3e9272SAbhishek Patel static constexpr std::string_view httpsServiceName = "bmcweb"; 505c3e9272SAbhishek Patel static constexpr std::string_view ipmiServiceName = "phosphor-ipmi-net"; 515c3e9272SAbhishek Patel 525c3e9272SAbhishek Patel // Mapping from Redfish NetworkProtocol key name to backend service that hosts 535c3e9272SAbhishek Patel // that protocol. 545c3e9272SAbhishek Patel static constexpr std::array<std::pair<std::string_view, std::string_view>, 3> 555c3e9272SAbhishek Patel networkProtocolToDbus = {{{"SSH", sshServiceName}, 5669320d54SJiaqing Zhao {"HTTPS", httpsServiceName}, 5769320d54SJiaqing Zhao {"IPMI", ipmiServiceName}}}; 583a8a0088SKowalski, Kamil 59711ac7a9SEd Tanous inline void extractNTPServersAndDomainNamesData( 60711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 610eebcefbSJishnu CM std::vector<std::string>& ntpData, std::vector<std::string>& dynamicNtpData, 620eebcefbSJishnu CM std::vector<std::string>& dnData) 6320e6ea5dSraviteja-b { 6481ce609eSEd Tanous for (const auto& obj : dbusData) 6520e6ea5dSraviteja-b { 6620e6ea5dSraviteja-b for (const auto& ifacePair : obj.second) 6720e6ea5dSraviteja-b { 680a052baaSGeorge Liu if (ifacePair.first != 6920e6ea5dSraviteja-b "xyz.openbmc_project.Network.EthernetInterface") 7020e6ea5dSraviteja-b { 710a052baaSGeorge Liu continue; 720a052baaSGeorge Liu } 730a052baaSGeorge Liu 7420e6ea5dSraviteja-b for (const auto& propertyPair : ifacePair.second) 7520e6ea5dSraviteja-b { 76fcd2682aSEd Tanous if (propertyPair.first == "StaticNTPServers") 7720e6ea5dSraviteja-b { 7820e6ea5dSraviteja-b const std::vector<std::string>* ntpServers = 798d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 8020e6ea5dSraviteja-b &propertyPair.second); 8120e6ea5dSraviteja-b if (ntpServers != nullptr) 8220e6ea5dSraviteja-b { 83c251fe81SJian Zhang ntpData.insert(ntpData.end(), ntpServers->begin(), 84c251fe81SJian Zhang ntpServers->end()); 8520e6ea5dSraviteja-b } 8620e6ea5dSraviteja-b } 870eebcefbSJishnu CM else if (propertyPair.first == "NTPServers") 880eebcefbSJishnu CM { 890eebcefbSJishnu CM const std::vector<std::string>* dynamicNtpServers = 900eebcefbSJishnu CM std::get_if<std::vector<std::string>>( 910eebcefbSJishnu CM &propertyPair.second); 920eebcefbSJishnu CM if (dynamicNtpServers != nullptr) 930eebcefbSJishnu CM { 940eebcefbSJishnu CM dynamicNtpData = *dynamicNtpServers; 950eebcefbSJishnu CM } 960eebcefbSJishnu CM } 97d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 98d24bfc7aSJennifer Lee { 99d24bfc7aSJennifer Lee const std::vector<std::string>* domainNames = 1008d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 101d24bfc7aSJennifer Lee &propertyPair.second); 102d24bfc7aSJennifer Lee if (domainNames != nullptr) 103d24bfc7aSJennifer Lee { 104c251fe81SJian Zhang dnData.insert(dnData.end(), domainNames->begin(), 105c251fe81SJian Zhang domainNames->end()); 106d24bfc7aSJennifer Lee } 107d24bfc7aSJennifer Lee } 10820e6ea5dSraviteja-b } 10920e6ea5dSraviteja-b } 11020e6ea5dSraviteja-b } 1110225b87bSEd Tanous stl_utils::removeDuplicate(ntpData); 112c251fe81SJian Zhang stl_utils::removeDuplicate(dnData); 11320e6ea5dSraviteja-b } 11420e6ea5dSraviteja-b 11520e6ea5dSraviteja-b template <typename CallbackFunc> 11620e6ea5dSraviteja-b void getEthernetIfaceData(CallbackFunc&& callback) 11720e6ea5dSraviteja-b { 1185eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1195eb468daSGeorge Liu dbus::utility::getManagedObjects( 1205eb468daSGeorge Liu "xyz.openbmc_project.Network", path, 1218cb2c024SEd Tanous [callback = std::forward<CallbackFunc>(callback)]( 1228b24275dSEd Tanous const boost::system::error_code& ec, 123711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData) { 12420e6ea5dSraviteja-b std::vector<std::string> ntpServers; 1250eebcefbSJishnu CM std::vector<std::string> dynamicNtpServers; 126d24bfc7aSJennifer Lee std::vector<std::string> domainNames; 12720e6ea5dSraviteja-b 1288b24275dSEd Tanous if (ec) 12920e6ea5dSraviteja-b { 1300eebcefbSJishnu CM callback(false, ntpServers, dynamicNtpServers, domainNames); 13120e6ea5dSraviteja-b return; 13220e6ea5dSraviteja-b } 13320e6ea5dSraviteja-b 134bd79bce8SPatrick Williams extractNTPServersAndDomainNamesData(dbusData, ntpServers, 1350eebcefbSJishnu CM dynamicNtpServers, domainNames); 13620e6ea5dSraviteja-b 1370eebcefbSJishnu CM callback(true, ntpServers, dynamicNtpServers, domainNames); 1385eb468daSGeorge Liu }); 139271584abSEd Tanous } 14020e6ea5dSraviteja-b 1415c3e9272SAbhishek Patel inline void afterNetworkPortRequest( 1425c3e9272SAbhishek Patel const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1435c3e9272SAbhishek Patel const boost::system::error_code& ec, 1445c3e9272SAbhishek Patel const std::vector<std::tuple<std::string, std::string, bool>>& socketData) 1455c3e9272SAbhishek Patel { 1465c3e9272SAbhishek Patel if (ec) 1475c3e9272SAbhishek Patel { 1485c3e9272SAbhishek Patel messages::internalError(asyncResp->res); 1495c3e9272SAbhishek Patel return; 1505c3e9272SAbhishek Patel } 1515c3e9272SAbhishek Patel for (const auto& data : socketData) 1525c3e9272SAbhishek Patel { 1535c3e9272SAbhishek Patel const std::string& socketPath = get<0>(data); 1545c3e9272SAbhishek Patel const std::string& protocolName = get<1>(data); 1555c3e9272SAbhishek Patel bool isProtocolEnabled = get<2>(data); 1565c3e9272SAbhishek Patel 1575c3e9272SAbhishek Patel asyncResp->res.jsonValue[protocolName]["ProtocolEnabled"] = 1585c3e9272SAbhishek Patel isProtocolEnabled; 1595c3e9272SAbhishek Patel asyncResp->res.jsonValue[protocolName]["Port"] = nullptr; 1605c3e9272SAbhishek Patel getPortNumber(socketPath, [asyncResp, protocolName]( 1615c3e9272SAbhishek Patel const boost::system::error_code& ec2, 1625c3e9272SAbhishek Patel int portNumber) { 1635c3e9272SAbhishek Patel if (ec2) 1645c3e9272SAbhishek Patel { 1655c3e9272SAbhishek Patel messages::internalError(asyncResp->res); 1665c3e9272SAbhishek Patel return; 1675c3e9272SAbhishek Patel } 1685c3e9272SAbhishek Patel asyncResp->res.jsonValue[protocolName]["Port"] = portNumber; 1695c3e9272SAbhishek Patel }); 1705c3e9272SAbhishek Patel } 1715c3e9272SAbhishek Patel } 1725c3e9272SAbhishek Patel 1734f48d5f6SEd Tanous inline void getNetworkData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 17472048780SAbhishek Patel const crow::Request& req) 1751abe55efSEd Tanous { 1763e72c202SNinad Palsule if (req.session == nullptr) 1773e72c202SNinad Palsule { 1783e72c202SNinad Palsule messages::internalError(asyncResp->res); 1793e72c202SNinad Palsule return; 1803e72c202SNinad Palsule } 1813e72c202SNinad Palsule 182e9f71672SEd Tanous asyncResp->res.addHeader( 183e9f71672SEd Tanous boost::beast::http::field::link, 184e9f71672SEd Tanous "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/NetworkProtocol.json>; rel=describedby"); 1850f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1860eebcefbSJishnu CM "#ManagerNetworkProtocol.v1_9_0.ManagerNetworkProtocol"; 1870f74e643SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 188253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/NetworkProtocol", 189253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 1900f74e643SEd Tanous asyncResp->res.jsonValue["Id"] = "NetworkProtocol"; 1910f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Network Protocol"; 1920f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = "Manager Network Service"; 193539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK; 194539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["HealthRollup"] = resource::Health::OK; 195539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled; 1960f74e643SEd Tanous 19761932318SXiaochao Ma // HTTP is Mandatory attribute as per OCP Baseline Profile - v1.0.0, 198818ea7b8SJoshi-Mansi // but from security perspective it is not recommended to use. 199818ea7b8SJoshi-Mansi // Hence using protocolEnabled as false to make it OCP and security-wise 200818ea7b8SJoshi-Mansi // compliant 2015c3e9272SAbhishek Patel asyncResp->res.jsonValue["HTTP"]["Port"] = nullptr; 202818ea7b8SJoshi-Mansi asyncResp->res.jsonValue["HTTP"]["ProtocolEnabled"] = false; 203818ea7b8SJoshi-Mansi 2041ee2db7fSAndrew Geissler // The ProtocolEnabled of the following protocols is determined by 2051ee2db7fSAndrew Geissler // inspecting the state of associated systemd sockets. If these protocols 2061ee2db7fSAndrew Geissler // have been disabled, then the systemd socket unit files will not be found 2071ee2db7fSAndrew Geissler // and the protocols will not be returned in this Redfish query. Set some 2081ee2db7fSAndrew Geissler // defaults to ensure something is always returned. 2091ee2db7fSAndrew Geissler for (const auto& nwkProtocol : networkProtocolToDbus) 2101ee2db7fSAndrew Geissler { 2111ee2db7fSAndrew Geissler asyncResp->res.jsonValue[nwkProtocol.first]["Port"] = nullptr; 2121ee2db7fSAndrew Geissler asyncResp->res.jsonValue[nwkProtocol.first]["ProtocolEnabled"] = false; 2131ee2db7fSAndrew Geissler } 2141ee2db7fSAndrew Geissler 215d24bfc7aSJennifer Lee std::string hostName = getHostName(); 216d24bfc7aSJennifer Lee 217d24bfc7aSJennifer Lee asyncResp->res.jsonValue["HostName"] = hostName; 2183a8a0088SKowalski, Kamil 21920e6ea5dSraviteja-b getNTPProtocolEnabled(asyncResp); 22020e6ea5dSraviteja-b 221bd79bce8SPatrick Williams getEthernetIfaceData([hostName, asyncResp]( 222bd79bce8SPatrick Williams const bool& success, 22302cad96eSEd Tanous const std::vector<std::string>& ntpServers, 2240eebcefbSJishnu CM const std::vector<std::string>& dynamicNtpServers, 225d24bfc7aSJennifer Lee const std::vector<std::string>& domainNames) { 22620e6ea5dSraviteja-b if (!success) 22720e6ea5dSraviteja-b { 2280a052baaSGeorge Liu messages::resourceNotFound(asyncResp->res, "ManagerNetworkProtocol", 2290a052baaSGeorge Liu "NetworkProtocol"); 23020e6ea5dSraviteja-b return; 23120e6ea5dSraviteja-b } 23220e6ea5dSraviteja-b asyncResp->res.jsonValue["NTP"]["NTPServers"] = ntpServers; 2330eebcefbSJishnu CM asyncResp->res.jsonValue["NTP"]["NetworkSuppliedServers"] = 2340eebcefbSJishnu CM dynamicNtpServers; 23526f6976fSEd Tanous if (!hostName.empty()) 236d24bfc7aSJennifer Lee { 237f23b7296SEd Tanous std::string fqdn = hostName; 23826f6976fSEd Tanous if (!domainNames.empty()) 239d24bfc7aSJennifer Lee { 240f23b7296SEd Tanous fqdn += "."; 241f23b7296SEd Tanous fqdn += domainNames[0]; 242d24bfc7aSJennifer Lee } 2432c70f800SEd Tanous asyncResp->res.jsonValue["FQDN"] = std::move(fqdn); 244d24bfc7aSJennifer Lee } 24520e6ea5dSraviteja-b }); 24620e6ea5dSraviteja-b 24772048780SAbhishek Patel Privileges effectiveUserPrivileges = 2483e72c202SNinad Palsule redfish::getUserPrivileges(*req.session); 24972048780SAbhishek Patel 25072048780SAbhishek Patel // /redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates is 25172048780SAbhishek Patel // something only ConfigureManager can access then only display when 25272048780SAbhishek Patel // the user has permissions ConfigureManager 25372048780SAbhishek Patel if (isOperationAllowedWithPrivileges({{"ConfigureManager"}}, 25472048780SAbhishek Patel effectiveUserPrivileges)) 25572048780SAbhishek Patel { 2561476687dSEd Tanous asyncResp->res.jsonValue["HTTPS"]["Certificates"]["@odata.id"] = 257253f11b8SEd Tanous boost::urls::format( 258253f11b8SEd Tanous "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates", 259253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 26070141561SBorawski.Lukasz } 26170141561SBorawski.Lukasz 2625c3e9272SAbhishek Patel getPortStatusAndPath(std::span(networkProtocolToDbus), 2635c3e9272SAbhishek Patel std::bind_front(afterNetworkPortRequest, asyncResp)); 264*d2b18018SEd Tanous } 265501be32bSraviteja-b 2668e157735SEd Tanous inline void afterSetNTP(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2678e157735SEd Tanous const boost::system::error_code& ec) 26820e6ea5dSraviteja-b { 2698e157735SEd Tanous if (ec) 27020e6ea5dSraviteja-b { 2718e157735SEd Tanous BMCWEB_LOG_DEBUG("Failed to set elapsed time. DBUS response error {}", 2728e157735SEd Tanous ec); 2738e157735SEd Tanous messages::internalError(asyncResp->res); 2748e157735SEd Tanous return; 27520e6ea5dSraviteja-b } 27620e6ea5dSraviteja-b } 27720e6ea5dSraviteja-b 2788e157735SEd Tanous inline void handleNTPProtocolEnabled( 2798e157735SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool ntpEnabled) 2808e157735SEd Tanous { 2818e157735SEd Tanous bool interactive = false; 2828e157735SEd Tanous auto callback = [asyncResp](const boost::system::error_code& ec) { 2838e157735SEd Tanous afterSetNTP(asyncResp, ec); 2848e157735SEd Tanous }; 285177612aaSEd Tanous dbus::utility::async_method_call( 286177612aaSEd Tanous asyncResp, std::move(callback), "org.freedesktop.timedate1", 2878e157735SEd Tanous "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "SetNTP", 2888e157735SEd Tanous ntpEnabled, interactive); 28920e6ea5dSraviteja-b } 29020e6ea5dSraviteja-b 291ed4de7a8SEd Tanous // Redfish states that ip addresses can be 292ed4de7a8SEd Tanous // string, to set a value 293ed4de7a8SEd Tanous // null, to delete the value 294ed4de7a8SEd Tanous // object_t, empty json object, to ignore the value 295ed4de7a8SEd Tanous using IpAddress = 296ed4de7a8SEd Tanous std::variant<std::string, nlohmann::json::object_t, std::nullptr_t>; 297ed4de7a8SEd Tanous 298504af5a0SPatrick Williams inline void handleNTPServersPatch( 299504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 300ed4de7a8SEd Tanous const std::vector<IpAddress>& ntpServerObjects, 301b9e15228SEd Tanous std::vector<std::string> currentNtpServers) 30220e6ea5dSraviteja-b { 303b9e15228SEd Tanous std::vector<std::string>::iterator currentNtpServer = 304b9e15228SEd Tanous currentNtpServers.begin(); 305b9e15228SEd Tanous for (size_t index = 0; index < ntpServerObjects.size(); index++) 306287ece64SGeorge Liu { 307ed4de7a8SEd Tanous const IpAddress& ntpServer = ntpServerObjects[index]; 308ed4de7a8SEd Tanous if (std::holds_alternative<std::nullptr_t>(ntpServer)) 309b9e15228SEd Tanous { 310b9e15228SEd Tanous // Can't delete an item that doesn't exist 311b9e15228SEd Tanous if (currentNtpServer == currentNtpServers.end()) 312b9e15228SEd Tanous { 313bd79bce8SPatrick Williams messages::propertyValueNotInList( 314bd79bce8SPatrick Williams asyncResp->res, "null", 315bd79bce8SPatrick Williams "NTP/NTPServers/" + std::to_string(index)); 316b9e15228SEd Tanous 317287ece64SGeorge Liu return; 318287ece64SGeorge Liu } 319b9e15228SEd Tanous currentNtpServer = currentNtpServers.erase(currentNtpServer); 320b9e15228SEd Tanous continue; 321b9e15228SEd Tanous } 322b9e15228SEd Tanous const nlohmann::json::object_t* ntpServerObject = 323ed4de7a8SEd Tanous std::get_if<nlohmann::json::object_t>(&ntpServer); 324b9e15228SEd Tanous if (ntpServerObject != nullptr) 325b9e15228SEd Tanous { 326b9e15228SEd Tanous if (!ntpServerObject->empty()) 327b9e15228SEd Tanous { 328ed4de7a8SEd Tanous messages::propertyValueNotInList( 329ed4de7a8SEd Tanous asyncResp->res, *ntpServerObject, 330ed4de7a8SEd Tanous "NTP/NTPServers/" + std::to_string(index)); 331b9e15228SEd Tanous return; 332b9e15228SEd Tanous } 333b9e15228SEd Tanous // Can't retain an item that doesn't exist 334b9e15228SEd Tanous if (currentNtpServer == currentNtpServers.end()) 335b9e15228SEd Tanous { 336ed4de7a8SEd Tanous messages::propertyValueOutOfRange( 337ed4de7a8SEd Tanous asyncResp->res, *ntpServerObject, 338ed4de7a8SEd Tanous "NTP/NTPServers/" + std::to_string(index)); 339b9e15228SEd Tanous 340b9e15228SEd Tanous return; 341b9e15228SEd Tanous } 342b9e15228SEd Tanous // empty objects should leave the NtpServer unmodified 343b9e15228SEd Tanous currentNtpServer++; 344b9e15228SEd Tanous continue; 345b9e15228SEd Tanous } 346b9e15228SEd Tanous 347ed4de7a8SEd Tanous const std::string* ntpServerStr = std::get_if<std::string>(&ntpServer); 348b9e15228SEd Tanous if (ntpServerStr == nullptr) 349b9e15228SEd Tanous { 350ed4de7a8SEd Tanous messages::internalError(asyncResp->res); 351b9e15228SEd Tanous return; 352b9e15228SEd Tanous } 353b9e15228SEd Tanous if (currentNtpServer == currentNtpServers.end()) 354b9e15228SEd Tanous { 355b9e15228SEd Tanous // if we're at the end of the list, append to the end 356b9e15228SEd Tanous currentNtpServers.push_back(*ntpServerStr); 357b9e15228SEd Tanous currentNtpServer = currentNtpServers.end(); 358b9e15228SEd Tanous continue; 359b9e15228SEd Tanous } 360b9e15228SEd Tanous *currentNtpServer = *ntpServerStr; 361b9e15228SEd Tanous currentNtpServer++; 362b9e15228SEd Tanous } 363b9e15228SEd Tanous 364b9e15228SEd Tanous // Any remaining array elements should be removed 365b9e15228SEd Tanous currentNtpServers.erase(currentNtpServer, currentNtpServers.end()); 366287ece64SGeorge Liu 367e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> ethInterfaces = { 368e99073f5SGeorge Liu "xyz.openbmc_project.Network.EthernetInterface"}; 369e99073f5SGeorge Liu dbus::utility::getSubTree( 370e99073f5SGeorge Liu "/xyz/openbmc_project", 0, ethInterfaces, 371b9e15228SEd Tanous [asyncResp, currentNtpServers]( 3722138483cSGeorge Liu const boost::system::error_code& ec, 373b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 3740a052baaSGeorge Liu if (ec) 3750a052baaSGeorge Liu { 37662598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 3770a052baaSGeorge Liu messages::internalError(asyncResp->res); 3780a052baaSGeorge Liu return; 3790a052baaSGeorge Liu } 3800a052baaSGeorge Liu 3810a052baaSGeorge Liu for (const auto& [objectPath, serviceMap] : subtree) 3820a052baaSGeorge Liu { 3830a052baaSGeorge Liu for (const auto& [service, interfaces] : serviceMap) 3840a052baaSGeorge Liu { 3850a052baaSGeorge Liu for (const auto& interface : interfaces) 3860a052baaSGeorge Liu { 3870a052baaSGeorge Liu if (interface != 3880a052baaSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface") 3890a052baaSGeorge Liu { 3900a052baaSGeorge Liu continue; 3910a052baaSGeorge Liu } 3920a052baaSGeorge Liu 393e93abac6SGinu George setDbusProperty(asyncResp, "NTP/NTPServers/", service, 394bd79bce8SPatrick Williams objectPath, interface, 395bd79bce8SPatrick Williams "StaticNTPServers", currentNtpServers); 39620e6ea5dSraviteja-b } 3970a052baaSGeorge Liu } 3980a052baaSGeorge Liu } 399e99073f5SGeorge Liu }); 4000a052baaSGeorge Liu } 40120e6ea5dSraviteja-b 402504af5a0SPatrick Williams inline void handleProtocolEnabled( 403504af5a0SPatrick Williams const bool protocolEnabled, 404e5a99777SAlbert Zhang const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 40569320d54SJiaqing Zhao const std::string& netBasePath) 40667a78d87STom Joseph { 407e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 408e99073f5SGeorge Liu "xyz.openbmc_project.Control.Service.Attributes"}; 409e99073f5SGeorge Liu dbus::utility::getSubTree( 410e99073f5SGeorge Liu "/xyz/openbmc_project/control/service", 0, interfaces, 411e5a99777SAlbert Zhang [protocolEnabled, asyncResp, 4122138483cSGeorge Liu netBasePath](const boost::system::error_code& ec, 413b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 41467a78d87STom Joseph if (ec) 41567a78d87STom Joseph { 41667a78d87STom Joseph messages::internalError(asyncResp->res); 41767a78d87STom Joseph return; 41867a78d87STom Joseph } 41967a78d87STom Joseph 42067a78d87STom Joseph for (const auto& entry : subtree) 42167a78d87STom Joseph { 42218f8f608SEd Tanous if (entry.first.starts_with(netBasePath)) 42367a78d87STom Joseph { 42487c44966SAsmitha Karunanithi setDbusProperty( 425e93abac6SGinu George asyncResp, "IPMI/ProtocolEnabled", 426e93abac6SGinu George entry.second.begin()->first, entry.first, 427bd79bce8SPatrick Williams "xyz.openbmc_project.Control.Service.Attributes", 428bd79bce8SPatrick Williams "Running", protocolEnabled); 42987c44966SAsmitha Karunanithi setDbusProperty( 430e93abac6SGinu George asyncResp, "IPMI/ProtocolEnabled", 431e93abac6SGinu George entry.second.begin()->first, entry.first, 432bd79bce8SPatrick Williams "xyz.openbmc_project.Control.Service.Attributes", 433bd79bce8SPatrick Williams "Enabled", protocolEnabled); 43467a78d87STom Joseph } 43567a78d87STom Joseph } 436e99073f5SGeorge Liu }); 43767a78d87STom Joseph } 43867a78d87STom Joseph 439504af5a0SPatrick Williams inline void getNTPProtocolEnabled( 440504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 4417e860f15SJohn Edward Broadbent { 442deae6a78SEd Tanous dbus::utility::getProperty<bool>( 443deae6a78SEd Tanous "org.freedesktop.timedate1", "/org/freedesktop/timedate1", 444deae6a78SEd Tanous "org.freedesktop.timedate1", "NTP", 4458e157735SEd Tanous [asyncResp](const boost::system::error_code& ec, bool enabled) { 4468b24275dSEd Tanous if (ec) 4477e860f15SJohn Edward Broadbent { 4488e157735SEd Tanous BMCWEB_LOG_WARNING( 4498e157735SEd Tanous "Failed to get NTP status, assuming not supported"); 4507e860f15SJohn Edward Broadbent return; 4517e860f15SJohn Edward Broadbent } 4527e860f15SJohn Edward Broadbent 4538e157735SEd Tanous asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = enabled; 4541e1e598dSJonathan Doman }); 4557e860f15SJohn Edward Broadbent } 4567e860f15SJohn Edward Broadbent 4575c3e9272SAbhishek Patel inline std::string encodeServiceObjectPath(std::string_view serviceName) 45869320d54SJiaqing Zhao { 45969320d54SJiaqing Zhao sdbusplus::message::object_path objPath( 46069320d54SJiaqing Zhao "/xyz/openbmc_project/control/service"); 46169320d54SJiaqing Zhao objPath /= serviceName; 46269320d54SJiaqing Zhao return objPath.str; 46369320d54SJiaqing Zhao } 46469320d54SJiaqing Zhao 465e634b34cSEd Tanous inline void handleManagersNetworkProtocolPatch( 466e634b34cSEd Tanous App& app, const crow::Request& req, 467253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 468253f11b8SEd Tanous const std::string& managerId) 4697e860f15SJohn Edward Broadbent { 4703ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 47145ca1b86SEd Tanous { 47245ca1b86SEd Tanous return; 47345ca1b86SEd Tanous } 474253f11b8SEd Tanous 475253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 476253f11b8SEd Tanous { 477253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 478253f11b8SEd Tanous return; 479253f11b8SEd Tanous } 480253f11b8SEd Tanous 481501be32bSraviteja-b std::optional<std::string> newHostName; 482ed4de7a8SEd Tanous 483ed4de7a8SEd Tanous std::optional<std::vector<IpAddress>> ntpServerObjects; 4845f4c798dSJiaqing Zhao std::optional<bool> ntpEnabled; 4855f4c798dSJiaqing Zhao std::optional<bool> ipmiEnabled; 4865f4c798dSJiaqing Zhao std::optional<bool> sshEnabled; 487501be32bSraviteja-b 4885f4c798dSJiaqing Zhao if (!json_util::readJsonPatch( 489afc474aeSMyung Bae req, asyncResp->res, // 490afc474aeSMyung Bae "HostName", newHostName, // 491afc474aeSMyung Bae "NTP/NTPServers", ntpServerObjects, // 492afc474aeSMyung Bae "NTP/ProtocolEnabled", ntpEnabled, // 493afc474aeSMyung Bae "IPMI/ProtocolEnabled", ipmiEnabled, // 494afc474aeSMyung Bae "SSH/ProtocolEnabled", sshEnabled // 495afc474aeSMyung Bae )) 496501be32bSraviteja-b { 497501be32bSraviteja-b return; 498501be32bSraviteja-b } 499cf05f9dcSJohnathan Mantey 5008d1b46d7Szhanghch05 asyncResp->res.result(boost::beast::http::status::no_content); 501501be32bSraviteja-b if (newHostName) 502501be32bSraviteja-b { 5032db77d34SJohnathan Mantey messages::propertyNotWritable(asyncResp->res, "HostName"); 50444fad2aaSEd Tanous return; 505cf05f9dcSJohnathan Mantey } 506cf05f9dcSJohnathan Mantey 50720e6ea5dSraviteja-b if (ntpEnabled) 50820e6ea5dSraviteja-b { 5098e157735SEd Tanous handleNTPProtocolEnabled(asyncResp, *ntpEnabled); 51020e6ea5dSraviteja-b } 511b9e15228SEd Tanous if (ntpServerObjects) 51220e6ea5dSraviteja-b { 513b9e15228SEd Tanous getEthernetIfaceData( 514b9e15228SEd Tanous [asyncResp, ntpServerObjects]( 515e634b34cSEd Tanous const bool success, std::vector<std::string>& currentNtpServers, 5160eebcefbSJishnu CM const std::vector<std::string>& /*dynamicNtpServers*/, 517b9e15228SEd Tanous const std::vector<std::string>& /*domainNames*/) { 518b9e15228SEd Tanous if (!success) 519b9e15228SEd Tanous { 520b9e15228SEd Tanous messages::internalError(asyncResp->res); 521b9e15228SEd Tanous return; 522b9e15228SEd Tanous } 523b9e15228SEd Tanous handleNTPServersPatch(asyncResp, *ntpServerObjects, 524b9e15228SEd Tanous std::move(currentNtpServers)); 525b9e15228SEd Tanous }); 52620e6ea5dSraviteja-b } 52767a78d87STom Joseph 5285f4c798dSJiaqing Zhao if (ipmiEnabled) 52967a78d87STom Joseph { 530e5a99777SAlbert Zhang handleProtocolEnabled( 5315f4c798dSJiaqing Zhao *ipmiEnabled, asyncResp, 53269320d54SJiaqing Zhao encodeServiceObjectPath(std::string(ipmiServiceName) + '@')); 533e5a99777SAlbert Zhang } 534e5a99777SAlbert Zhang 5355f4c798dSJiaqing Zhao if (sshEnabled) 536e5a99777SAlbert Zhang { 53769320d54SJiaqing Zhao handleProtocolEnabled(*sshEnabled, asyncResp, 53869320d54SJiaqing Zhao encodeServiceObjectPath(sshServiceName)); 53967a78d87STom Joseph } 540e634b34cSEd Tanous } 541e634b34cSEd Tanous 542af20dd1cSEd Tanous inline void handleManagersNetworkProtocolHead( 543e634b34cSEd Tanous App& app, const crow::Request& req, 544253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 545253f11b8SEd Tanous const std::string& managerId) 546e634b34cSEd Tanous { 547e634b34cSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 548e634b34cSEd Tanous { 549e634b34cSEd Tanous return; 550e634b34cSEd Tanous } 551af20dd1cSEd Tanous asyncResp->res.addHeader( 552af20dd1cSEd Tanous boost::beast::http::field::link, 553af20dd1cSEd Tanous "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/ManagerNetworkProtocol.json>; rel=describedby"); 554253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 555253f11b8SEd Tanous { 556253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 557253f11b8SEd Tanous return; 558253f11b8SEd Tanous } 559af20dd1cSEd Tanous } 560af20dd1cSEd Tanous 561af20dd1cSEd Tanous inline void handleManagersNetworkProtocolGet( 562af20dd1cSEd Tanous App& app, const crow::Request& req, 563253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 564253f11b8SEd Tanous const std::string& managerId) 565af20dd1cSEd Tanous { 566253f11b8SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 567253f11b8SEd Tanous { 568253f11b8SEd Tanous return; 569253f11b8SEd Tanous } 570253f11b8SEd Tanous asyncResp->res.addHeader( 571253f11b8SEd Tanous boost::beast::http::field::link, 572253f11b8SEd Tanous "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/ManagerNetworkProtocol.json>; rel=describedby"); 573253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 574253f11b8SEd Tanous { 575253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 576253f11b8SEd Tanous return; 577253f11b8SEd Tanous } 578253f11b8SEd Tanous 579e634b34cSEd Tanous getNetworkData(asyncResp, req); 580e634b34cSEd Tanous } 581e634b34cSEd Tanous 582e634b34cSEd Tanous inline void requestRoutesNetworkProtocol(App& app) 583e634b34cSEd Tanous { 584253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/NetworkProtocol/") 585e634b34cSEd Tanous .privileges(redfish::privileges::patchManagerNetworkProtocol) 586e634b34cSEd Tanous .methods(boost::beast::http::verb::patch)( 587e634b34cSEd Tanous std::bind_front(handleManagersNetworkProtocolPatch, std::ref(app))); 5887e860f15SJohn Edward Broadbent 589253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/NetworkProtocol/") 590e9f71672SEd Tanous .privileges(redfish::privileges::headManagerNetworkProtocol) 591e9f71672SEd Tanous .methods(boost::beast::http::verb::head)( 592af20dd1cSEd Tanous std::bind_front(handleManagersNetworkProtocolHead, std::ref(app))); 593e9f71672SEd Tanous 594253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/NetworkProtocol/") 595ed398213SEd Tanous .privileges(redfish::privileges::getManagerNetworkProtocol) 5967e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 597e634b34cSEd Tanous std::bind_front(handleManagersNetworkProtocolGet, std::ref(app))); 598cf05f9dcSJohnathan Mantey } 59970141561SBorawski.Lukasz 60070141561SBorawski.Lukasz } // namespace redfish 601