xref: /openbmc/bmcweb/features/redfish/lib/network_protocol.hpp (revision 18f8f608b966c802b3e2a389e3c1ec5a1fd9407b)
170141561SBorawski.Lukasz /*
270141561SBorawski.Lukasz // Copyright (c) 2018 Intel Corporation
370141561SBorawski.Lukasz //
470141561SBorawski.Lukasz // Licensed under the Apache License, Version 2.0 (the "License");
570141561SBorawski.Lukasz // you may not use this file except in compliance with the License.
670141561SBorawski.Lukasz // You may obtain a copy of the License at
770141561SBorawski.Lukasz //
870141561SBorawski.Lukasz //      http://www.apache.org/licenses/LICENSE-2.0
970141561SBorawski.Lukasz //
1070141561SBorawski.Lukasz // Unless required by applicable law or agreed to in writing, software
1170141561SBorawski.Lukasz // distributed under the License is distributed on an "AS IS" BASIS,
1270141561SBorawski.Lukasz // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1370141561SBorawski.Lukasz // See the License for the specific language governing permissions and
1470141561SBorawski.Lukasz // limitations under the License.
1570141561SBorawski.Lukasz */
1670141561SBorawski.Lukasz #pragma once
1770141561SBorawski.Lukasz 
183ccb3adbSEd Tanous #include "app.hpp"
193ccb3adbSEd Tanous #include "dbus_utility.hpp"
203a8a0088SKowalski, Kamil #include "error_messages.hpp"
2167a78d87STom Joseph #include "openbmc_dbus_rest.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>
291e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp>
301214b7e7SGunnar Mills 
31e99073f5SGeorge Liu #include <array>
321214b7e7SGunnar Mills #include <optional>
33e99073f5SGeorge Liu #include <string_view>
34abf2add6SEd Tanous #include <variant>
355f4c798dSJiaqing Zhao 
361abe55efSEd Tanous namespace redfish
371abe55efSEd Tanous {
3870141561SBorawski.Lukasz 
397e860f15SJohn Edward Broadbent void getNTPProtocolEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp);
407e860f15SJohn Edward Broadbent std::string getHostName();
417e860f15SJohn Edward Broadbent 
425c3e9272SAbhishek Patel static constexpr std::string_view sshServiceName = "dropbear";
435c3e9272SAbhishek Patel static constexpr std::string_view httpsServiceName = "bmcweb";
445c3e9272SAbhishek Patel static constexpr std::string_view ipmiServiceName = "phosphor-ipmi-net";
455c3e9272SAbhishek Patel 
465c3e9272SAbhishek Patel // Mapping from Redfish NetworkProtocol key name to backend service that hosts
475c3e9272SAbhishek Patel // that protocol.
485c3e9272SAbhishek Patel static constexpr std::array<std::pair<std::string_view, std::string_view>, 3>
495c3e9272SAbhishek Patel     networkProtocolToDbus = {{{"SSH", sshServiceName},
5069320d54SJiaqing Zhao                               {"HTTPS", httpsServiceName},
5169320d54SJiaqing Zhao                               {"IPMI", ipmiServiceName}}};
523a8a0088SKowalski, Kamil 
53711ac7a9SEd Tanous inline void extractNTPServersAndDomainNamesData(
54711ac7a9SEd Tanous     const dbus::utility::ManagedObjectType& dbusData,
55532d7697SGunnar Mills     std::vector<std::string>& ntpData, std::vector<std::string>& dnData)
5620e6ea5dSraviteja-b {
5781ce609eSEd Tanous     for (const auto& obj : dbusData)
5820e6ea5dSraviteja-b     {
5920e6ea5dSraviteja-b         for (const auto& ifacePair : obj.second)
6020e6ea5dSraviteja-b         {
610a052baaSGeorge Liu             if (ifacePair.first !=
6220e6ea5dSraviteja-b                 "xyz.openbmc_project.Network.EthernetInterface")
6320e6ea5dSraviteja-b             {
640a052baaSGeorge Liu                 continue;
650a052baaSGeorge Liu             }
660a052baaSGeorge Liu 
6720e6ea5dSraviteja-b             for (const auto& propertyPair : ifacePair.second)
6820e6ea5dSraviteja-b             {
69fcd2682aSEd Tanous                 if (propertyPair.first == "StaticNTPServers")
7020e6ea5dSraviteja-b                 {
7120e6ea5dSraviteja-b                     const std::vector<std::string>* ntpServers =
728d78b7a9SPatrick Williams                         std::get_if<std::vector<std::string>>(
7320e6ea5dSraviteja-b                             &propertyPair.second);
7420e6ea5dSraviteja-b                     if (ntpServers != nullptr)
7520e6ea5dSraviteja-b                     {
76c251fe81SJian Zhang                         ntpData.insert(ntpData.end(), ntpServers->begin(),
77c251fe81SJian Zhang                                        ntpServers->end());
7820e6ea5dSraviteja-b                     }
7920e6ea5dSraviteja-b                 }
80d24bfc7aSJennifer Lee                 else if (propertyPair.first == "DomainName")
81d24bfc7aSJennifer Lee                 {
82d24bfc7aSJennifer Lee                     const std::vector<std::string>* domainNames =
838d78b7a9SPatrick Williams                         std::get_if<std::vector<std::string>>(
84d24bfc7aSJennifer Lee                             &propertyPair.second);
85d24bfc7aSJennifer Lee                     if (domainNames != nullptr)
86d24bfc7aSJennifer Lee                     {
87c251fe81SJian Zhang                         dnData.insert(dnData.end(), domainNames->begin(),
88c251fe81SJian Zhang                                       domainNames->end());
89d24bfc7aSJennifer Lee                     }
90d24bfc7aSJennifer Lee                 }
9120e6ea5dSraviteja-b             }
9220e6ea5dSraviteja-b         }
9320e6ea5dSraviteja-b     }
940225b87bSEd Tanous     stl_utils::removeDuplicate(ntpData);
95c251fe81SJian Zhang     stl_utils::removeDuplicate(dnData);
9620e6ea5dSraviteja-b }
9720e6ea5dSraviteja-b 
9820e6ea5dSraviteja-b template <typename CallbackFunc>
9920e6ea5dSraviteja-b void getEthernetIfaceData(CallbackFunc&& callback)
10020e6ea5dSraviteja-b {
1015eb468daSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1025eb468daSGeorge Liu     dbus::utility::getManagedObjects(
1035eb468daSGeorge Liu         "xyz.openbmc_project.Network", path,
104f94c4ecfSEd Tanous         [callback{std::forward<CallbackFunc>(callback)}](
1058b24275dSEd Tanous             const boost::system::error_code& ec,
106711ac7a9SEd Tanous             const dbus::utility::ManagedObjectType& dbusData) {
10720e6ea5dSraviteja-b         std::vector<std::string> ntpServers;
108d24bfc7aSJennifer Lee         std::vector<std::string> domainNames;
10920e6ea5dSraviteja-b 
1108b24275dSEd Tanous         if (ec)
11120e6ea5dSraviteja-b         {
112532d7697SGunnar Mills             callback(false, ntpServers, domainNames);
11320e6ea5dSraviteja-b             return;
11420e6ea5dSraviteja-b         }
11520e6ea5dSraviteja-b 
116532d7697SGunnar Mills         extractNTPServersAndDomainNamesData(dbusData, ntpServers, domainNames);
11720e6ea5dSraviteja-b 
118532d7697SGunnar Mills         callback(true, ntpServers, domainNames);
1195eb468daSGeorge Liu     });
120271584abSEd Tanous }
12120e6ea5dSraviteja-b 
1225c3e9272SAbhishek Patel inline void afterNetworkPortRequest(
1235c3e9272SAbhishek Patel     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1245c3e9272SAbhishek Patel     const boost::system::error_code& ec,
1255c3e9272SAbhishek Patel     const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
1265c3e9272SAbhishek Patel {
1275c3e9272SAbhishek Patel     if (ec)
1285c3e9272SAbhishek Patel     {
1295c3e9272SAbhishek Patel         messages::internalError(asyncResp->res);
1305c3e9272SAbhishek Patel         return;
1315c3e9272SAbhishek Patel     }
1325c3e9272SAbhishek Patel     for (const auto& data : socketData)
1335c3e9272SAbhishek Patel     {
1345c3e9272SAbhishek Patel         const std::string& socketPath = get<0>(data);
1355c3e9272SAbhishek Patel         const std::string& protocolName = get<1>(data);
1365c3e9272SAbhishek Patel         bool isProtocolEnabled = get<2>(data);
1375c3e9272SAbhishek Patel 
1385c3e9272SAbhishek Patel         asyncResp->res.jsonValue[protocolName]["ProtocolEnabled"] =
1395c3e9272SAbhishek Patel             isProtocolEnabled;
1405c3e9272SAbhishek Patel         asyncResp->res.jsonValue[protocolName]["Port"] = nullptr;
1415c3e9272SAbhishek Patel         getPortNumber(socketPath, [asyncResp, protocolName](
1425c3e9272SAbhishek Patel                                       const boost::system::error_code& ec2,
1435c3e9272SAbhishek Patel                                       int portNumber) {
1445c3e9272SAbhishek Patel             if (ec2)
1455c3e9272SAbhishek Patel             {
1465c3e9272SAbhishek Patel                 messages::internalError(asyncResp->res);
1475c3e9272SAbhishek Patel                 return;
1485c3e9272SAbhishek Patel             }
1495c3e9272SAbhishek Patel             asyncResp->res.jsonValue[protocolName]["Port"] = portNumber;
1505c3e9272SAbhishek Patel         });
1515c3e9272SAbhishek Patel     }
1525c3e9272SAbhishek Patel }
1535c3e9272SAbhishek Patel 
1544f48d5f6SEd Tanous inline void getNetworkData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
15572048780SAbhishek Patel                            const crow::Request& req)
1561abe55efSEd Tanous {
1573e72c202SNinad Palsule     if (req.session == nullptr)
1583e72c202SNinad Palsule     {
1593e72c202SNinad Palsule         messages::internalError(asyncResp->res);
1603e72c202SNinad Palsule         return;
1613e72c202SNinad Palsule     }
1623e72c202SNinad Palsule 
163e9f71672SEd Tanous     asyncResp->res.addHeader(
164e9f71672SEd Tanous         boost::beast::http::field::link,
165e9f71672SEd Tanous         "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/NetworkProtocol.json>; rel=describedby");
1660f74e643SEd Tanous     asyncResp->res.jsonValue["@odata.type"] =
167532d7697SGunnar Mills         "#ManagerNetworkProtocol.v1_5_0.ManagerNetworkProtocol";
1680f74e643SEd Tanous     asyncResp->res.jsonValue["@odata.id"] =
1690f74e643SEd Tanous         "/redfish/v1/Managers/bmc/NetworkProtocol";
1700f74e643SEd Tanous     asyncResp->res.jsonValue["Id"] = "NetworkProtocol";
1710f74e643SEd Tanous     asyncResp->res.jsonValue["Name"] = "Manager Network Protocol";
1720f74e643SEd Tanous     asyncResp->res.jsonValue["Description"] = "Manager Network Service";
1730f74e643SEd Tanous     asyncResp->res.jsonValue["Status"]["Health"] = "OK";
1740f74e643SEd Tanous     asyncResp->res.jsonValue["Status"]["HealthRollup"] = "OK";
1750f74e643SEd Tanous     asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
1760f74e643SEd Tanous 
17761932318SXiaochao Ma     // HTTP is Mandatory attribute as per OCP Baseline Profile - v1.0.0,
178818ea7b8SJoshi-Mansi     // but from security perspective it is not recommended to use.
179818ea7b8SJoshi-Mansi     // Hence using protocolEnabled as false to make it OCP and security-wise
180818ea7b8SJoshi-Mansi     // compliant
1815c3e9272SAbhishek Patel     asyncResp->res.jsonValue["HTTP"]["Port"] = nullptr;
182818ea7b8SJoshi-Mansi     asyncResp->res.jsonValue["HTTP"]["ProtocolEnabled"] = false;
183818ea7b8SJoshi-Mansi 
1841ee2db7fSAndrew Geissler     // The ProtocolEnabled of the following protocols is determined by
1851ee2db7fSAndrew Geissler     // inspecting the state of associated systemd sockets. If these protocols
1861ee2db7fSAndrew Geissler     // have been disabled, then the systemd socket unit files will not be found
1871ee2db7fSAndrew Geissler     // and the protocols will not be returned in this Redfish query. Set some
1881ee2db7fSAndrew Geissler     // defaults to ensure something is always returned.
1891ee2db7fSAndrew Geissler     for (const auto& nwkProtocol : networkProtocolToDbus)
1901ee2db7fSAndrew Geissler     {
1911ee2db7fSAndrew Geissler         asyncResp->res.jsonValue[nwkProtocol.first]["Port"] = nullptr;
1921ee2db7fSAndrew Geissler         asyncResp->res.jsonValue[nwkProtocol.first]["ProtocolEnabled"] = false;
1931ee2db7fSAndrew Geissler     }
1941ee2db7fSAndrew Geissler 
195d24bfc7aSJennifer Lee     std::string hostName = getHostName();
196d24bfc7aSJennifer Lee 
197d24bfc7aSJennifer Lee     asyncResp->res.jsonValue["HostName"] = hostName;
1983a8a0088SKowalski, Kamil 
19920e6ea5dSraviteja-b     getNTPProtocolEnabled(asyncResp);
20020e6ea5dSraviteja-b 
201002d39b4SEd Tanous     getEthernetIfaceData(
202002d39b4SEd Tanous         [hostName, asyncResp](const bool& success,
20302cad96eSEd Tanous                               const std::vector<std::string>& ntpServers,
204d24bfc7aSJennifer Lee                               const std::vector<std::string>& domainNames) {
20520e6ea5dSraviteja-b         if (!success)
20620e6ea5dSraviteja-b         {
2070a052baaSGeorge Liu             messages::resourceNotFound(asyncResp->res, "ManagerNetworkProtocol",
2080a052baaSGeorge Liu                                        "NetworkProtocol");
20920e6ea5dSraviteja-b             return;
21020e6ea5dSraviteja-b         }
21120e6ea5dSraviteja-b         asyncResp->res.jsonValue["NTP"]["NTPServers"] = ntpServers;
21226f6976fSEd Tanous         if (!hostName.empty())
213d24bfc7aSJennifer Lee         {
214f23b7296SEd Tanous             std::string fqdn = hostName;
21526f6976fSEd Tanous             if (!domainNames.empty())
216d24bfc7aSJennifer Lee             {
217f23b7296SEd Tanous                 fqdn += ".";
218f23b7296SEd Tanous                 fqdn += domainNames[0];
219d24bfc7aSJennifer Lee             }
2202c70f800SEd Tanous             asyncResp->res.jsonValue["FQDN"] = std::move(fqdn);
221d24bfc7aSJennifer Lee         }
22220e6ea5dSraviteja-b     });
22320e6ea5dSraviteja-b 
22472048780SAbhishek Patel     Privileges effectiveUserPrivileges =
2253e72c202SNinad Palsule         redfish::getUserPrivileges(*req.session);
22672048780SAbhishek Patel 
22772048780SAbhishek Patel     // /redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates is
22872048780SAbhishek Patel     // something only ConfigureManager can access then only display when
22972048780SAbhishek Patel     // the user has permissions ConfigureManager
23072048780SAbhishek Patel     if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
23172048780SAbhishek Patel                                          effectiveUserPrivileges))
23272048780SAbhishek Patel     {
2331476687dSEd Tanous         asyncResp->res.jsonValue["HTTPS"]["Certificates"]["@odata.id"] =
2341476687dSEd Tanous             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates";
23570141561SBorawski.Lukasz     }
23670141561SBorawski.Lukasz 
2375c3e9272SAbhishek Patel     getPortStatusAndPath(std::span(networkProtocolToDbus),
2385c3e9272SAbhishek Patel                          std::bind_front(afterNetworkPortRequest, asyncResp));
239b4bec66bSAbhishek Patel } // namespace redfish
240501be32bSraviteja-b 
2414f48d5f6SEd Tanous inline void handleNTPProtocolEnabled(
2427e860f15SJohn Edward Broadbent     const bool& ntpEnabled, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
24320e6ea5dSraviteja-b {
24420e6ea5dSraviteja-b     std::string timeSyncMethod;
24520e6ea5dSraviteja-b     if (ntpEnabled)
24620e6ea5dSraviteja-b     {
2477e860f15SJohn Edward Broadbent         timeSyncMethod = "xyz.openbmc_project.Time.Synchronization.Method.NTP";
24820e6ea5dSraviteja-b     }
24920e6ea5dSraviteja-b     else
25020e6ea5dSraviteja-b     {
25120e6ea5dSraviteja-b         timeSyncMethod =
25220e6ea5dSraviteja-b             "xyz.openbmc_project.Time.Synchronization.Method.Manual";
25320e6ea5dSraviteja-b     }
25420e6ea5dSraviteja-b 
2559ae226faSGeorge Liu     sdbusplus::asio::setProperty(
2569ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Settings",
2579ae226faSGeorge Liu         "/xyz/openbmc_project/time/sync_method",
2589ae226faSGeorge Liu         "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod",
2598b24275dSEd Tanous         timeSyncMethod, [asyncResp](const boost::system::error_code& ec) {
2608b24275dSEd Tanous         if (ec)
261cb13a392SEd Tanous         {
262cb13a392SEd Tanous             messages::internalError(asyncResp->res);
263cb13a392SEd Tanous         }
2649ae226faSGeorge Liu     });
26520e6ea5dSraviteja-b }
26620e6ea5dSraviteja-b 
2674f48d5f6SEd Tanous inline void
268287ece64SGeorge Liu     handleNTPServersPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
269b9e15228SEd Tanous                           const std::vector<nlohmann::json>& ntpServerObjects,
270b9e15228SEd Tanous                           std::vector<std::string> currentNtpServers)
27120e6ea5dSraviteja-b {
272b9e15228SEd Tanous     std::vector<std::string>::iterator currentNtpServer =
273b9e15228SEd Tanous         currentNtpServers.begin();
274b9e15228SEd Tanous     for (size_t index = 0; index < ntpServerObjects.size(); index++)
275287ece64SGeorge Liu     {
276b9e15228SEd Tanous         const nlohmann::json& ntpServer = ntpServerObjects[index];
277b9e15228SEd Tanous         if (ntpServer.is_null())
278b9e15228SEd Tanous         {
279b9e15228SEd Tanous             // Can't delete an item that doesn't exist
280b9e15228SEd Tanous             if (currentNtpServer == currentNtpServers.end())
281b9e15228SEd Tanous             {
282b9e15228SEd Tanous                 messages::propertyValueNotInList(asyncResp->res, "null",
283b9e15228SEd Tanous                                                  "NTP/NTPServers/" +
284b9e15228SEd Tanous                                                      std::to_string(index));
285b9e15228SEd Tanous 
286287ece64SGeorge Liu                 return;
287287ece64SGeorge Liu             }
288b9e15228SEd Tanous             currentNtpServer = currentNtpServers.erase(currentNtpServer);
289b9e15228SEd Tanous             continue;
290b9e15228SEd Tanous         }
291b9e15228SEd Tanous         const nlohmann::json::object_t* ntpServerObject =
292b9e15228SEd Tanous             ntpServer.get_ptr<const nlohmann::json::object_t*>();
293b9e15228SEd Tanous         if (ntpServerObject != nullptr)
294b9e15228SEd Tanous         {
295b9e15228SEd Tanous             if (!ntpServerObject->empty())
296b9e15228SEd Tanous             {
297b9e15228SEd Tanous                 messages::propertyValueNotInList(
298b9e15228SEd Tanous                     asyncResp->res,
299b9e15228SEd Tanous                     ntpServer.dump(2, ' ', true,
300b9e15228SEd Tanous                                    nlohmann::json::error_handler_t::replace),
301b9e15228SEd Tanous                     "NTP/NTPServers/" + std::to_string(index));
302b9e15228SEd Tanous                 return;
303b9e15228SEd Tanous             }
304b9e15228SEd Tanous             // Can't retain an item that doesn't exist
305b9e15228SEd Tanous             if (currentNtpServer == currentNtpServers.end())
306b9e15228SEd Tanous             {
307b9e15228SEd Tanous                 messages::propertyValueOutOfRange(
308b9e15228SEd Tanous                     asyncResp->res,
309b9e15228SEd Tanous                     ntpServer.dump(2, ' ', true,
310b9e15228SEd Tanous                                    nlohmann::json::error_handler_t::replace),
311b9e15228SEd Tanous                     "NTP/NTPServers/" + std::to_string(index));
312b9e15228SEd Tanous 
313b9e15228SEd Tanous                 return;
314b9e15228SEd Tanous             }
315b9e15228SEd Tanous             // empty objects should leave the NtpServer unmodified
316b9e15228SEd Tanous             currentNtpServer++;
317b9e15228SEd Tanous             continue;
318b9e15228SEd Tanous         }
319b9e15228SEd Tanous 
320b9e15228SEd Tanous         const std::string* ntpServerStr =
321b9e15228SEd Tanous             ntpServer.get_ptr<const std::string*>();
322b9e15228SEd Tanous         if (ntpServerStr == nullptr)
323b9e15228SEd Tanous         {
324b9e15228SEd Tanous             messages::propertyValueTypeError(
325b9e15228SEd Tanous                 asyncResp->res,
326b9e15228SEd Tanous                 ntpServer.dump(2, ' ', true,
327b9e15228SEd Tanous                                nlohmann::json::error_handler_t::replace),
328b9e15228SEd Tanous                 "NTP/NTPServers/" + std::to_string(index));
329b9e15228SEd Tanous             return;
330b9e15228SEd Tanous         }
331b9e15228SEd Tanous         if (currentNtpServer == currentNtpServers.end())
332b9e15228SEd Tanous         {
333b9e15228SEd Tanous             // if we're at the end of the list, append to the end
334b9e15228SEd Tanous             currentNtpServers.push_back(*ntpServerStr);
335b9e15228SEd Tanous             currentNtpServer = currentNtpServers.end();
336b9e15228SEd Tanous             continue;
337b9e15228SEd Tanous         }
338b9e15228SEd Tanous         *currentNtpServer = *ntpServerStr;
339b9e15228SEd Tanous         currentNtpServer++;
340b9e15228SEd Tanous     }
341b9e15228SEd Tanous 
342b9e15228SEd Tanous     // Any remaining array elements should be removed
343b9e15228SEd Tanous     currentNtpServers.erase(currentNtpServer, currentNtpServers.end());
344287ece64SGeorge Liu 
345e99073f5SGeorge Liu     constexpr std::array<std::string_view, 1> ethInterfaces = {
346e99073f5SGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface"};
347e99073f5SGeorge Liu     dbus::utility::getSubTree(
348e99073f5SGeorge Liu         "/xyz/openbmc_project", 0, ethInterfaces,
349b9e15228SEd Tanous         [asyncResp, currentNtpServers](
3502138483cSGeorge Liu             const boost::system::error_code& ec,
351b9d36b47SEd Tanous             const dbus::utility::MapperGetSubTreeResponse& subtree) {
3520a052baaSGeorge Liu         if (ec)
3530a052baaSGeorge Liu         {
35462598e31SEd Tanous             BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
3550a052baaSGeorge Liu             messages::internalError(asyncResp->res);
3560a052baaSGeorge Liu             return;
3570a052baaSGeorge Liu         }
3580a052baaSGeorge Liu 
3590a052baaSGeorge Liu         for (const auto& [objectPath, serviceMap] : subtree)
3600a052baaSGeorge Liu         {
3610a052baaSGeorge Liu             for (const auto& [service, interfaces] : serviceMap)
3620a052baaSGeorge Liu             {
3630a052baaSGeorge Liu                 for (const auto& interface : interfaces)
3640a052baaSGeorge Liu                 {
3650a052baaSGeorge Liu                     if (interface !=
3660a052baaSGeorge Liu                         "xyz.openbmc_project.Network.EthernetInterface")
3670a052baaSGeorge Liu                     {
3680a052baaSGeorge Liu                         continue;
3690a052baaSGeorge Liu                     }
3700a052baaSGeorge Liu 
3719ae226faSGeorge Liu                     sdbusplus::asio::setProperty(
3729ae226faSGeorge Liu                         *crow::connections::systemBus, service, objectPath,
3739ae226faSGeorge Liu                         interface, "StaticNTPServers", currentNtpServers,
3745e7e2dc5SEd Tanous                         [asyncResp](const boost::system::error_code& ec2) {
3758a592810SEd Tanous                         if (ec2)
37620e6ea5dSraviteja-b                         {
37720e6ea5dSraviteja-b                             messages::internalError(asyncResp->res);
37820e6ea5dSraviteja-b                             return;
37920e6ea5dSraviteja-b                         }
3809ae226faSGeorge Liu                     });
38120e6ea5dSraviteja-b                 }
3820a052baaSGeorge Liu             }
3830a052baaSGeorge Liu         }
384e99073f5SGeorge Liu     });
3850a052baaSGeorge Liu }
38620e6ea5dSraviteja-b 
3874f48d5f6SEd Tanous inline void
3884f48d5f6SEd Tanous     handleProtocolEnabled(const bool protocolEnabled,
389e5a99777SAlbert Zhang                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
39069320d54SJiaqing Zhao                           const std::string& netBasePath)
39167a78d87STom Joseph {
392e99073f5SGeorge Liu     constexpr std::array<std::string_view, 1> interfaces = {
393e99073f5SGeorge Liu         "xyz.openbmc_project.Control.Service.Attributes"};
394e99073f5SGeorge Liu     dbus::utility::getSubTree(
395e99073f5SGeorge Liu         "/xyz/openbmc_project/control/service", 0, interfaces,
396e5a99777SAlbert Zhang         [protocolEnabled, asyncResp,
3972138483cSGeorge Liu          netBasePath](const boost::system::error_code& ec,
398b9d36b47SEd Tanous                       const dbus::utility::MapperGetSubTreeResponse& subtree) {
39967a78d87STom Joseph         if (ec)
40067a78d87STom Joseph         {
40167a78d87STom Joseph             messages::internalError(asyncResp->res);
40267a78d87STom Joseph             return;
40367a78d87STom Joseph         }
40467a78d87STom Joseph 
40567a78d87STom Joseph         for (const auto& entry : subtree)
40667a78d87STom Joseph         {
407*18f8f608SEd Tanous             if (entry.first.starts_with(netBasePath))
40867a78d87STom Joseph             {
4099ae226faSGeorge Liu                 sdbusplus::asio::setProperty(
4109ae226faSGeorge Liu                     *crow::connections::systemBus, entry.second.begin()->first,
4119ae226faSGeorge Liu                     entry.first,
412002d39b4SEd Tanous                     "xyz.openbmc_project.Control.Service.Attributes", "Running",
4139ae226faSGeorge Liu                     protocolEnabled,
4145e7e2dc5SEd Tanous                     [asyncResp](const boost::system::error_code& ec2) {
41523a21a1cSEd Tanous                     if (ec2)
41667a78d87STom Joseph                     {
41767a78d87STom Joseph                         messages::internalError(asyncResp->res);
41867a78d87STom Joseph                         return;
41967a78d87STom Joseph                     }
4209ae226faSGeorge Liu                 });
4219ae226faSGeorge Liu                 sdbusplus::asio::setProperty(
4229ae226faSGeorge Liu                     *crow::connections::systemBus, entry.second.begin()->first,
4239ae226faSGeorge Liu                     entry.first,
424002d39b4SEd Tanous                     "xyz.openbmc_project.Control.Service.Attributes", "Enabled",
4259ae226faSGeorge Liu                     protocolEnabled,
4269ae226faSGeorge Liu                     [asyncResp](const boost::system::error_code& ec2) {
4279ae226faSGeorge Liu                     if (ec2)
4289ae226faSGeorge Liu                     {
4299ae226faSGeorge Liu                         messages::internalError(asyncResp->res);
4309ae226faSGeorge Liu                         return;
4319ae226faSGeorge Liu                     }
4329ae226faSGeorge Liu                 });
43367a78d87STom Joseph             }
43467a78d87STom Joseph         }
435e99073f5SGeorge Liu     });
43667a78d87STom Joseph }
43767a78d87STom Joseph 
4384f48d5f6SEd Tanous inline std::string getHostName()
439501be32bSraviteja-b {
4407e860f15SJohn Edward Broadbent     std::string hostName;
4418d1b46d7Szhanghch05 
442d3a9e084SEd Tanous     std::array<char, HOST_NAME_MAX> hostNameCStr{};
4437e860f15SJohn Edward Broadbent     if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0)
4447e860f15SJohn Edward Broadbent     {
4457e860f15SJohn Edward Broadbent         hostName = hostNameCStr.data();
4467e860f15SJohn Edward Broadbent     }
4477e860f15SJohn Edward Broadbent     return hostName;
4487e860f15SJohn Edward Broadbent }
4497e860f15SJohn Edward Broadbent 
4504f48d5f6SEd Tanous inline void
4514f48d5f6SEd Tanous     getNTPProtocolEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
4527e860f15SJohn Edward Broadbent {
4531e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
4541e1e598dSJonathan Doman         *crow::connections::systemBus, "xyz.openbmc_project.Settings",
4551e1e598dSJonathan Doman         "/xyz/openbmc_project/time/sync_method",
4561e1e598dSJonathan Doman         "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod",
4578b24275dSEd Tanous         [asyncResp](const boost::system::error_code& ec,
4581e1e598dSJonathan Doman                     const std::string& timeSyncMethod) {
4598b24275dSEd Tanous         if (ec)
4607e860f15SJohn Edward Broadbent         {
4617e860f15SJohn Edward Broadbent             return;
4627e860f15SJohn Edward Broadbent         }
4637e860f15SJohn Edward Broadbent 
4641e1e598dSJonathan Doman         if (timeSyncMethod ==
4651e1e598dSJonathan Doman             "xyz.openbmc_project.Time.Synchronization.Method.NTP")
4667e860f15SJohn Edward Broadbent         {
4677e860f15SJohn Edward Broadbent             asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = true;
4687e860f15SJohn Edward Broadbent         }
469002d39b4SEd Tanous         else if (timeSyncMethod == "xyz.openbmc_project.Time.Synchronization."
4701e1e598dSJonathan Doman                                    "Method.Manual")
4717e860f15SJohn Edward Broadbent         {
4727e860f15SJohn Edward Broadbent             asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = false;
4737e860f15SJohn Edward Broadbent         }
4741e1e598dSJonathan Doman     });
4757e860f15SJohn Edward Broadbent }
4767e860f15SJohn Edward Broadbent 
4775c3e9272SAbhishek Patel inline std::string encodeServiceObjectPath(std::string_view serviceName)
47869320d54SJiaqing Zhao {
47969320d54SJiaqing Zhao     sdbusplus::message::object_path objPath(
48069320d54SJiaqing Zhao         "/xyz/openbmc_project/control/service");
48169320d54SJiaqing Zhao     objPath /= serviceName;
48269320d54SJiaqing Zhao     return objPath.str;
48369320d54SJiaqing Zhao }
48469320d54SJiaqing Zhao 
4850f55d946SEd Tanous inline void handleBmcNetworkProtocolHead(
486e9f71672SEd Tanous     crow::App& app, const crow::Request& req,
487e9f71672SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
488e9f71672SEd Tanous {
489e9f71672SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
490e9f71672SEd Tanous     {
491e9f71672SEd Tanous         return;
492e9f71672SEd Tanous     }
493e9f71672SEd Tanous     asyncResp->res.addHeader(
494e9f71672SEd Tanous         boost::beast::http::field::link,
495e9f71672SEd Tanous         "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/ManagerNetworkProtocol.json>; rel=describedby");
496e9f71672SEd Tanous }
497e9f71672SEd Tanous 
498e634b34cSEd Tanous inline void handleManagersNetworkProtocolPatch(
499e634b34cSEd Tanous     App& app, const crow::Request& req,
500e634b34cSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
5017e860f15SJohn Edward Broadbent {
5023ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
50345ca1b86SEd Tanous     {
50445ca1b86SEd Tanous         return;
50545ca1b86SEd Tanous     }
506501be32bSraviteja-b     std::optional<std::string> newHostName;
507b9e15228SEd Tanous     std::optional<std::vector<nlohmann::json>> ntpServerObjects;
5085f4c798dSJiaqing Zhao     std::optional<bool> ntpEnabled;
5095f4c798dSJiaqing Zhao     std::optional<bool> ipmiEnabled;
5105f4c798dSJiaqing Zhao     std::optional<bool> sshEnabled;
511501be32bSraviteja-b 
5125f4c798dSJiaqing Zhao     // clang-format off
5135f4c798dSJiaqing Zhao         if (!json_util::readJsonPatch(
5145f4c798dSJiaqing Zhao                 req, asyncResp->res,
5155f4c798dSJiaqing Zhao                 "HostName", newHostName,
516b9e15228SEd Tanous                 "NTP/NTPServers", ntpServerObjects,
5175f4c798dSJiaqing Zhao                 "NTP/ProtocolEnabled", ntpEnabled,
5185f4c798dSJiaqing Zhao                 "IPMI/ProtocolEnabled", ipmiEnabled,
5195f4c798dSJiaqing Zhao                 "SSH/ProtocolEnabled", sshEnabled))
520501be32bSraviteja-b         {
521501be32bSraviteja-b             return;
522501be32bSraviteja-b         }
5235f4c798dSJiaqing Zhao     // clang-format on
524cf05f9dcSJohnathan Mantey 
5258d1b46d7Szhanghch05     asyncResp->res.result(boost::beast::http::status::no_content);
526501be32bSraviteja-b     if (newHostName)
527501be32bSraviteja-b     {
5282db77d34SJohnathan Mantey         messages::propertyNotWritable(asyncResp->res, "HostName");
52944fad2aaSEd Tanous         return;
530cf05f9dcSJohnathan Mantey     }
531cf05f9dcSJohnathan Mantey 
53220e6ea5dSraviteja-b     if (ntpEnabled)
53320e6ea5dSraviteja-b     {
53420e6ea5dSraviteja-b         handleNTPProtocolEnabled(*ntpEnabled, asyncResp);
53520e6ea5dSraviteja-b     }
536b9e15228SEd Tanous     if (ntpServerObjects)
53720e6ea5dSraviteja-b     {
538b9e15228SEd Tanous         getEthernetIfaceData(
539b9e15228SEd Tanous             [asyncResp, ntpServerObjects](
540e634b34cSEd Tanous                 const bool success, std::vector<std::string>& currentNtpServers,
541b9e15228SEd Tanous                 const std::vector<std::string>& /*domainNames*/) {
542b9e15228SEd Tanous             if (!success)
543b9e15228SEd Tanous             {
544b9e15228SEd Tanous                 messages::internalError(asyncResp->res);
545b9e15228SEd Tanous                 return;
546b9e15228SEd Tanous             }
547b9e15228SEd Tanous             handleNTPServersPatch(asyncResp, *ntpServerObjects,
548b9e15228SEd Tanous                                   std::move(currentNtpServers));
549b9e15228SEd Tanous         });
55020e6ea5dSraviteja-b     }
55167a78d87STom Joseph 
5525f4c798dSJiaqing Zhao     if (ipmiEnabled)
55367a78d87STom Joseph     {
554e5a99777SAlbert Zhang         handleProtocolEnabled(
5555f4c798dSJiaqing Zhao             *ipmiEnabled, asyncResp,
55669320d54SJiaqing Zhao             encodeServiceObjectPath(std::string(ipmiServiceName) + '@'));
557e5a99777SAlbert Zhang     }
558e5a99777SAlbert Zhang 
5595f4c798dSJiaqing Zhao     if (sshEnabled)
560e5a99777SAlbert Zhang     {
56169320d54SJiaqing Zhao         handleProtocolEnabled(*sshEnabled, asyncResp,
56269320d54SJiaqing Zhao                               encodeServiceObjectPath(sshServiceName));
56367a78d87STom Joseph     }
564e634b34cSEd Tanous }
565e634b34cSEd Tanous 
566af20dd1cSEd Tanous inline void handleManagersNetworkProtocolHead(
567e634b34cSEd Tanous     App& app, const crow::Request& req,
568e634b34cSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
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");
577af20dd1cSEd Tanous }
578af20dd1cSEd Tanous 
579af20dd1cSEd Tanous inline void handleManagersNetworkProtocolGet(
580af20dd1cSEd Tanous     App& app, const crow::Request& req,
581af20dd1cSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
582af20dd1cSEd Tanous {
583af20dd1cSEd Tanous     handleManagersNetworkProtocolHead(app, req, asyncResp);
584e634b34cSEd Tanous     getNetworkData(asyncResp, req);
585e634b34cSEd Tanous }
586e634b34cSEd Tanous 
587e634b34cSEd Tanous inline void requestRoutesNetworkProtocol(App& app)
588e634b34cSEd Tanous {
589e634b34cSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/")
590e634b34cSEd Tanous         .privileges(redfish::privileges::patchManagerNetworkProtocol)
591e634b34cSEd Tanous         .methods(boost::beast::http::verb::patch)(
592e634b34cSEd Tanous             std::bind_front(handleManagersNetworkProtocolPatch, std::ref(app)));
5937e860f15SJohn Edward Broadbent 
5947e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/")
595e9f71672SEd Tanous         .privileges(redfish::privileges::headManagerNetworkProtocol)
596e9f71672SEd Tanous         .methods(boost::beast::http::verb::head)(
597af20dd1cSEd Tanous             std::bind_front(handleManagersNetworkProtocolHead, std::ref(app)));
598e9f71672SEd Tanous 
599e9f71672SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/")
600ed398213SEd Tanous         .privileges(redfish::privileges::getManagerNetworkProtocol)
6017e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
602e634b34cSEd Tanous             std::bind_front(handleManagersNetworkProtocolGet, std::ref(app)));
603cf05f9dcSJohnathan Mantey }
60470141561SBorawski.Lukasz 
60570141561SBorawski.Lukasz } // namespace redfish
606