170141561SBorawski.Lukasz /* 2*6be832e2SEd Tanous Copyright (c) 2018 Intel Corporation 3*6be832e2SEd Tanous 4*6be832e2SEd Tanous Licensed under the Apache License, Version 2.0 (the "License"); 5*6be832e2SEd Tanous you may not use this file except in compliance with the License. 6*6be832e2SEd Tanous You may obtain a copy of the License at 7*6be832e2SEd Tanous 8*6be832e2SEd Tanous http://www.apache.org/licenses/LICENSE-2.0 9*6be832e2SEd Tanous 10*6be832e2SEd Tanous Unless required by applicable law or agreed to in writing, software 11*6be832e2SEd Tanous distributed under the License is distributed on an "AS IS" BASIS, 12*6be832e2SEd Tanous WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*6be832e2SEd Tanous See the License for the specific language governing permissions and 14*6be832e2SEd 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 // clang-format off 5115f4c798dSJiaqing Zhao if (!json_util::readJsonPatch( 5125f4c798dSJiaqing Zhao req, asyncResp->res, 5135f4c798dSJiaqing Zhao "HostName", newHostName, 514b9e15228SEd Tanous "NTP/NTPServers", ntpServerObjects, 5155f4c798dSJiaqing Zhao "NTP/ProtocolEnabled", ntpEnabled, 5165f4c798dSJiaqing Zhao "IPMI/ProtocolEnabled", ipmiEnabled, 5175f4c798dSJiaqing Zhao "SSH/ProtocolEnabled", sshEnabled)) 518501be32bSraviteja-b { 519501be32bSraviteja-b return; 520501be32bSraviteja-b } 5215f4c798dSJiaqing Zhao // clang-format on 522cf05f9dcSJohnathan Mantey 5238d1b46d7Szhanghch05 asyncResp->res.result(boost::beast::http::status::no_content); 524501be32bSraviteja-b if (newHostName) 525501be32bSraviteja-b { 5262db77d34SJohnathan Mantey messages::propertyNotWritable(asyncResp->res, "HostName"); 52744fad2aaSEd Tanous return; 528cf05f9dcSJohnathan Mantey } 529cf05f9dcSJohnathan Mantey 53020e6ea5dSraviteja-b if (ntpEnabled) 53120e6ea5dSraviteja-b { 5328e157735SEd Tanous handleNTPProtocolEnabled(asyncResp, *ntpEnabled); 53320e6ea5dSraviteja-b } 534b9e15228SEd Tanous if (ntpServerObjects) 53520e6ea5dSraviteja-b { 536b9e15228SEd Tanous getEthernetIfaceData( 537b9e15228SEd Tanous [asyncResp, ntpServerObjects]( 538e634b34cSEd Tanous const bool success, std::vector<std::string>& currentNtpServers, 5390eebcefbSJishnu CM const std::vector<std::string>& /*dynamicNtpServers*/, 540b9e15228SEd Tanous const std::vector<std::string>& /*domainNames*/) { 541b9e15228SEd Tanous if (!success) 542b9e15228SEd Tanous { 543b9e15228SEd Tanous messages::internalError(asyncResp->res); 544b9e15228SEd Tanous return; 545b9e15228SEd Tanous } 546b9e15228SEd Tanous handleNTPServersPatch(asyncResp, *ntpServerObjects, 547b9e15228SEd Tanous std::move(currentNtpServers)); 548b9e15228SEd Tanous }); 54920e6ea5dSraviteja-b } 55067a78d87STom Joseph 5515f4c798dSJiaqing Zhao if (ipmiEnabled) 55267a78d87STom Joseph { 553e5a99777SAlbert Zhang handleProtocolEnabled( 5545f4c798dSJiaqing Zhao *ipmiEnabled, asyncResp, 55569320d54SJiaqing Zhao encodeServiceObjectPath(std::string(ipmiServiceName) + '@')); 556e5a99777SAlbert Zhang } 557e5a99777SAlbert Zhang 5585f4c798dSJiaqing Zhao if (sshEnabled) 559e5a99777SAlbert Zhang { 56069320d54SJiaqing Zhao handleProtocolEnabled(*sshEnabled, asyncResp, 56169320d54SJiaqing Zhao encodeServiceObjectPath(sshServiceName)); 56267a78d87STom Joseph } 563e634b34cSEd Tanous } 564e634b34cSEd Tanous 565af20dd1cSEd Tanous inline void handleManagersNetworkProtocolHead( 566e634b34cSEd Tanous App& app, const crow::Request& req, 567253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 568253f11b8SEd Tanous const std::string& managerId) 569e634b34cSEd Tanous { 570e634b34cSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 571e634b34cSEd Tanous { 572e634b34cSEd Tanous return; 573e634b34cSEd Tanous } 574af20dd1cSEd Tanous asyncResp->res.addHeader( 575af20dd1cSEd Tanous boost::beast::http::field::link, 576af20dd1cSEd Tanous "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/ManagerNetworkProtocol.json>; rel=describedby"); 577253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 578253f11b8SEd Tanous { 579253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 580253f11b8SEd Tanous return; 581253f11b8SEd Tanous } 582af20dd1cSEd Tanous } 583af20dd1cSEd Tanous 584af20dd1cSEd Tanous inline void handleManagersNetworkProtocolGet( 585af20dd1cSEd Tanous App& app, const crow::Request& req, 586253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 587253f11b8SEd Tanous const std::string& managerId) 588af20dd1cSEd Tanous { 589253f11b8SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 590253f11b8SEd Tanous { 591253f11b8SEd Tanous return; 592253f11b8SEd Tanous } 593253f11b8SEd Tanous asyncResp->res.addHeader( 594253f11b8SEd Tanous boost::beast::http::field::link, 595253f11b8SEd Tanous "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/ManagerNetworkProtocol.json>; rel=describedby"); 596253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 597253f11b8SEd Tanous { 598253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 599253f11b8SEd Tanous return; 600253f11b8SEd Tanous } 601253f11b8SEd Tanous 602e634b34cSEd Tanous getNetworkData(asyncResp, req); 603e634b34cSEd Tanous } 604e634b34cSEd Tanous 605e634b34cSEd Tanous inline void requestRoutesNetworkProtocol(App& app) 606e634b34cSEd Tanous { 607253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/NetworkProtocol/") 608e634b34cSEd Tanous .privileges(redfish::privileges::patchManagerNetworkProtocol) 609e634b34cSEd Tanous .methods(boost::beast::http::verb::patch)( 610e634b34cSEd Tanous std::bind_front(handleManagersNetworkProtocolPatch, std::ref(app))); 6117e860f15SJohn Edward Broadbent 612253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/NetworkProtocol/") 613e9f71672SEd Tanous .privileges(redfish::privileges::headManagerNetworkProtocol) 614e9f71672SEd Tanous .methods(boost::beast::http::verb::head)( 615af20dd1cSEd Tanous std::bind_front(handleManagersNetworkProtocolHead, std::ref(app))); 616e9f71672SEd Tanous 617253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/NetworkProtocol/") 618ed398213SEd Tanous .privileges(redfish::privileges::getManagerNetworkProtocol) 6197e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 620e634b34cSEd Tanous std::bind_front(handleManagersNetworkProtocolGet, std::ref(app))); 621cf05f9dcSJohnathan Mantey } 62270141561SBorawski.Lukasz 62370141561SBorawski.Lukasz } // namespace redfish 624