170141561SBorawski.Lukasz /* 26be832e2SEd Tanous Copyright (c) 2018 Intel Corporation 36be832e2SEd Tanous 46be832e2SEd Tanous Licensed under the Apache License, Version 2.0 (the "License"); 56be832e2SEd Tanous you may not use this file except in compliance with the License. 66be832e2SEd Tanous You may obtain a copy of the License at 76be832e2SEd Tanous 86be832e2SEd Tanous http://www.apache.org/licenses/LICENSE-2.0 96be832e2SEd Tanous 106be832e2SEd Tanous Unless required by applicable law or agreed to in writing, software 116be832e2SEd Tanous distributed under the License is distributed on an "AS IS" BASIS, 126be832e2SEd Tanous WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136be832e2SEd Tanous See the License for the specific language governing permissions and 146be832e2SEd Tanous 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" 21539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 223ccb3adbSEd Tanous #include "query.hpp" 23b4bec66bSAbhishek Patel #include "redfish_util.hpp" 243ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 253ccb3adbSEd Tanous #include "utils/json_utils.hpp" 263ccb3adbSEd Tanous #include "utils/stl_utils.hpp" 2770141561SBorawski.Lukasz 28e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 29253f11b8SEd Tanous #include <boost/url/format.hpp> 301e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp> 311214b7e7SGunnar Mills 32e99073f5SGeorge Liu #include <array> 331214b7e7SGunnar Mills #include <optional> 34e99073f5SGeorge Liu #include <string_view> 35abf2add6SEd Tanous #include <variant> 360eebcefbSJishnu CM #include <vector> 375f4c798dSJiaqing Zhao 381abe55efSEd Tanous namespace redfish 391abe55efSEd Tanous { 4070141561SBorawski.Lukasz 417e860f15SJohn Edward Broadbent void getNTPProtocolEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp); 427e860f15SJohn Edward Broadbent std::string getHostName(); 437e860f15SJohn Edward Broadbent 445c3e9272SAbhishek Patel static constexpr std::string_view sshServiceName = "dropbear"; 455c3e9272SAbhishek Patel static constexpr std::string_view httpsServiceName = "bmcweb"; 465c3e9272SAbhishek Patel static constexpr std::string_view ipmiServiceName = "phosphor-ipmi-net"; 475c3e9272SAbhishek Patel 485c3e9272SAbhishek Patel // Mapping from Redfish NetworkProtocol key name to backend service that hosts 495c3e9272SAbhishek Patel // that protocol. 505c3e9272SAbhishek Patel static constexpr std::array<std::pair<std::string_view, std::string_view>, 3> 515c3e9272SAbhishek Patel networkProtocolToDbus = {{{"SSH", sshServiceName}, 5269320d54SJiaqing Zhao {"HTTPS", httpsServiceName}, 5369320d54SJiaqing Zhao {"IPMI", ipmiServiceName}}}; 543a8a0088SKowalski, Kamil 55711ac7a9SEd Tanous inline void extractNTPServersAndDomainNamesData( 56711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 570eebcefbSJishnu CM std::vector<std::string>& ntpData, std::vector<std::string>& dynamicNtpData, 580eebcefbSJishnu CM std::vector<std::string>& dnData) 5920e6ea5dSraviteja-b { 6081ce609eSEd Tanous for (const auto& obj : dbusData) 6120e6ea5dSraviteja-b { 6220e6ea5dSraviteja-b for (const auto& ifacePair : obj.second) 6320e6ea5dSraviteja-b { 640a052baaSGeorge Liu if (ifacePair.first != 6520e6ea5dSraviteja-b "xyz.openbmc_project.Network.EthernetInterface") 6620e6ea5dSraviteja-b { 670a052baaSGeorge Liu continue; 680a052baaSGeorge Liu } 690a052baaSGeorge Liu 7020e6ea5dSraviteja-b for (const auto& propertyPair : ifacePair.second) 7120e6ea5dSraviteja-b { 72fcd2682aSEd Tanous if (propertyPair.first == "StaticNTPServers") 7320e6ea5dSraviteja-b { 7420e6ea5dSraviteja-b const std::vector<std::string>* ntpServers = 758d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 7620e6ea5dSraviteja-b &propertyPair.second); 7720e6ea5dSraviteja-b if (ntpServers != nullptr) 7820e6ea5dSraviteja-b { 79c251fe81SJian Zhang ntpData.insert(ntpData.end(), ntpServers->begin(), 80c251fe81SJian Zhang ntpServers->end()); 8120e6ea5dSraviteja-b } 8220e6ea5dSraviteja-b } 830eebcefbSJishnu CM else if (propertyPair.first == "NTPServers") 840eebcefbSJishnu CM { 850eebcefbSJishnu CM const std::vector<std::string>* dynamicNtpServers = 860eebcefbSJishnu CM std::get_if<std::vector<std::string>>( 870eebcefbSJishnu CM &propertyPair.second); 880eebcefbSJishnu CM if (dynamicNtpServers != nullptr) 890eebcefbSJishnu CM { 900eebcefbSJishnu CM dynamicNtpData = *dynamicNtpServers; 910eebcefbSJishnu CM } 920eebcefbSJishnu CM } 93d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 94d24bfc7aSJennifer Lee { 95d24bfc7aSJennifer Lee const std::vector<std::string>* domainNames = 968d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 97d24bfc7aSJennifer Lee &propertyPair.second); 98d24bfc7aSJennifer Lee if (domainNames != nullptr) 99d24bfc7aSJennifer Lee { 100c251fe81SJian Zhang dnData.insert(dnData.end(), domainNames->begin(), 101c251fe81SJian Zhang domainNames->end()); 102d24bfc7aSJennifer Lee } 103d24bfc7aSJennifer Lee } 10420e6ea5dSraviteja-b } 10520e6ea5dSraviteja-b } 10620e6ea5dSraviteja-b } 1070225b87bSEd Tanous stl_utils::removeDuplicate(ntpData); 108c251fe81SJian Zhang stl_utils::removeDuplicate(dnData); 10920e6ea5dSraviteja-b } 11020e6ea5dSraviteja-b 11120e6ea5dSraviteja-b template <typename CallbackFunc> 11220e6ea5dSraviteja-b void getEthernetIfaceData(CallbackFunc&& callback) 11320e6ea5dSraviteja-b { 1145eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1155eb468daSGeorge Liu dbus::utility::getManagedObjects( 1165eb468daSGeorge Liu "xyz.openbmc_project.Network", path, 1178cb2c024SEd Tanous [callback = std::forward<CallbackFunc>(callback)]( 1188b24275dSEd Tanous const boost::system::error_code& ec, 119711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData) { 12020e6ea5dSraviteja-b std::vector<std::string> ntpServers; 1210eebcefbSJishnu CM std::vector<std::string> dynamicNtpServers; 122d24bfc7aSJennifer Lee std::vector<std::string> domainNames; 12320e6ea5dSraviteja-b 1248b24275dSEd Tanous if (ec) 12520e6ea5dSraviteja-b { 1260eebcefbSJishnu CM callback(false, ntpServers, dynamicNtpServers, domainNames); 12720e6ea5dSraviteja-b return; 12820e6ea5dSraviteja-b } 12920e6ea5dSraviteja-b 130bd79bce8SPatrick Williams extractNTPServersAndDomainNamesData(dbusData, ntpServers, 1310eebcefbSJishnu CM dynamicNtpServers, domainNames); 13220e6ea5dSraviteja-b 1330eebcefbSJishnu CM callback(true, ntpServers, dynamicNtpServers, domainNames); 1345eb468daSGeorge Liu }); 135271584abSEd Tanous } 13620e6ea5dSraviteja-b 1375c3e9272SAbhishek Patel inline void afterNetworkPortRequest( 1385c3e9272SAbhishek Patel const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1395c3e9272SAbhishek Patel const boost::system::error_code& ec, 1405c3e9272SAbhishek Patel const std::vector<std::tuple<std::string, std::string, bool>>& socketData) 1415c3e9272SAbhishek Patel { 1425c3e9272SAbhishek Patel if (ec) 1435c3e9272SAbhishek Patel { 1445c3e9272SAbhishek Patel messages::internalError(asyncResp->res); 1455c3e9272SAbhishek Patel return; 1465c3e9272SAbhishek Patel } 1475c3e9272SAbhishek Patel for (const auto& data : socketData) 1485c3e9272SAbhishek Patel { 1495c3e9272SAbhishek Patel const std::string& socketPath = get<0>(data); 1505c3e9272SAbhishek Patel const std::string& protocolName = get<1>(data); 1515c3e9272SAbhishek Patel bool isProtocolEnabled = get<2>(data); 1525c3e9272SAbhishek Patel 1535c3e9272SAbhishek Patel asyncResp->res.jsonValue[protocolName]["ProtocolEnabled"] = 1545c3e9272SAbhishek Patel isProtocolEnabled; 1555c3e9272SAbhishek Patel asyncResp->res.jsonValue[protocolName]["Port"] = nullptr; 1565c3e9272SAbhishek Patel getPortNumber(socketPath, [asyncResp, protocolName]( 1575c3e9272SAbhishek Patel const boost::system::error_code& ec2, 1585c3e9272SAbhishek Patel int portNumber) { 1595c3e9272SAbhishek Patel if (ec2) 1605c3e9272SAbhishek Patel { 1615c3e9272SAbhishek Patel messages::internalError(asyncResp->res); 1625c3e9272SAbhishek Patel return; 1635c3e9272SAbhishek Patel } 1645c3e9272SAbhishek Patel asyncResp->res.jsonValue[protocolName]["Port"] = portNumber; 1655c3e9272SAbhishek Patel }); 1665c3e9272SAbhishek Patel } 1675c3e9272SAbhishek Patel } 1685c3e9272SAbhishek Patel 1694f48d5f6SEd Tanous inline void getNetworkData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 17072048780SAbhishek Patel const crow::Request& req) 1711abe55efSEd Tanous { 1723e72c202SNinad Palsule if (req.session == nullptr) 1733e72c202SNinad Palsule { 1743e72c202SNinad Palsule messages::internalError(asyncResp->res); 1753e72c202SNinad Palsule return; 1763e72c202SNinad Palsule } 1773e72c202SNinad Palsule 178e9f71672SEd Tanous asyncResp->res.addHeader( 179e9f71672SEd Tanous boost::beast::http::field::link, 180e9f71672SEd Tanous "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/NetworkProtocol.json>; rel=describedby"); 1810f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1820eebcefbSJishnu CM "#ManagerNetworkProtocol.v1_9_0.ManagerNetworkProtocol"; 1830f74e643SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 184253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/NetworkProtocol", 185253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 1860f74e643SEd Tanous asyncResp->res.jsonValue["Id"] = "NetworkProtocol"; 1870f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Network Protocol"; 1880f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = "Manager Network Service"; 189539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK; 190539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["HealthRollup"] = resource::Health::OK; 191539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled; 1920f74e643SEd Tanous 19361932318SXiaochao Ma // HTTP is Mandatory attribute as per OCP Baseline Profile - v1.0.0, 194818ea7b8SJoshi-Mansi // but from security perspective it is not recommended to use. 195818ea7b8SJoshi-Mansi // Hence using protocolEnabled as false to make it OCP and security-wise 196818ea7b8SJoshi-Mansi // compliant 1975c3e9272SAbhishek Patel asyncResp->res.jsonValue["HTTP"]["Port"] = nullptr; 198818ea7b8SJoshi-Mansi asyncResp->res.jsonValue["HTTP"]["ProtocolEnabled"] = false; 199818ea7b8SJoshi-Mansi 2001ee2db7fSAndrew Geissler // The ProtocolEnabled of the following protocols is determined by 2011ee2db7fSAndrew Geissler // inspecting the state of associated systemd sockets. If these protocols 2021ee2db7fSAndrew Geissler // have been disabled, then the systemd socket unit files will not be found 2031ee2db7fSAndrew Geissler // and the protocols will not be returned in this Redfish query. Set some 2041ee2db7fSAndrew Geissler // defaults to ensure something is always returned. 2051ee2db7fSAndrew Geissler for (const auto& nwkProtocol : networkProtocolToDbus) 2061ee2db7fSAndrew Geissler { 2071ee2db7fSAndrew Geissler asyncResp->res.jsonValue[nwkProtocol.first]["Port"] = nullptr; 2081ee2db7fSAndrew Geissler asyncResp->res.jsonValue[nwkProtocol.first]["ProtocolEnabled"] = false; 2091ee2db7fSAndrew Geissler } 2101ee2db7fSAndrew Geissler 211d24bfc7aSJennifer Lee std::string hostName = getHostName(); 212d24bfc7aSJennifer Lee 213d24bfc7aSJennifer Lee asyncResp->res.jsonValue["HostName"] = hostName; 2143a8a0088SKowalski, Kamil 21520e6ea5dSraviteja-b getNTPProtocolEnabled(asyncResp); 21620e6ea5dSraviteja-b 217bd79bce8SPatrick Williams getEthernetIfaceData([hostName, asyncResp]( 218bd79bce8SPatrick Williams const bool& success, 21902cad96eSEd Tanous const std::vector<std::string>& ntpServers, 2200eebcefbSJishnu CM const std::vector<std::string>& dynamicNtpServers, 221d24bfc7aSJennifer Lee const std::vector<std::string>& domainNames) { 22220e6ea5dSraviteja-b if (!success) 22320e6ea5dSraviteja-b { 2240a052baaSGeorge Liu messages::resourceNotFound(asyncResp->res, "ManagerNetworkProtocol", 2250a052baaSGeorge Liu "NetworkProtocol"); 22620e6ea5dSraviteja-b return; 22720e6ea5dSraviteja-b } 22820e6ea5dSraviteja-b asyncResp->res.jsonValue["NTP"]["NTPServers"] = ntpServers; 2290eebcefbSJishnu CM asyncResp->res.jsonValue["NTP"]["NetworkSuppliedServers"] = 2300eebcefbSJishnu CM dynamicNtpServers; 23126f6976fSEd Tanous if (!hostName.empty()) 232d24bfc7aSJennifer Lee { 233f23b7296SEd Tanous std::string fqdn = hostName; 23426f6976fSEd Tanous if (!domainNames.empty()) 235d24bfc7aSJennifer Lee { 236f23b7296SEd Tanous fqdn += "."; 237f23b7296SEd Tanous fqdn += domainNames[0]; 238d24bfc7aSJennifer Lee } 2392c70f800SEd Tanous asyncResp->res.jsonValue["FQDN"] = std::move(fqdn); 240d24bfc7aSJennifer Lee } 24120e6ea5dSraviteja-b }); 24220e6ea5dSraviteja-b 24372048780SAbhishek Patel Privileges effectiveUserPrivileges = 2443e72c202SNinad Palsule redfish::getUserPrivileges(*req.session); 24572048780SAbhishek Patel 24672048780SAbhishek Patel // /redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates is 24772048780SAbhishek Patel // something only ConfigureManager can access then only display when 24872048780SAbhishek Patel // the user has permissions ConfigureManager 24972048780SAbhishek Patel if (isOperationAllowedWithPrivileges({{"ConfigureManager"}}, 25072048780SAbhishek Patel effectiveUserPrivileges)) 25172048780SAbhishek Patel { 2521476687dSEd Tanous asyncResp->res.jsonValue["HTTPS"]["Certificates"]["@odata.id"] = 253253f11b8SEd Tanous boost::urls::format( 254253f11b8SEd Tanous "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates", 255253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 25670141561SBorawski.Lukasz } 25770141561SBorawski.Lukasz 2585c3e9272SAbhishek Patel getPortStatusAndPath(std::span(networkProtocolToDbus), 2595c3e9272SAbhishek Patel std::bind_front(afterNetworkPortRequest, asyncResp)); 260b4bec66bSAbhishek Patel } // namespace redfish 261501be32bSraviteja-b 2628e157735SEd Tanous inline void afterSetNTP(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2638e157735SEd Tanous const boost::system::error_code& ec) 26420e6ea5dSraviteja-b { 2658e157735SEd Tanous if (ec) 26620e6ea5dSraviteja-b { 2678e157735SEd Tanous BMCWEB_LOG_DEBUG("Failed to set elapsed time. DBUS response error {}", 2688e157735SEd Tanous ec); 2698e157735SEd Tanous messages::internalError(asyncResp->res); 2708e157735SEd Tanous return; 27120e6ea5dSraviteja-b } 2728e157735SEd Tanous asyncResp->res.result(boost::beast::http::status::no_content); 27320e6ea5dSraviteja-b } 27420e6ea5dSraviteja-b 2758e157735SEd Tanous inline void handleNTPProtocolEnabled( 2768e157735SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool ntpEnabled) 2778e157735SEd Tanous { 2788e157735SEd Tanous bool interactive = false; 2798e157735SEd Tanous auto callback = [asyncResp](const boost::system::error_code& ec) { 2808e157735SEd Tanous afterSetNTP(asyncResp, ec); 2818e157735SEd Tanous }; 2828e157735SEd Tanous crow::connections::systemBus->async_method_call( 2838e157735SEd Tanous std::move(callback), "org.freedesktop.timedate1", 2848e157735SEd Tanous "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "SetNTP", 2858e157735SEd Tanous ntpEnabled, interactive); 28620e6ea5dSraviteja-b } 28720e6ea5dSraviteja-b 288ed4de7a8SEd Tanous // Redfish states that ip addresses can be 289ed4de7a8SEd Tanous // string, to set a value 290ed4de7a8SEd Tanous // null, to delete the value 291ed4de7a8SEd Tanous // object_t, empty json object, to ignore the value 292ed4de7a8SEd Tanous using IpAddress = 293ed4de7a8SEd Tanous std::variant<std::string, nlohmann::json::object_t, std::nullptr_t>; 294ed4de7a8SEd Tanous 2954f48d5f6SEd Tanous inline void 296287ece64SGeorge Liu handleNTPServersPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 297ed4de7a8SEd Tanous const std::vector<IpAddress>& ntpServerObjects, 298b9e15228SEd Tanous std::vector<std::string> currentNtpServers) 29920e6ea5dSraviteja-b { 300b9e15228SEd Tanous std::vector<std::string>::iterator currentNtpServer = 301b9e15228SEd Tanous currentNtpServers.begin(); 302b9e15228SEd Tanous for (size_t index = 0; index < ntpServerObjects.size(); index++) 303287ece64SGeorge Liu { 304ed4de7a8SEd Tanous const IpAddress& ntpServer = ntpServerObjects[index]; 305ed4de7a8SEd Tanous if (std::holds_alternative<std::nullptr_t>(ntpServer)) 306b9e15228SEd Tanous { 307b9e15228SEd Tanous // Can't delete an item that doesn't exist 308b9e15228SEd Tanous if (currentNtpServer == currentNtpServers.end()) 309b9e15228SEd Tanous { 310bd79bce8SPatrick Williams messages::propertyValueNotInList( 311bd79bce8SPatrick Williams asyncResp->res, "null", 312bd79bce8SPatrick Williams "NTP/NTPServers/" + std::to_string(index)); 313b9e15228SEd Tanous 314287ece64SGeorge Liu return; 315287ece64SGeorge Liu } 316b9e15228SEd Tanous currentNtpServer = currentNtpServers.erase(currentNtpServer); 317b9e15228SEd Tanous continue; 318b9e15228SEd Tanous } 319b9e15228SEd Tanous const nlohmann::json::object_t* ntpServerObject = 320ed4de7a8SEd Tanous std::get_if<nlohmann::json::object_t>(&ntpServer); 321b9e15228SEd Tanous if (ntpServerObject != nullptr) 322b9e15228SEd Tanous { 323b9e15228SEd Tanous if (!ntpServerObject->empty()) 324b9e15228SEd Tanous { 325ed4de7a8SEd Tanous messages::propertyValueNotInList( 326ed4de7a8SEd Tanous asyncResp->res, *ntpServerObject, 327ed4de7a8SEd Tanous "NTP/NTPServers/" + std::to_string(index)); 328b9e15228SEd Tanous return; 329b9e15228SEd Tanous } 330b9e15228SEd Tanous // Can't retain an item that doesn't exist 331b9e15228SEd Tanous if (currentNtpServer == currentNtpServers.end()) 332b9e15228SEd Tanous { 333ed4de7a8SEd Tanous messages::propertyValueOutOfRange( 334ed4de7a8SEd Tanous asyncResp->res, *ntpServerObject, 335ed4de7a8SEd Tanous "NTP/NTPServers/" + std::to_string(index)); 336b9e15228SEd Tanous 337b9e15228SEd Tanous return; 338b9e15228SEd Tanous } 339b9e15228SEd Tanous // empty objects should leave the NtpServer unmodified 340b9e15228SEd Tanous currentNtpServer++; 341b9e15228SEd Tanous continue; 342b9e15228SEd Tanous } 343b9e15228SEd Tanous 344ed4de7a8SEd Tanous const std::string* ntpServerStr = std::get_if<std::string>(&ntpServer); 345b9e15228SEd Tanous if (ntpServerStr == nullptr) 346b9e15228SEd Tanous { 347ed4de7a8SEd Tanous messages::internalError(asyncResp->res); 348b9e15228SEd Tanous return; 349b9e15228SEd Tanous } 350b9e15228SEd Tanous if (currentNtpServer == currentNtpServers.end()) 351b9e15228SEd Tanous { 352b9e15228SEd Tanous // if we're at the end of the list, append to the end 353b9e15228SEd Tanous currentNtpServers.push_back(*ntpServerStr); 354b9e15228SEd Tanous currentNtpServer = currentNtpServers.end(); 355b9e15228SEd Tanous continue; 356b9e15228SEd Tanous } 357b9e15228SEd Tanous *currentNtpServer = *ntpServerStr; 358b9e15228SEd Tanous currentNtpServer++; 359b9e15228SEd Tanous } 360b9e15228SEd Tanous 361b9e15228SEd Tanous // Any remaining array elements should be removed 362b9e15228SEd Tanous currentNtpServers.erase(currentNtpServer, currentNtpServers.end()); 363287ece64SGeorge Liu 364e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> ethInterfaces = { 365e99073f5SGeorge Liu "xyz.openbmc_project.Network.EthernetInterface"}; 366e99073f5SGeorge Liu dbus::utility::getSubTree( 367e99073f5SGeorge Liu "/xyz/openbmc_project", 0, ethInterfaces, 368b9e15228SEd Tanous [asyncResp, currentNtpServers]( 3692138483cSGeorge Liu const boost::system::error_code& ec, 370b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 3710a052baaSGeorge Liu if (ec) 3720a052baaSGeorge Liu { 37362598e31SEd Tanous BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message()); 3740a052baaSGeorge Liu messages::internalError(asyncResp->res); 3750a052baaSGeorge Liu return; 3760a052baaSGeorge Liu } 3770a052baaSGeorge Liu 3780a052baaSGeorge Liu for (const auto& [objectPath, serviceMap] : subtree) 3790a052baaSGeorge Liu { 3800a052baaSGeorge Liu for (const auto& [service, interfaces] : serviceMap) 3810a052baaSGeorge Liu { 3820a052baaSGeorge Liu for (const auto& interface : interfaces) 3830a052baaSGeorge Liu { 3840a052baaSGeorge Liu if (interface != 3850a052baaSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface") 3860a052baaSGeorge Liu { 3870a052baaSGeorge Liu continue; 3880a052baaSGeorge Liu } 3890a052baaSGeorge Liu 390e93abac6SGinu George setDbusProperty(asyncResp, "NTP/NTPServers/", service, 391bd79bce8SPatrick Williams objectPath, interface, 392bd79bce8SPatrick Williams "StaticNTPServers", currentNtpServers); 39320e6ea5dSraviteja-b } 3940a052baaSGeorge Liu } 3950a052baaSGeorge Liu } 396e99073f5SGeorge Liu }); 3970a052baaSGeorge Liu } 39820e6ea5dSraviteja-b 3994f48d5f6SEd Tanous inline void 4004f48d5f6SEd Tanous handleProtocolEnabled(const bool protocolEnabled, 401e5a99777SAlbert Zhang const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 40269320d54SJiaqing Zhao const std::string& netBasePath) 40367a78d87STom Joseph { 404e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 405e99073f5SGeorge Liu "xyz.openbmc_project.Control.Service.Attributes"}; 406e99073f5SGeorge Liu dbus::utility::getSubTree( 407e99073f5SGeorge Liu "/xyz/openbmc_project/control/service", 0, interfaces, 408e5a99777SAlbert Zhang [protocolEnabled, asyncResp, 4092138483cSGeorge Liu netBasePath](const boost::system::error_code& ec, 410b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 41167a78d87STom Joseph if (ec) 41267a78d87STom Joseph { 41367a78d87STom Joseph messages::internalError(asyncResp->res); 41467a78d87STom Joseph return; 41567a78d87STom Joseph } 41667a78d87STom Joseph 41767a78d87STom Joseph for (const auto& entry : subtree) 41867a78d87STom Joseph { 41918f8f608SEd Tanous if (entry.first.starts_with(netBasePath)) 42067a78d87STom Joseph { 42187c44966SAsmitha Karunanithi setDbusProperty( 422e93abac6SGinu George asyncResp, "IPMI/ProtocolEnabled", 423e93abac6SGinu George entry.second.begin()->first, entry.first, 424bd79bce8SPatrick Williams "xyz.openbmc_project.Control.Service.Attributes", 425bd79bce8SPatrick Williams "Running", protocolEnabled); 42687c44966SAsmitha Karunanithi setDbusProperty( 427e93abac6SGinu George asyncResp, "IPMI/ProtocolEnabled", 428e93abac6SGinu George entry.second.begin()->first, entry.first, 429bd79bce8SPatrick Williams "xyz.openbmc_project.Control.Service.Attributes", 430bd79bce8SPatrick Williams "Enabled", protocolEnabled); 43167a78d87STom Joseph } 43267a78d87STom Joseph } 433e99073f5SGeorge Liu }); 43467a78d87STom Joseph } 43567a78d87STom Joseph 4364f48d5f6SEd Tanous inline std::string getHostName() 437501be32bSraviteja-b { 4387e860f15SJohn Edward Broadbent std::string hostName; 4398d1b46d7Szhanghch05 440d3a9e084SEd Tanous std::array<char, HOST_NAME_MAX> hostNameCStr{}; 4417e860f15SJohn Edward Broadbent if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0) 4427e860f15SJohn Edward Broadbent { 4437e860f15SJohn Edward Broadbent hostName = hostNameCStr.data(); 4447e860f15SJohn Edward Broadbent } 4457e860f15SJohn Edward Broadbent return hostName; 4467e860f15SJohn Edward Broadbent } 4477e860f15SJohn Edward Broadbent 4484f48d5f6SEd Tanous inline void 4494f48d5f6SEd Tanous getNTPProtocolEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 4507e860f15SJohn Edward Broadbent { 4518e157735SEd Tanous sdbusplus::asio::getProperty<bool>( 4528e157735SEd Tanous *crow::connections::systemBus, "org.freedesktop.timedate1", 4538e157735SEd Tanous "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", 4548e157735SEd Tanous [asyncResp](const boost::system::error_code& ec, bool enabled) { 4558b24275dSEd Tanous if (ec) 4567e860f15SJohn Edward Broadbent { 4578e157735SEd Tanous BMCWEB_LOG_WARNING( 4588e157735SEd Tanous "Failed to get NTP status, assuming not supported"); 4597e860f15SJohn Edward Broadbent return; 4607e860f15SJohn Edward Broadbent } 4617e860f15SJohn Edward Broadbent 4628e157735SEd Tanous asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = enabled; 4631e1e598dSJonathan Doman }); 4647e860f15SJohn Edward Broadbent } 4657e860f15SJohn Edward Broadbent 4665c3e9272SAbhishek Patel inline std::string encodeServiceObjectPath(std::string_view serviceName) 46769320d54SJiaqing Zhao { 46869320d54SJiaqing Zhao sdbusplus::message::object_path objPath( 46969320d54SJiaqing Zhao "/xyz/openbmc_project/control/service"); 47069320d54SJiaqing Zhao objPath /= serviceName; 47169320d54SJiaqing Zhao return objPath.str; 47269320d54SJiaqing Zhao } 47369320d54SJiaqing Zhao 4740f55d946SEd Tanous inline void handleBmcNetworkProtocolHead( 475e9f71672SEd Tanous crow::App& app, const crow::Request& req, 476e9f71672SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 477e9f71672SEd Tanous { 478e9f71672SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 479e9f71672SEd Tanous { 480e9f71672SEd Tanous return; 481e9f71672SEd Tanous } 482e9f71672SEd Tanous asyncResp->res.addHeader( 483e9f71672SEd Tanous boost::beast::http::field::link, 484e9f71672SEd Tanous "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/ManagerNetworkProtocol.json>; rel=describedby"); 485e9f71672SEd Tanous } 486e9f71672SEd Tanous 487e634b34cSEd Tanous inline void handleManagersNetworkProtocolPatch( 488e634b34cSEd Tanous App& app, const crow::Request& req, 489253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 490253f11b8SEd Tanous const std::string& managerId) 4917e860f15SJohn Edward Broadbent { 4923ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 49345ca1b86SEd Tanous { 49445ca1b86SEd Tanous return; 49545ca1b86SEd Tanous } 496253f11b8SEd Tanous 497253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 498253f11b8SEd Tanous { 499253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 500253f11b8SEd Tanous return; 501253f11b8SEd Tanous } 502253f11b8SEd Tanous 503501be32bSraviteja-b std::optional<std::string> newHostName; 504ed4de7a8SEd Tanous 505ed4de7a8SEd Tanous std::optional<std::vector<IpAddress>> ntpServerObjects; 5065f4c798dSJiaqing Zhao std::optional<bool> ntpEnabled; 5075f4c798dSJiaqing Zhao std::optional<bool> ipmiEnabled; 5085f4c798dSJiaqing Zhao std::optional<bool> sshEnabled; 509501be32bSraviteja-b 5105f4c798dSJiaqing Zhao if (!json_util::readJsonPatch( 511*afc474aeSMyung Bae req, asyncResp->res, // 512*afc474aeSMyung Bae "HostName", newHostName, // 513*afc474aeSMyung Bae "NTP/NTPServers", ntpServerObjects, // 514*afc474aeSMyung Bae "NTP/ProtocolEnabled", ntpEnabled, // 515*afc474aeSMyung Bae "IPMI/ProtocolEnabled", ipmiEnabled, // 516*afc474aeSMyung Bae "SSH/ProtocolEnabled", sshEnabled // 517*afc474aeSMyung Bae )) 518501be32bSraviteja-b { 519501be32bSraviteja-b return; 520501be32bSraviteja-b } 521cf05f9dcSJohnathan Mantey 5228d1b46d7Szhanghch05 asyncResp->res.result(boost::beast::http::status::no_content); 523501be32bSraviteja-b if (newHostName) 524501be32bSraviteja-b { 5252db77d34SJohnathan Mantey messages::propertyNotWritable(asyncResp->res, "HostName"); 52644fad2aaSEd Tanous return; 527cf05f9dcSJohnathan Mantey } 528cf05f9dcSJohnathan Mantey 52920e6ea5dSraviteja-b if (ntpEnabled) 53020e6ea5dSraviteja-b { 5318e157735SEd Tanous handleNTPProtocolEnabled(asyncResp, *ntpEnabled); 53220e6ea5dSraviteja-b } 533b9e15228SEd Tanous if (ntpServerObjects) 53420e6ea5dSraviteja-b { 535b9e15228SEd Tanous getEthernetIfaceData( 536b9e15228SEd Tanous [asyncResp, ntpServerObjects]( 537e634b34cSEd Tanous const bool success, std::vector<std::string>& currentNtpServers, 5380eebcefbSJishnu CM const std::vector<std::string>& /*dynamicNtpServers*/, 539b9e15228SEd Tanous const std::vector<std::string>& /*domainNames*/) { 540b9e15228SEd Tanous if (!success) 541b9e15228SEd Tanous { 542b9e15228SEd Tanous messages::internalError(asyncResp->res); 543b9e15228SEd Tanous return; 544b9e15228SEd Tanous } 545b9e15228SEd Tanous handleNTPServersPatch(asyncResp, *ntpServerObjects, 546b9e15228SEd Tanous std::move(currentNtpServers)); 547b9e15228SEd Tanous }); 54820e6ea5dSraviteja-b } 54967a78d87STom Joseph 5505f4c798dSJiaqing Zhao if (ipmiEnabled) 55167a78d87STom Joseph { 552e5a99777SAlbert Zhang handleProtocolEnabled( 5535f4c798dSJiaqing Zhao *ipmiEnabled, asyncResp, 55469320d54SJiaqing Zhao encodeServiceObjectPath(std::string(ipmiServiceName) + '@')); 555e5a99777SAlbert Zhang } 556e5a99777SAlbert Zhang 5575f4c798dSJiaqing Zhao if (sshEnabled) 558e5a99777SAlbert Zhang { 55969320d54SJiaqing Zhao handleProtocolEnabled(*sshEnabled, asyncResp, 56069320d54SJiaqing Zhao encodeServiceObjectPath(sshServiceName)); 56167a78d87STom Joseph } 562e634b34cSEd Tanous } 563e634b34cSEd Tanous 564af20dd1cSEd Tanous inline void handleManagersNetworkProtocolHead( 565e634b34cSEd Tanous App& app, const crow::Request& req, 566253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 567253f11b8SEd Tanous const std::string& managerId) 568e634b34cSEd Tanous { 569e634b34cSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 570e634b34cSEd Tanous { 571e634b34cSEd Tanous return; 572e634b34cSEd Tanous } 573af20dd1cSEd Tanous asyncResp->res.addHeader( 574af20dd1cSEd Tanous boost::beast::http::field::link, 575af20dd1cSEd Tanous "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/ManagerNetworkProtocol.json>; rel=describedby"); 576253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 577253f11b8SEd Tanous { 578253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 579253f11b8SEd Tanous return; 580253f11b8SEd Tanous } 581af20dd1cSEd Tanous } 582af20dd1cSEd Tanous 583af20dd1cSEd Tanous inline void handleManagersNetworkProtocolGet( 584af20dd1cSEd Tanous App& app, const crow::Request& req, 585253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 586253f11b8SEd Tanous const std::string& managerId) 587af20dd1cSEd Tanous { 588253f11b8SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 589253f11b8SEd Tanous { 590253f11b8SEd Tanous return; 591253f11b8SEd Tanous } 592253f11b8SEd Tanous asyncResp->res.addHeader( 593253f11b8SEd Tanous boost::beast::http::field::link, 594253f11b8SEd Tanous "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/ManagerNetworkProtocol.json>; rel=describedby"); 595253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 596253f11b8SEd Tanous { 597253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 598253f11b8SEd Tanous return; 599253f11b8SEd Tanous } 600253f11b8SEd Tanous 601e634b34cSEd Tanous getNetworkData(asyncResp, req); 602e634b34cSEd Tanous } 603e634b34cSEd Tanous 604e634b34cSEd Tanous inline void requestRoutesNetworkProtocol(App& app) 605e634b34cSEd Tanous { 606253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/NetworkProtocol/") 607e634b34cSEd Tanous .privileges(redfish::privileges::patchManagerNetworkProtocol) 608e634b34cSEd Tanous .methods(boost::beast::http::verb::patch)( 609e634b34cSEd Tanous std::bind_front(handleManagersNetworkProtocolPatch, std::ref(app))); 6107e860f15SJohn Edward Broadbent 611253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/NetworkProtocol/") 612e9f71672SEd Tanous .privileges(redfish::privileges::headManagerNetworkProtocol) 613e9f71672SEd Tanous .methods(boost::beast::http::verb::head)( 614af20dd1cSEd Tanous std::bind_front(handleManagersNetworkProtocolHead, std::ref(app))); 615e9f71672SEd Tanous 616253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/NetworkProtocol/") 617ed398213SEd Tanous .privileges(redfish::privileges::getManagerNetworkProtocol) 6187e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 619e634b34cSEd Tanous std::bind_front(handleManagersNetworkProtocolGet, std::ref(app))); 620cf05f9dcSJohnathan Mantey } 62170141561SBorawski.Lukasz 62270141561SBorawski.Lukasz } // namespace redfish 623