xref: /openbmc/bmcweb/features/redfish/lib/network_protocol.hpp (revision 2138483c183b367bb5657d3f4c7354708e67cc47)
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 
183a8a0088SKowalski, Kamil #include "error_messages.hpp"
1967a78d87STom Joseph #include "openbmc_dbus_rest.hpp"
20b4bec66bSAbhishek Patel #include "redfish_util.hpp"
2170141561SBorawski.Lukasz 
227e860f15SJohn Edward Broadbent #include <app.hpp>
23168e20c1SEd Tanous #include <dbus_utility.hpp>
2445ca1b86SEd Tanous #include <query.hpp>
25ed398213SEd Tanous #include <registries/privilege_registry.hpp>
261e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp>
2720e6ea5dSraviteja-b #include <utils/json_utils.hpp>
28287ece64SGeorge Liu #include <utils/stl_utils.hpp>
291214b7e7SGunnar Mills 
301214b7e7SGunnar Mills #include <optional>
31abf2add6SEd Tanous #include <variant>
325f4c798dSJiaqing Zhao 
331abe55efSEd Tanous namespace redfish
341abe55efSEd Tanous {
3570141561SBorawski.Lukasz 
367e860f15SJohn Edward Broadbent void getNTPProtocolEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp);
377e860f15SJohn Edward Broadbent std::string getHostName();
387e860f15SJohn Edward Broadbent 
3969320d54SJiaqing Zhao static constexpr const char* sshServiceName = "dropbear";
4069320d54SJiaqing Zhao static constexpr const char* httpsServiceName = "bmcweb";
4169320d54SJiaqing Zhao static constexpr const char* ipmiServiceName = "phosphor-ipmi-net";
4269320d54SJiaqing Zhao static constexpr std::array<std::pair<const char*, const char*>, 3>
4369320d54SJiaqing Zhao     protocolToService = {{{"SSH", sshServiceName},
4469320d54SJiaqing Zhao                           {"HTTPS", httpsServiceName},
4569320d54SJiaqing Zhao                           {"IPMI", ipmiServiceName}}};
463a8a0088SKowalski, Kamil 
47711ac7a9SEd Tanous inline void extractNTPServersAndDomainNamesData(
48711ac7a9SEd Tanous     const dbus::utility::ManagedObjectType& dbusData,
49532d7697SGunnar Mills     std::vector<std::string>& ntpData, std::vector<std::string>& dnData)
5020e6ea5dSraviteja-b {
5181ce609eSEd Tanous     for (const auto& obj : dbusData)
5220e6ea5dSraviteja-b     {
5320e6ea5dSraviteja-b         for (const auto& ifacePair : obj.second)
5420e6ea5dSraviteja-b         {
550a052baaSGeorge Liu             if (ifacePair.first !=
5620e6ea5dSraviteja-b                 "xyz.openbmc_project.Network.EthernetInterface")
5720e6ea5dSraviteja-b             {
580a052baaSGeorge Liu                 continue;
590a052baaSGeorge Liu             }
600a052baaSGeorge Liu 
6120e6ea5dSraviteja-b             for (const auto& propertyPair : ifacePair.second)
6220e6ea5dSraviteja-b             {
63532d7697SGunnar Mills                 if (propertyPair.first == "NTPServers")
6420e6ea5dSraviteja-b                 {
6520e6ea5dSraviteja-b                     const std::vector<std::string>* ntpServers =
668d78b7a9SPatrick Williams                         std::get_if<std::vector<std::string>>(
6720e6ea5dSraviteja-b                             &propertyPair.second);
6820e6ea5dSraviteja-b                     if (ntpServers != nullptr)
6920e6ea5dSraviteja-b                     {
70f23b7296SEd Tanous                         ntpData = *ntpServers;
7120e6ea5dSraviteja-b                     }
7220e6ea5dSraviteja-b                 }
73d24bfc7aSJennifer Lee                 else if (propertyPair.first == "DomainName")
74d24bfc7aSJennifer Lee                 {
75d24bfc7aSJennifer Lee                     const std::vector<std::string>* domainNames =
768d78b7a9SPatrick Williams                         std::get_if<std::vector<std::string>>(
77d24bfc7aSJennifer Lee                             &propertyPair.second);
78d24bfc7aSJennifer Lee                     if (domainNames != nullptr)
79d24bfc7aSJennifer Lee                     {
80f23b7296SEd Tanous                         dnData = *domainNames;
81d24bfc7aSJennifer Lee                     }
82d24bfc7aSJennifer Lee                 }
8320e6ea5dSraviteja-b             }
8420e6ea5dSraviteja-b         }
8520e6ea5dSraviteja-b     }
860225b87bSEd Tanous     stl_utils::removeDuplicate(ntpData);
8720e6ea5dSraviteja-b }
8820e6ea5dSraviteja-b 
8920e6ea5dSraviteja-b template <typename CallbackFunc>
9020e6ea5dSraviteja-b void getEthernetIfaceData(CallbackFunc&& callback)
9120e6ea5dSraviteja-b {
9220e6ea5dSraviteja-b     crow::connections::systemBus->async_method_call(
93f94c4ecfSEd Tanous         [callback{std::forward<CallbackFunc>(callback)}](
9481ce609eSEd Tanous             const boost::system::error_code errorCode,
95711ac7a9SEd Tanous             const dbus::utility::ManagedObjectType& dbusData) {
9620e6ea5dSraviteja-b         std::vector<std::string> ntpServers;
97d24bfc7aSJennifer Lee         std::vector<std::string> domainNames;
9820e6ea5dSraviteja-b 
9981ce609eSEd Tanous         if (errorCode)
10020e6ea5dSraviteja-b         {
101532d7697SGunnar Mills             callback(false, ntpServers, domainNames);
10220e6ea5dSraviteja-b             return;
10320e6ea5dSraviteja-b         }
10420e6ea5dSraviteja-b 
105532d7697SGunnar Mills         extractNTPServersAndDomainNamesData(dbusData, ntpServers, domainNames);
10620e6ea5dSraviteja-b 
107532d7697SGunnar Mills         callback(true, ntpServers, domainNames);
10820e6ea5dSraviteja-b         },
10920e6ea5dSraviteja-b         "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
11020e6ea5dSraviteja-b         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
111271584abSEd Tanous }
11220e6ea5dSraviteja-b 
1134f48d5f6SEd Tanous inline void getNetworkData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
11472048780SAbhishek Patel                            const crow::Request& req)
1151abe55efSEd Tanous {
116e9f71672SEd Tanous     asyncResp->res.addHeader(
117e9f71672SEd Tanous         boost::beast::http::field::link,
118e9f71672SEd Tanous         "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/NetworkProtocol.json>; rel=describedby");
1190f74e643SEd Tanous     asyncResp->res.jsonValue["@odata.type"] =
120532d7697SGunnar Mills         "#ManagerNetworkProtocol.v1_5_0.ManagerNetworkProtocol";
1210f74e643SEd Tanous     asyncResp->res.jsonValue["@odata.id"] =
1220f74e643SEd Tanous         "/redfish/v1/Managers/bmc/NetworkProtocol";
1230f74e643SEd Tanous     asyncResp->res.jsonValue["Id"] = "NetworkProtocol";
1240f74e643SEd Tanous     asyncResp->res.jsonValue["Name"] = "Manager Network Protocol";
1250f74e643SEd Tanous     asyncResp->res.jsonValue["Description"] = "Manager Network Service";
1260f74e643SEd Tanous     asyncResp->res.jsonValue["Status"]["Health"] = "OK";
1270f74e643SEd Tanous     asyncResp->res.jsonValue["Status"]["HealthRollup"] = "OK";
1280f74e643SEd Tanous     asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
1290f74e643SEd Tanous 
13061932318SXiaochao Ma     // HTTP is Mandatory attribute as per OCP Baseline Profile - v1.0.0,
131818ea7b8SJoshi-Mansi     // but from security perspective it is not recommended to use.
132818ea7b8SJoshi-Mansi     // Hence using protocolEnabled as false to make it OCP and security-wise
133818ea7b8SJoshi-Mansi     // compliant
134818ea7b8SJoshi-Mansi     asyncResp->res.jsonValue["HTTP"]["Port"] = 0;
135818ea7b8SJoshi-Mansi     asyncResp->res.jsonValue["HTTP"]["ProtocolEnabled"] = false;
136818ea7b8SJoshi-Mansi 
137d24bfc7aSJennifer Lee     std::string hostName = getHostName();
138d24bfc7aSJennifer Lee 
139d24bfc7aSJennifer Lee     asyncResp->res.jsonValue["HostName"] = hostName;
1403a8a0088SKowalski, Kamil 
14120e6ea5dSraviteja-b     getNTPProtocolEnabled(asyncResp);
14220e6ea5dSraviteja-b 
143002d39b4SEd Tanous     getEthernetIfaceData(
144002d39b4SEd Tanous         [hostName, asyncResp](const bool& success,
14502cad96eSEd Tanous                               const std::vector<std::string>& ntpServers,
146d24bfc7aSJennifer Lee                               const std::vector<std::string>& domainNames) {
14720e6ea5dSraviteja-b         if (!success)
14820e6ea5dSraviteja-b         {
1490a052baaSGeorge Liu             messages::resourceNotFound(asyncResp->res, "ManagerNetworkProtocol",
1500a052baaSGeorge Liu                                        "NetworkProtocol");
15120e6ea5dSraviteja-b             return;
15220e6ea5dSraviteja-b         }
15320e6ea5dSraviteja-b         asyncResp->res.jsonValue["NTP"]["NTPServers"] = ntpServers;
15426f6976fSEd Tanous         if (!hostName.empty())
155d24bfc7aSJennifer Lee         {
156f23b7296SEd Tanous             std::string fqdn = hostName;
15726f6976fSEd Tanous             if (!domainNames.empty())
158d24bfc7aSJennifer Lee             {
159f23b7296SEd Tanous                 fqdn += ".";
160f23b7296SEd Tanous                 fqdn += domainNames[0];
161d24bfc7aSJennifer Lee             }
1622c70f800SEd Tanous             asyncResp->res.jsonValue["FQDN"] = std::move(fqdn);
163d24bfc7aSJennifer Lee         }
16420e6ea5dSraviteja-b     });
16520e6ea5dSraviteja-b 
16672048780SAbhishek Patel     Privileges effectiveUserPrivileges =
16772048780SAbhishek Patel         redfish::getUserPrivileges(req.userRole);
16872048780SAbhishek Patel 
16972048780SAbhishek Patel     // /redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates is
17072048780SAbhishek Patel     // something only ConfigureManager can access then only display when
17172048780SAbhishek Patel     // the user has permissions ConfigureManager
17272048780SAbhishek Patel     if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
17372048780SAbhishek Patel                                          effectiveUserPrivileges))
17472048780SAbhishek Patel     {
1751476687dSEd Tanous         asyncResp->res.jsonValue["HTTPS"]["Certificates"]["@odata.id"] =
1761476687dSEd Tanous             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates";
17770141561SBorawski.Lukasz     }
17870141561SBorawski.Lukasz 
17969320d54SJiaqing Zhao     for (const auto& protocol : protocolToService)
180ec4974ddSAppaRao Puli     {
181b4bec66bSAbhishek Patel         const std::string& protocolName = protocol.first;
182b4bec66bSAbhishek Patel         const std::string& serviceName = protocol.second;
183b4bec66bSAbhishek Patel         getPortStatusAndPath(
184b4bec66bSAbhishek Patel             serviceName,
185b4bec66bSAbhishek Patel             [asyncResp, protocolName](const boost::system::error_code ec,
186b4bec66bSAbhishek Patel                                       const std::string& socketPath,
187b4bec66bSAbhishek Patel                                       bool isProtocolEnabled) {
1884d875bd8SEd Tanous             // If the service is not installed, that is not an error
1894d875bd8SEd Tanous             if (ec == boost::system::errc::no_such_process)
1904d875bd8SEd Tanous             {
1914d875bd8SEd Tanous                 asyncResp->res.jsonValue[protocolName]["Port"] =
1924d875bd8SEd Tanous                     nlohmann::detail::value_t::null;
1934d875bd8SEd Tanous                 asyncResp->res.jsonValue[protocolName]["ProtocolEnabled"] =
1944d875bd8SEd Tanous                     false;
1954d875bd8SEd Tanous                 return;
1964d875bd8SEd Tanous             }
1971abe55efSEd Tanous             if (ec)
1981abe55efSEd Tanous             {
199a08b46ccSJason M. Bills                 messages::internalError(asyncResp->res);
200865fbb75SEd Tanous                 return;
2013a8a0088SKowalski, Kamil             }
202b4bec66bSAbhishek Patel             asyncResp->res.jsonValue[protocolName]["ProtocolEnabled"] =
203b4bec66bSAbhishek Patel                 isProtocolEnabled;
204002d39b4SEd Tanous             getPortNumber(socketPath, [asyncResp, protocolName](
2058a592810SEd Tanous                                           const boost::system::error_code ec2,
206002d39b4SEd Tanous                                           int portNumber) {
2078a592810SEd Tanous                 if (ec2)
2081abe55efSEd Tanous                 {
209b4bec66bSAbhishek Patel                     messages::internalError(asyncResp->res);
210865fbb75SEd Tanous                     return;
21170141561SBorawski.Lukasz                 }
212002d39b4SEd Tanous                 asyncResp->res.jsonValue[protocolName]["Port"] = portNumber;
213b4bec66bSAbhishek Patel             });
214b4bec66bSAbhishek Patel             });
215865fbb75SEd Tanous     }
216b4bec66bSAbhishek Patel } // namespace redfish
217501be32bSraviteja-b 
2184f48d5f6SEd Tanous inline void handleNTPProtocolEnabled(
2197e860f15SJohn Edward Broadbent     const bool& ntpEnabled, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
22020e6ea5dSraviteja-b {
22120e6ea5dSraviteja-b     std::string timeSyncMethod;
22220e6ea5dSraviteja-b     if (ntpEnabled)
22320e6ea5dSraviteja-b     {
2247e860f15SJohn Edward Broadbent         timeSyncMethod = "xyz.openbmc_project.Time.Synchronization.Method.NTP";
22520e6ea5dSraviteja-b     }
22620e6ea5dSraviteja-b     else
22720e6ea5dSraviteja-b     {
22820e6ea5dSraviteja-b         timeSyncMethod =
22920e6ea5dSraviteja-b             "xyz.openbmc_project.Time.Synchronization.Method.Manual";
23020e6ea5dSraviteja-b     }
23120e6ea5dSraviteja-b 
23220e6ea5dSraviteja-b     crow::connections::systemBus->async_method_call(
23381ce609eSEd Tanous         [asyncResp](const boost::system::error_code errorCode) {
23481ce609eSEd Tanous         if (errorCode)
235cb13a392SEd Tanous         {
236cb13a392SEd Tanous             messages::internalError(asyncResp->res);
237cb13a392SEd Tanous         }
238cb13a392SEd Tanous         },
2397e860f15SJohn Edward Broadbent         "xyz.openbmc_project.Settings", "/xyz/openbmc_project/time/sync_method",
24020e6ea5dSraviteja-b         "org.freedesktop.DBus.Properties", "Set",
24120e6ea5dSraviteja-b         "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod",
242168e20c1SEd Tanous         dbus::utility::DbusVariantType{timeSyncMethod});
24320e6ea5dSraviteja-b }
24420e6ea5dSraviteja-b 
2454f48d5f6SEd Tanous inline void
246287ece64SGeorge Liu     handleNTPServersPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
247b9e15228SEd Tanous                           const std::vector<nlohmann::json>& ntpServerObjects,
248b9e15228SEd Tanous                           std::vector<std::string> currentNtpServers)
24920e6ea5dSraviteja-b {
250b9e15228SEd Tanous     std::vector<std::string>::iterator currentNtpServer =
251b9e15228SEd Tanous         currentNtpServers.begin();
252b9e15228SEd Tanous     for (size_t index = 0; index < ntpServerObjects.size(); index++)
253287ece64SGeorge Liu     {
254b9e15228SEd Tanous         const nlohmann::json& ntpServer = ntpServerObjects[index];
255b9e15228SEd Tanous         if (ntpServer.is_null())
256b9e15228SEd Tanous         {
257b9e15228SEd Tanous             // Can't delete an item that doesn't exist
258b9e15228SEd Tanous             if (currentNtpServer == currentNtpServers.end())
259b9e15228SEd Tanous             {
260b9e15228SEd Tanous                 messages::propertyValueNotInList(asyncResp->res, "null",
261b9e15228SEd Tanous                                                  "NTP/NTPServers/" +
262b9e15228SEd Tanous                                                      std::to_string(index));
263b9e15228SEd Tanous 
264287ece64SGeorge Liu                 return;
265287ece64SGeorge Liu             }
266b9e15228SEd Tanous             currentNtpServer = currentNtpServers.erase(currentNtpServer);
267b9e15228SEd Tanous             continue;
268b9e15228SEd Tanous         }
269b9e15228SEd Tanous         const nlohmann::json::object_t* ntpServerObject =
270b9e15228SEd Tanous             ntpServer.get_ptr<const nlohmann::json::object_t*>();
271b9e15228SEd Tanous         if (ntpServerObject != nullptr)
272b9e15228SEd Tanous         {
273b9e15228SEd Tanous             if (!ntpServerObject->empty())
274b9e15228SEd Tanous             {
275b9e15228SEd Tanous                 messages::propertyValueNotInList(
276b9e15228SEd Tanous                     asyncResp->res,
277b9e15228SEd Tanous                     ntpServer.dump(2, ' ', true,
278b9e15228SEd Tanous                                    nlohmann::json::error_handler_t::replace),
279b9e15228SEd Tanous                     "NTP/NTPServers/" + std::to_string(index));
280b9e15228SEd Tanous                 return;
281b9e15228SEd Tanous             }
282b9e15228SEd Tanous             // Can't retain an item that doesn't exist
283b9e15228SEd Tanous             if (currentNtpServer == currentNtpServers.end())
284b9e15228SEd Tanous             {
285b9e15228SEd Tanous                 messages::propertyValueOutOfRange(
286b9e15228SEd Tanous                     asyncResp->res,
287b9e15228SEd Tanous                     ntpServer.dump(2, ' ', true,
288b9e15228SEd Tanous                                    nlohmann::json::error_handler_t::replace),
289b9e15228SEd Tanous                     "NTP/NTPServers/" + std::to_string(index));
290b9e15228SEd Tanous 
291b9e15228SEd Tanous                 return;
292b9e15228SEd Tanous             }
293b9e15228SEd Tanous             // empty objects should leave the NtpServer unmodified
294b9e15228SEd Tanous             currentNtpServer++;
295b9e15228SEd Tanous             continue;
296b9e15228SEd Tanous         }
297b9e15228SEd Tanous 
298b9e15228SEd Tanous         const std::string* ntpServerStr =
299b9e15228SEd Tanous             ntpServer.get_ptr<const std::string*>();
300b9e15228SEd Tanous         if (ntpServerStr == nullptr)
301b9e15228SEd Tanous         {
302b9e15228SEd Tanous             messages::propertyValueTypeError(
303b9e15228SEd Tanous                 asyncResp->res,
304b9e15228SEd Tanous                 ntpServer.dump(2, ' ', true,
305b9e15228SEd Tanous                                nlohmann::json::error_handler_t::replace),
306b9e15228SEd Tanous                 "NTP/NTPServers/" + std::to_string(index));
307b9e15228SEd Tanous             return;
308b9e15228SEd Tanous         }
309b9e15228SEd Tanous         if (currentNtpServer == currentNtpServers.end())
310b9e15228SEd Tanous         {
311b9e15228SEd Tanous             // if we're at the end of the list, append to the end
312b9e15228SEd Tanous             currentNtpServers.push_back(*ntpServerStr);
313b9e15228SEd Tanous             currentNtpServer = currentNtpServers.end();
314b9e15228SEd Tanous             continue;
315b9e15228SEd Tanous         }
316b9e15228SEd Tanous         *currentNtpServer = *ntpServerStr;
317b9e15228SEd Tanous         currentNtpServer++;
318b9e15228SEd Tanous     }
319b9e15228SEd Tanous 
320b9e15228SEd Tanous     // Any remaining array elements should be removed
321b9e15228SEd Tanous     currentNtpServers.erase(currentNtpServer, currentNtpServers.end());
322287ece64SGeorge Liu 
323*2138483cSGeorge Liu     auto respHandler =
324b9e15228SEd Tanous         [asyncResp, currentNtpServers](
325*2138483cSGeorge Liu             const boost::system::error_code& ec,
326b9d36b47SEd Tanous             const dbus::utility::MapperGetSubTreeResponse& subtree) {
3270a052baaSGeorge Liu         if (ec)
3280a052baaSGeorge Liu         {
329002d39b4SEd Tanous             BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message();
3300a052baaSGeorge Liu             messages::internalError(asyncResp->res);
3310a052baaSGeorge Liu             return;
3320a052baaSGeorge Liu         }
3330a052baaSGeorge Liu 
3340a052baaSGeorge Liu         for (const auto& [objectPath, serviceMap] : subtree)
3350a052baaSGeorge Liu         {
3360a052baaSGeorge Liu             for (const auto& [service, interfaces] : serviceMap)
3370a052baaSGeorge Liu             {
3380a052baaSGeorge Liu                 for (const auto& interface : interfaces)
3390a052baaSGeorge Liu                 {
3400a052baaSGeorge Liu                     if (interface !=
3410a052baaSGeorge Liu                         "xyz.openbmc_project.Network.EthernetInterface")
3420a052baaSGeorge Liu                     {
3430a052baaSGeorge Liu                         continue;
3440a052baaSGeorge Liu                     }
3450a052baaSGeorge Liu 
3460a052baaSGeorge Liu                     crow::connections::systemBus->async_method_call(
3478a592810SEd Tanous                         [asyncResp](const boost::system::error_code ec2) {
3488a592810SEd Tanous                         if (ec2)
34920e6ea5dSraviteja-b                         {
35020e6ea5dSraviteja-b                             messages::internalError(asyncResp->res);
35120e6ea5dSraviteja-b                             return;
35220e6ea5dSraviteja-b                         }
35320e6ea5dSraviteja-b                         },
354002d39b4SEd Tanous                         service, objectPath, "org.freedesktop.DBus.Properties",
355532d7697SGunnar Mills                         "Set", interface, "NTPServers",
356b9e15228SEd Tanous                         dbus::utility::DbusVariantType{currentNtpServers});
35720e6ea5dSraviteja-b                 }
3580a052baaSGeorge Liu             }
3590a052baaSGeorge Liu         }
360*2138483cSGeorge Liu     };
361*2138483cSGeorge Liu 
362*2138483cSGeorge Liu     std::vector<std::string> interfaces = {
363*2138483cSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface"};
364*2138483cSGeorge Liu     dbus::utility::getSubTree("/xyz/openbmc_project", interfaces,
365*2138483cSGeorge Liu                               std::move(respHandler));
3660a052baaSGeorge Liu }
36720e6ea5dSraviteja-b 
3684f48d5f6SEd Tanous inline void
3694f48d5f6SEd Tanous     handleProtocolEnabled(const bool protocolEnabled,
370e5a99777SAlbert Zhang                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
37169320d54SJiaqing Zhao                           const std::string& netBasePath)
37267a78d87STom Joseph {
373*2138483cSGeorge Liu     auto respHandler =
374e5a99777SAlbert Zhang         [protocolEnabled, asyncResp,
375*2138483cSGeorge Liu          netBasePath](const boost::system::error_code& ec,
376b9d36b47SEd Tanous                       const dbus::utility::MapperGetSubTreeResponse& subtree) {
37767a78d87STom Joseph         if (ec)
37867a78d87STom Joseph         {
37967a78d87STom Joseph             messages::internalError(asyncResp->res);
38067a78d87STom Joseph             return;
38167a78d87STom Joseph         }
38267a78d87STom Joseph 
38367a78d87STom Joseph         for (const auto& entry : subtree)
38467a78d87STom Joseph         {
385e5a99777SAlbert Zhang             if (boost::algorithm::starts_with(entry.first, netBasePath))
38667a78d87STom Joseph             {
38767a78d87STom Joseph                 crow::connections::systemBus->async_method_call(
38823a21a1cSEd Tanous                     [asyncResp](const boost::system::error_code ec2) {
38923a21a1cSEd Tanous                     if (ec2)
39067a78d87STom Joseph                     {
39167a78d87STom Joseph                         messages::internalError(asyncResp->res);
39267a78d87STom Joseph                         return;
39367a78d87STom Joseph                     }
39467a78d87STom Joseph                     },
39567a78d87STom Joseph                     entry.second.begin()->first, entry.first,
39667a78d87STom Joseph                     "org.freedesktop.DBus.Properties", "Set",
397002d39b4SEd Tanous                     "xyz.openbmc_project.Control.Service.Attributes", "Running",
398168e20c1SEd Tanous                     dbus::utility::DbusVariantType{protocolEnabled});
39967a78d87STom Joseph 
40067a78d87STom Joseph                 crow::connections::systemBus->async_method_call(
40123a21a1cSEd Tanous                     [asyncResp](const boost::system::error_code ec2) {
40223a21a1cSEd Tanous                     if (ec2)
40367a78d87STom Joseph                     {
40467a78d87STom Joseph                         messages::internalError(asyncResp->res);
40567a78d87STom Joseph                         return;
40667a78d87STom Joseph                     }
40767a78d87STom Joseph                     },
40867a78d87STom Joseph                     entry.second.begin()->first, entry.first,
40967a78d87STom Joseph                     "org.freedesktop.DBus.Properties", "Set",
410002d39b4SEd Tanous                     "xyz.openbmc_project.Control.Service.Attributes", "Enabled",
411168e20c1SEd Tanous                     dbus::utility::DbusVariantType{protocolEnabled});
41267a78d87STom Joseph             }
41367a78d87STom Joseph         }
414*2138483cSGeorge Liu     };
415*2138483cSGeorge Liu 
416*2138483cSGeorge Liu     std::vector<std::string> interfaces = {
417*2138483cSGeorge Liu         "xyz.openbmc_project.Control.Service.Attributes"};
418*2138483cSGeorge Liu     dbus::utility::getSubTree("/xyz/openbmc_project/control/service",
419*2138483cSGeorge Liu                               interfaces, std::move(respHandler));
42067a78d87STom Joseph }
42167a78d87STom Joseph 
4224f48d5f6SEd Tanous inline std::string getHostName()
423501be32bSraviteja-b {
4247e860f15SJohn Edward Broadbent     std::string hostName;
4258d1b46d7Szhanghch05 
426d3a9e084SEd Tanous     std::array<char, HOST_NAME_MAX> hostNameCStr{};
4277e860f15SJohn Edward Broadbent     if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0)
4287e860f15SJohn Edward Broadbent     {
4297e860f15SJohn Edward Broadbent         hostName = hostNameCStr.data();
4307e860f15SJohn Edward Broadbent     }
4317e860f15SJohn Edward Broadbent     return hostName;
4327e860f15SJohn Edward Broadbent }
4337e860f15SJohn Edward Broadbent 
4344f48d5f6SEd Tanous inline void
4354f48d5f6SEd Tanous     getNTPProtocolEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
4367e860f15SJohn Edward Broadbent {
4371e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
4381e1e598dSJonathan Doman         *crow::connections::systemBus, "xyz.openbmc_project.Settings",
4391e1e598dSJonathan Doman         "/xyz/openbmc_project/time/sync_method",
4401e1e598dSJonathan Doman         "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod",
4417e860f15SJohn Edward Broadbent         [asyncResp](const boost::system::error_code errorCode,
4421e1e598dSJonathan Doman                     const std::string& timeSyncMethod) {
4437e860f15SJohn Edward Broadbent         if (errorCode)
4447e860f15SJohn Edward Broadbent         {
4457e860f15SJohn Edward Broadbent             return;
4467e860f15SJohn Edward Broadbent         }
4477e860f15SJohn Edward Broadbent 
4481e1e598dSJonathan Doman         if (timeSyncMethod ==
4491e1e598dSJonathan Doman             "xyz.openbmc_project.Time.Synchronization.Method.NTP")
4507e860f15SJohn Edward Broadbent         {
4517e860f15SJohn Edward Broadbent             asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = true;
4527e860f15SJohn Edward Broadbent         }
453002d39b4SEd Tanous         else if (timeSyncMethod == "xyz.openbmc_project.Time.Synchronization."
4541e1e598dSJonathan Doman                                    "Method.Manual")
4557e860f15SJohn Edward Broadbent         {
4567e860f15SJohn Edward Broadbent             asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = false;
4577e860f15SJohn Edward Broadbent         }
4581e1e598dSJonathan Doman         });
4597e860f15SJohn Edward Broadbent }
4607e860f15SJohn Edward Broadbent 
46169320d54SJiaqing Zhao inline std::string encodeServiceObjectPath(const std::string& serviceName)
46269320d54SJiaqing Zhao {
46369320d54SJiaqing Zhao     sdbusplus::message::object_path objPath(
46469320d54SJiaqing Zhao         "/xyz/openbmc_project/control/service");
46569320d54SJiaqing Zhao     objPath /= serviceName;
46669320d54SJiaqing Zhao     return objPath.str;
46769320d54SJiaqing Zhao }
46869320d54SJiaqing Zhao 
469e9f71672SEd Tanous void handleBmcNetworkProtocolHead(
470e9f71672SEd Tanous     crow::App& app, const crow::Request& req,
471e9f71672SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
472e9f71672SEd Tanous {
473e9f71672SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
474e9f71672SEd Tanous     {
475e9f71672SEd Tanous         return;
476e9f71672SEd Tanous     }
477e9f71672SEd Tanous     asyncResp->res.addHeader(
478e9f71672SEd Tanous         boost::beast::http::field::link,
479e9f71672SEd Tanous         "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/ManagerNetworkProtocol.json>; rel=describedby");
480e9f71672SEd Tanous }
481e9f71672SEd Tanous 
4827e860f15SJohn Edward Broadbent inline void requestRoutesNetworkProtocol(App& app)
4837e860f15SJohn Edward Broadbent {
4847e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/")
485ed398213SEd Tanous         .privileges(redfish::privileges::patchManagerNetworkProtocol)
486002d39b4SEd Tanous         .methods(boost::beast::http::verb::patch)(
487002d39b4SEd Tanous             [&app](const crow::Request& req,
488002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
4893ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
49045ca1b86SEd Tanous         {
49145ca1b86SEd Tanous             return;
49245ca1b86SEd Tanous         }
493501be32bSraviteja-b         std::optional<std::string> newHostName;
494b9e15228SEd Tanous         std::optional<std::vector<nlohmann::json>> ntpServerObjects;
4955f4c798dSJiaqing Zhao         std::optional<bool> ntpEnabled;
4965f4c798dSJiaqing Zhao         std::optional<bool> ipmiEnabled;
4975f4c798dSJiaqing Zhao         std::optional<bool> sshEnabled;
498501be32bSraviteja-b 
4995f4c798dSJiaqing Zhao         // clang-format off
5005f4c798dSJiaqing Zhao         if (!json_util::readJsonPatch(
5015f4c798dSJiaqing Zhao                 req, asyncResp->res,
5025f4c798dSJiaqing Zhao                 "HostName", newHostName,
503b9e15228SEd Tanous                 "NTP/NTPServers", ntpServerObjects,
5045f4c798dSJiaqing Zhao                 "NTP/ProtocolEnabled", ntpEnabled,
5055f4c798dSJiaqing Zhao                 "IPMI/ProtocolEnabled", ipmiEnabled,
5065f4c798dSJiaqing Zhao                 "SSH/ProtocolEnabled", sshEnabled))
507501be32bSraviteja-b         {
508501be32bSraviteja-b             return;
509501be32bSraviteja-b         }
5105f4c798dSJiaqing Zhao         // clang-format on
511cf05f9dcSJohnathan Mantey 
5128d1b46d7Szhanghch05         asyncResp->res.result(boost::beast::http::status::no_content);
513501be32bSraviteja-b         if (newHostName)
514501be32bSraviteja-b         {
5152db77d34SJohnathan Mantey             messages::propertyNotWritable(asyncResp->res, "HostName");
51644fad2aaSEd Tanous             return;
517cf05f9dcSJohnathan Mantey         }
518cf05f9dcSJohnathan Mantey 
51920e6ea5dSraviteja-b         if (ntpEnabled)
52020e6ea5dSraviteja-b         {
52120e6ea5dSraviteja-b             handleNTPProtocolEnabled(*ntpEnabled, asyncResp);
52220e6ea5dSraviteja-b         }
523b9e15228SEd Tanous         if (ntpServerObjects)
52420e6ea5dSraviteja-b         {
525b9e15228SEd Tanous             getEthernetIfaceData(
526b9e15228SEd Tanous                 [asyncResp, ntpServerObjects](
527b9e15228SEd Tanous                     const bool success,
528b9e15228SEd Tanous                     std::vector<std::string>& currentNtpServers,
529b9e15228SEd Tanous                     const std::vector<std::string>& /*domainNames*/) {
530b9e15228SEd Tanous                 if (!success)
531b9e15228SEd Tanous                 {
532b9e15228SEd Tanous                     messages::internalError(asyncResp->res);
533b9e15228SEd Tanous                     return;
534b9e15228SEd Tanous                 }
535b9e15228SEd Tanous                 handleNTPServersPatch(asyncResp, *ntpServerObjects,
536b9e15228SEd Tanous                                       std::move(currentNtpServers));
537b9e15228SEd Tanous             });
53820e6ea5dSraviteja-b         }
53967a78d87STom Joseph 
5405f4c798dSJiaqing Zhao         if (ipmiEnabled)
54167a78d87STom Joseph         {
542e5a99777SAlbert Zhang             handleProtocolEnabled(
5435f4c798dSJiaqing Zhao                 *ipmiEnabled, asyncResp,
54469320d54SJiaqing Zhao                 encodeServiceObjectPath(std::string(ipmiServiceName) + '@'));
545e5a99777SAlbert Zhang         }
546e5a99777SAlbert Zhang 
5475f4c798dSJiaqing Zhao         if (sshEnabled)
548e5a99777SAlbert Zhang         {
54969320d54SJiaqing Zhao             handleProtocolEnabled(*sshEnabled, asyncResp,
55069320d54SJiaqing Zhao                                   encodeServiceObjectPath(sshServiceName));
55167a78d87STom Joseph         }
5527e860f15SJohn Edward Broadbent         });
5537e860f15SJohn Edward Broadbent 
5547e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/")
555e9f71672SEd Tanous         .privileges(redfish::privileges::headManagerNetworkProtocol)
556e9f71672SEd Tanous         .methods(boost::beast::http::verb::head)(
557e9f71672SEd Tanous             std::bind_front(handleBmcNetworkProtocolHead, std::ref(app)));
558e9f71672SEd Tanous 
559e9f71672SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/")
560ed398213SEd Tanous         .privileges(redfish::privileges::getManagerNetworkProtocol)
5617e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
56245ca1b86SEd Tanous             [&app](const crow::Request& req,
5637e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
5643ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
56545ca1b86SEd Tanous         {
56645ca1b86SEd Tanous             return;
56745ca1b86SEd Tanous         }
56872048780SAbhishek Patel         getNetworkData(asyncResp, req);
5697e860f15SJohn Edward Broadbent         });
570cf05f9dcSJohnathan Mantey }
57170141561SBorawski.Lukasz 
57270141561SBorawski.Lukasz } // namespace redfish
573