xref: /openbmc/bmcweb/features/redfish/lib/network_protocol.hpp (revision e634b34c08feefd977399afc5e745e77c4baa815)
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 
4269320d54SJiaqing Zhao static constexpr const char* sshServiceName = "dropbear";
4369320d54SJiaqing Zhao static constexpr const char* httpsServiceName = "bmcweb";
4469320d54SJiaqing Zhao static constexpr const char* ipmiServiceName = "phosphor-ipmi-net";
4569320d54SJiaqing Zhao static constexpr std::array<std::pair<const char*, const char*>, 3>
4669320d54SJiaqing Zhao     protocolToService = {{{"SSH", sshServiceName},
4769320d54SJiaqing Zhao                           {"HTTPS", httpsServiceName},
4869320d54SJiaqing Zhao                           {"IPMI", ipmiServiceName}}};
493a8a0088SKowalski, Kamil 
50711ac7a9SEd Tanous inline void extractNTPServersAndDomainNamesData(
51711ac7a9SEd Tanous     const dbus::utility::ManagedObjectType& dbusData,
52532d7697SGunnar Mills     std::vector<std::string>& ntpData, std::vector<std::string>& dnData)
5320e6ea5dSraviteja-b {
5481ce609eSEd Tanous     for (const auto& obj : dbusData)
5520e6ea5dSraviteja-b     {
5620e6ea5dSraviteja-b         for (const auto& ifacePair : obj.second)
5720e6ea5dSraviteja-b         {
580a052baaSGeorge Liu             if (ifacePair.first !=
5920e6ea5dSraviteja-b                 "xyz.openbmc_project.Network.EthernetInterface")
6020e6ea5dSraviteja-b             {
610a052baaSGeorge Liu                 continue;
620a052baaSGeorge Liu             }
630a052baaSGeorge Liu 
6420e6ea5dSraviteja-b             for (const auto& propertyPair : ifacePair.second)
6520e6ea5dSraviteja-b             {
66fcd2682aSEd Tanous                 if (propertyPair.first == "StaticNTPServers")
6720e6ea5dSraviteja-b                 {
6820e6ea5dSraviteja-b                     const std::vector<std::string>* ntpServers =
698d78b7a9SPatrick Williams                         std::get_if<std::vector<std::string>>(
7020e6ea5dSraviteja-b                             &propertyPair.second);
7120e6ea5dSraviteja-b                     if (ntpServers != nullptr)
7220e6ea5dSraviteja-b                     {
73f23b7296SEd Tanous                         ntpData = *ntpServers;
7420e6ea5dSraviteja-b                     }
7520e6ea5dSraviteja-b                 }
76d24bfc7aSJennifer Lee                 else if (propertyPair.first == "DomainName")
77d24bfc7aSJennifer Lee                 {
78d24bfc7aSJennifer Lee                     const std::vector<std::string>* domainNames =
798d78b7a9SPatrick Williams                         std::get_if<std::vector<std::string>>(
80d24bfc7aSJennifer Lee                             &propertyPair.second);
81d24bfc7aSJennifer Lee                     if (domainNames != nullptr)
82d24bfc7aSJennifer Lee                     {
83f23b7296SEd Tanous                         dnData = *domainNames;
84d24bfc7aSJennifer Lee                     }
85d24bfc7aSJennifer Lee                 }
8620e6ea5dSraviteja-b             }
8720e6ea5dSraviteja-b         }
8820e6ea5dSraviteja-b     }
890225b87bSEd Tanous     stl_utils::removeDuplicate(ntpData);
9020e6ea5dSraviteja-b }
9120e6ea5dSraviteja-b 
9220e6ea5dSraviteja-b template <typename CallbackFunc>
9320e6ea5dSraviteja-b void getEthernetIfaceData(CallbackFunc&& callback)
9420e6ea5dSraviteja-b {
9520e6ea5dSraviteja-b     crow::connections::systemBus->async_method_call(
96f94c4ecfSEd Tanous         [callback{std::forward<CallbackFunc>(callback)}](
975e7e2dc5SEd Tanous             const boost::system::error_code& errorCode,
98711ac7a9SEd Tanous             const dbus::utility::ManagedObjectType& dbusData) {
9920e6ea5dSraviteja-b         std::vector<std::string> ntpServers;
100d24bfc7aSJennifer Lee         std::vector<std::string> domainNames;
10120e6ea5dSraviteja-b 
10281ce609eSEd Tanous         if (errorCode)
10320e6ea5dSraviteja-b         {
104532d7697SGunnar Mills             callback(false, ntpServers, domainNames);
10520e6ea5dSraviteja-b             return;
10620e6ea5dSraviteja-b         }
10720e6ea5dSraviteja-b 
108532d7697SGunnar Mills         extractNTPServersAndDomainNamesData(dbusData, ntpServers, domainNames);
10920e6ea5dSraviteja-b 
110532d7697SGunnar Mills         callback(true, ntpServers, domainNames);
11120e6ea5dSraviteja-b         },
11220e6ea5dSraviteja-b         "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
11320e6ea5dSraviteja-b         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
114271584abSEd Tanous }
11520e6ea5dSraviteja-b 
1164f48d5f6SEd Tanous inline void getNetworkData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
11772048780SAbhishek Patel                            const crow::Request& req)
1181abe55efSEd Tanous {
119e9f71672SEd Tanous     asyncResp->res.addHeader(
120e9f71672SEd Tanous         boost::beast::http::field::link,
121e9f71672SEd Tanous         "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/NetworkProtocol.json>; rel=describedby");
1220f74e643SEd Tanous     asyncResp->res.jsonValue["@odata.type"] =
123532d7697SGunnar Mills         "#ManagerNetworkProtocol.v1_5_0.ManagerNetworkProtocol";
1240f74e643SEd Tanous     asyncResp->res.jsonValue["@odata.id"] =
1250f74e643SEd Tanous         "/redfish/v1/Managers/bmc/NetworkProtocol";
1260f74e643SEd Tanous     asyncResp->res.jsonValue["Id"] = "NetworkProtocol";
1270f74e643SEd Tanous     asyncResp->res.jsonValue["Name"] = "Manager Network Protocol";
1280f74e643SEd Tanous     asyncResp->res.jsonValue["Description"] = "Manager Network Service";
1290f74e643SEd Tanous     asyncResp->res.jsonValue["Status"]["Health"] = "OK";
1300f74e643SEd Tanous     asyncResp->res.jsonValue["Status"]["HealthRollup"] = "OK";
1310f74e643SEd Tanous     asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
1320f74e643SEd Tanous 
13361932318SXiaochao Ma     // HTTP is Mandatory attribute as per OCP Baseline Profile - v1.0.0,
134818ea7b8SJoshi-Mansi     // but from security perspective it is not recommended to use.
135818ea7b8SJoshi-Mansi     // Hence using protocolEnabled as false to make it OCP and security-wise
136818ea7b8SJoshi-Mansi     // compliant
137818ea7b8SJoshi-Mansi     asyncResp->res.jsonValue["HTTP"]["Port"] = 0;
138818ea7b8SJoshi-Mansi     asyncResp->res.jsonValue["HTTP"]["ProtocolEnabled"] = false;
139818ea7b8SJoshi-Mansi 
140d24bfc7aSJennifer Lee     std::string hostName = getHostName();
141d24bfc7aSJennifer Lee 
142d24bfc7aSJennifer Lee     asyncResp->res.jsonValue["HostName"] = hostName;
1433a8a0088SKowalski, Kamil 
14420e6ea5dSraviteja-b     getNTPProtocolEnabled(asyncResp);
14520e6ea5dSraviteja-b 
146002d39b4SEd Tanous     getEthernetIfaceData(
147002d39b4SEd Tanous         [hostName, asyncResp](const bool& success,
14802cad96eSEd Tanous                               const std::vector<std::string>& ntpServers,
149d24bfc7aSJennifer Lee                               const std::vector<std::string>& domainNames) {
15020e6ea5dSraviteja-b         if (!success)
15120e6ea5dSraviteja-b         {
1520a052baaSGeorge Liu             messages::resourceNotFound(asyncResp->res, "ManagerNetworkProtocol",
1530a052baaSGeorge Liu                                        "NetworkProtocol");
15420e6ea5dSraviteja-b             return;
15520e6ea5dSraviteja-b         }
15620e6ea5dSraviteja-b         asyncResp->res.jsonValue["NTP"]["NTPServers"] = ntpServers;
15726f6976fSEd Tanous         if (!hostName.empty())
158d24bfc7aSJennifer Lee         {
159f23b7296SEd Tanous             std::string fqdn = hostName;
16026f6976fSEd Tanous             if (!domainNames.empty())
161d24bfc7aSJennifer Lee             {
162f23b7296SEd Tanous                 fqdn += ".";
163f23b7296SEd Tanous                 fqdn += domainNames[0];
164d24bfc7aSJennifer Lee             }
1652c70f800SEd Tanous             asyncResp->res.jsonValue["FQDN"] = std::move(fqdn);
166d24bfc7aSJennifer Lee         }
16720e6ea5dSraviteja-b     });
16820e6ea5dSraviteja-b 
16972048780SAbhishek Patel     Privileges effectiveUserPrivileges =
17072048780SAbhishek Patel         redfish::getUserPrivileges(req.userRole);
17172048780SAbhishek Patel 
17272048780SAbhishek Patel     // /redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates is
17372048780SAbhishek Patel     // something only ConfigureManager can access then only display when
17472048780SAbhishek Patel     // the user has permissions ConfigureManager
17572048780SAbhishek Patel     if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
17672048780SAbhishek Patel                                          effectiveUserPrivileges))
17772048780SAbhishek Patel     {
1781476687dSEd Tanous         asyncResp->res.jsonValue["HTTPS"]["Certificates"]["@odata.id"] =
1791476687dSEd Tanous             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates";
18070141561SBorawski.Lukasz     }
18170141561SBorawski.Lukasz 
18269320d54SJiaqing Zhao     for (const auto& protocol : protocolToService)
183ec4974ddSAppaRao Puli     {
184b4bec66bSAbhishek Patel         const std::string& protocolName = protocol.first;
185b4bec66bSAbhishek Patel         const std::string& serviceName = protocol.second;
186b4bec66bSAbhishek Patel         getPortStatusAndPath(
187b4bec66bSAbhishek Patel             serviceName,
1885e7e2dc5SEd Tanous             [asyncResp, protocolName](const boost::system::error_code& ec,
189b4bec66bSAbhishek Patel                                       const std::string& socketPath,
190b4bec66bSAbhishek Patel                                       bool isProtocolEnabled) {
1914d875bd8SEd Tanous             // If the service is not installed, that is not an error
1924d875bd8SEd Tanous             if (ec == boost::system::errc::no_such_process)
1934d875bd8SEd Tanous             {
1944d875bd8SEd Tanous                 asyncResp->res.jsonValue[protocolName]["Port"] =
1954d875bd8SEd Tanous                     nlohmann::detail::value_t::null;
1964d875bd8SEd Tanous                 asyncResp->res.jsonValue[protocolName]["ProtocolEnabled"] =
1974d875bd8SEd Tanous                     false;
1984d875bd8SEd Tanous                 return;
1994d875bd8SEd Tanous             }
2001abe55efSEd Tanous             if (ec)
2011abe55efSEd Tanous             {
202a08b46ccSJason M. Bills                 messages::internalError(asyncResp->res);
203865fbb75SEd Tanous                 return;
2043a8a0088SKowalski, Kamil             }
205b4bec66bSAbhishek Patel             asyncResp->res.jsonValue[protocolName]["ProtocolEnabled"] =
206b4bec66bSAbhishek Patel                 isProtocolEnabled;
207002d39b4SEd Tanous             getPortNumber(socketPath, [asyncResp, protocolName](
2085e7e2dc5SEd Tanous                                           const boost::system::error_code& ec2,
209002d39b4SEd Tanous                                           int portNumber) {
2108a592810SEd Tanous                 if (ec2)
2111abe55efSEd Tanous                 {
212b4bec66bSAbhishek Patel                     messages::internalError(asyncResp->res);
213865fbb75SEd Tanous                     return;
21470141561SBorawski.Lukasz                 }
215002d39b4SEd Tanous                 asyncResp->res.jsonValue[protocolName]["Port"] = portNumber;
216b4bec66bSAbhishek Patel             });
217b4bec66bSAbhishek Patel             });
218865fbb75SEd Tanous     }
219b4bec66bSAbhishek Patel } // namespace redfish
220501be32bSraviteja-b 
2214f48d5f6SEd Tanous inline void handleNTPProtocolEnabled(
2227e860f15SJohn Edward Broadbent     const bool& ntpEnabled, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
22320e6ea5dSraviteja-b {
22420e6ea5dSraviteja-b     std::string timeSyncMethod;
22520e6ea5dSraviteja-b     if (ntpEnabled)
22620e6ea5dSraviteja-b     {
2277e860f15SJohn Edward Broadbent         timeSyncMethod = "xyz.openbmc_project.Time.Synchronization.Method.NTP";
22820e6ea5dSraviteja-b     }
22920e6ea5dSraviteja-b     else
23020e6ea5dSraviteja-b     {
23120e6ea5dSraviteja-b         timeSyncMethod =
23220e6ea5dSraviteja-b             "xyz.openbmc_project.Time.Synchronization.Method.Manual";
23320e6ea5dSraviteja-b     }
23420e6ea5dSraviteja-b 
23520e6ea5dSraviteja-b     crow::connections::systemBus->async_method_call(
2365e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& errorCode) {
23781ce609eSEd Tanous         if (errorCode)
238cb13a392SEd Tanous         {
239cb13a392SEd Tanous             messages::internalError(asyncResp->res);
240cb13a392SEd Tanous         }
241cb13a392SEd Tanous         },
2427e860f15SJohn Edward Broadbent         "xyz.openbmc_project.Settings", "/xyz/openbmc_project/time/sync_method",
24320e6ea5dSraviteja-b         "org.freedesktop.DBus.Properties", "Set",
24420e6ea5dSraviteja-b         "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod",
245168e20c1SEd Tanous         dbus::utility::DbusVariantType{timeSyncMethod});
24620e6ea5dSraviteja-b }
24720e6ea5dSraviteja-b 
2484f48d5f6SEd Tanous inline void
249287ece64SGeorge Liu     handleNTPServersPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
250b9e15228SEd Tanous                           const std::vector<nlohmann::json>& ntpServerObjects,
251b9e15228SEd Tanous                           std::vector<std::string> currentNtpServers)
25220e6ea5dSraviteja-b {
253b9e15228SEd Tanous     std::vector<std::string>::iterator currentNtpServer =
254b9e15228SEd Tanous         currentNtpServers.begin();
255b9e15228SEd Tanous     for (size_t index = 0; index < ntpServerObjects.size(); index++)
256287ece64SGeorge Liu     {
257b9e15228SEd Tanous         const nlohmann::json& ntpServer = ntpServerObjects[index];
258b9e15228SEd Tanous         if (ntpServer.is_null())
259b9e15228SEd Tanous         {
260b9e15228SEd Tanous             // Can't delete an item that doesn't exist
261b9e15228SEd Tanous             if (currentNtpServer == currentNtpServers.end())
262b9e15228SEd Tanous             {
263b9e15228SEd Tanous                 messages::propertyValueNotInList(asyncResp->res, "null",
264b9e15228SEd Tanous                                                  "NTP/NTPServers/" +
265b9e15228SEd Tanous                                                      std::to_string(index));
266b9e15228SEd Tanous 
267287ece64SGeorge Liu                 return;
268287ece64SGeorge Liu             }
269b9e15228SEd Tanous             currentNtpServer = currentNtpServers.erase(currentNtpServer);
270b9e15228SEd Tanous             continue;
271b9e15228SEd Tanous         }
272b9e15228SEd Tanous         const nlohmann::json::object_t* ntpServerObject =
273b9e15228SEd Tanous             ntpServer.get_ptr<const nlohmann::json::object_t*>();
274b9e15228SEd Tanous         if (ntpServerObject != nullptr)
275b9e15228SEd Tanous         {
276b9e15228SEd Tanous             if (!ntpServerObject->empty())
277b9e15228SEd Tanous             {
278b9e15228SEd Tanous                 messages::propertyValueNotInList(
279b9e15228SEd Tanous                     asyncResp->res,
280b9e15228SEd Tanous                     ntpServer.dump(2, ' ', true,
281b9e15228SEd Tanous                                    nlohmann::json::error_handler_t::replace),
282b9e15228SEd Tanous                     "NTP/NTPServers/" + std::to_string(index));
283b9e15228SEd Tanous                 return;
284b9e15228SEd Tanous             }
285b9e15228SEd Tanous             // Can't retain an item that doesn't exist
286b9e15228SEd Tanous             if (currentNtpServer == currentNtpServers.end())
287b9e15228SEd Tanous             {
288b9e15228SEd Tanous                 messages::propertyValueOutOfRange(
289b9e15228SEd Tanous                     asyncResp->res,
290b9e15228SEd Tanous                     ntpServer.dump(2, ' ', true,
291b9e15228SEd Tanous                                    nlohmann::json::error_handler_t::replace),
292b9e15228SEd Tanous                     "NTP/NTPServers/" + std::to_string(index));
293b9e15228SEd Tanous 
294b9e15228SEd Tanous                 return;
295b9e15228SEd Tanous             }
296b9e15228SEd Tanous             // empty objects should leave the NtpServer unmodified
297b9e15228SEd Tanous             currentNtpServer++;
298b9e15228SEd Tanous             continue;
299b9e15228SEd Tanous         }
300b9e15228SEd Tanous 
301b9e15228SEd Tanous         const std::string* ntpServerStr =
302b9e15228SEd Tanous             ntpServer.get_ptr<const std::string*>();
303b9e15228SEd Tanous         if (ntpServerStr == nullptr)
304b9e15228SEd Tanous         {
305b9e15228SEd Tanous             messages::propertyValueTypeError(
306b9e15228SEd Tanous                 asyncResp->res,
307b9e15228SEd Tanous                 ntpServer.dump(2, ' ', true,
308b9e15228SEd Tanous                                nlohmann::json::error_handler_t::replace),
309b9e15228SEd Tanous                 "NTP/NTPServers/" + std::to_string(index));
310b9e15228SEd Tanous             return;
311b9e15228SEd Tanous         }
312b9e15228SEd Tanous         if (currentNtpServer == currentNtpServers.end())
313b9e15228SEd Tanous         {
314b9e15228SEd Tanous             // if we're at the end of the list, append to the end
315b9e15228SEd Tanous             currentNtpServers.push_back(*ntpServerStr);
316b9e15228SEd Tanous             currentNtpServer = currentNtpServers.end();
317b9e15228SEd Tanous             continue;
318b9e15228SEd Tanous         }
319b9e15228SEd Tanous         *currentNtpServer = *ntpServerStr;
320b9e15228SEd Tanous         currentNtpServer++;
321b9e15228SEd Tanous     }
322b9e15228SEd Tanous 
323b9e15228SEd Tanous     // Any remaining array elements should be removed
324b9e15228SEd Tanous     currentNtpServers.erase(currentNtpServer, currentNtpServers.end());
325287ece64SGeorge Liu 
326e99073f5SGeorge Liu     constexpr std::array<std::string_view, 1> ethInterfaces = {
327e99073f5SGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface"};
328e99073f5SGeorge Liu     dbus::utility::getSubTree(
329e99073f5SGeorge Liu         "/xyz/openbmc_project", 0, ethInterfaces,
330b9e15228SEd Tanous         [asyncResp, currentNtpServers](
3312138483cSGeorge Liu             const boost::system::error_code& ec,
332b9d36b47SEd Tanous             const dbus::utility::MapperGetSubTreeResponse& subtree) {
3330a052baaSGeorge Liu         if (ec)
3340a052baaSGeorge Liu         {
335002d39b4SEd Tanous             BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message();
3360a052baaSGeorge Liu             messages::internalError(asyncResp->res);
3370a052baaSGeorge Liu             return;
3380a052baaSGeorge Liu         }
3390a052baaSGeorge Liu 
3400a052baaSGeorge Liu         for (const auto& [objectPath, serviceMap] : subtree)
3410a052baaSGeorge Liu         {
3420a052baaSGeorge Liu             for (const auto& [service, interfaces] : serviceMap)
3430a052baaSGeorge Liu             {
3440a052baaSGeorge Liu                 for (const auto& interface : interfaces)
3450a052baaSGeorge Liu                 {
3460a052baaSGeorge Liu                     if (interface !=
3470a052baaSGeorge Liu                         "xyz.openbmc_project.Network.EthernetInterface")
3480a052baaSGeorge Liu                     {
3490a052baaSGeorge Liu                         continue;
3500a052baaSGeorge Liu                     }
3510a052baaSGeorge Liu 
3520a052baaSGeorge Liu                     crow::connections::systemBus->async_method_call(
3535e7e2dc5SEd Tanous                         [asyncResp](const boost::system::error_code& ec2) {
3548a592810SEd Tanous                         if (ec2)
35520e6ea5dSraviteja-b                         {
35620e6ea5dSraviteja-b                             messages::internalError(asyncResp->res);
35720e6ea5dSraviteja-b                             return;
35820e6ea5dSraviteja-b                         }
35920e6ea5dSraviteja-b                         },
360002d39b4SEd Tanous                         service, objectPath, "org.freedesktop.DBus.Properties",
361fcd2682aSEd Tanous                         "Set", interface, "StaticNTPServers",
362b9e15228SEd Tanous                         dbus::utility::DbusVariantType{currentNtpServers});
36320e6ea5dSraviteja-b                 }
3640a052baaSGeorge Liu             }
3650a052baaSGeorge Liu         }
366e99073f5SGeorge Liu         });
3670a052baaSGeorge Liu }
36820e6ea5dSraviteja-b 
3694f48d5f6SEd Tanous inline void
3704f48d5f6SEd Tanous     handleProtocolEnabled(const bool protocolEnabled,
371e5a99777SAlbert Zhang                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
37269320d54SJiaqing Zhao                           const std::string& netBasePath)
37367a78d87STom Joseph {
374e99073f5SGeorge Liu     constexpr std::array<std::string_view, 1> interfaces = {
375e99073f5SGeorge Liu         "xyz.openbmc_project.Control.Service.Attributes"};
376e99073f5SGeorge Liu     dbus::utility::getSubTree(
377e99073f5SGeorge Liu         "/xyz/openbmc_project/control/service", 0, interfaces,
378e5a99777SAlbert Zhang         [protocolEnabled, asyncResp,
3792138483cSGeorge Liu          netBasePath](const boost::system::error_code& ec,
380b9d36b47SEd Tanous                       const dbus::utility::MapperGetSubTreeResponse& subtree) {
38167a78d87STom Joseph         if (ec)
38267a78d87STom Joseph         {
38367a78d87STom Joseph             messages::internalError(asyncResp->res);
38467a78d87STom Joseph             return;
38567a78d87STom Joseph         }
38667a78d87STom Joseph 
38767a78d87STom Joseph         for (const auto& entry : subtree)
38867a78d87STom Joseph         {
389e5a99777SAlbert Zhang             if (boost::algorithm::starts_with(entry.first, netBasePath))
39067a78d87STom Joseph             {
39167a78d87STom Joseph                 crow::connections::systemBus->async_method_call(
3925e7e2dc5SEd Tanous                     [asyncResp](const boost::system::error_code& ec2) {
39323a21a1cSEd Tanous                     if (ec2)
39467a78d87STom Joseph                     {
39567a78d87STom Joseph                         messages::internalError(asyncResp->res);
39667a78d87STom Joseph                         return;
39767a78d87STom Joseph                     }
39867a78d87STom Joseph                     },
39967a78d87STom Joseph                     entry.second.begin()->first, entry.first,
40067a78d87STom Joseph                     "org.freedesktop.DBus.Properties", "Set",
401002d39b4SEd Tanous                     "xyz.openbmc_project.Control.Service.Attributes", "Running",
402168e20c1SEd Tanous                     dbus::utility::DbusVariantType{protocolEnabled});
40367a78d87STom Joseph 
40467a78d87STom Joseph                 crow::connections::systemBus->async_method_call(
4055e7e2dc5SEd Tanous                     [asyncResp](const boost::system::error_code& ec2) {
40623a21a1cSEd Tanous                     if (ec2)
40767a78d87STom Joseph                     {
40867a78d87STom Joseph                         messages::internalError(asyncResp->res);
40967a78d87STom Joseph                         return;
41067a78d87STom Joseph                     }
41167a78d87STom Joseph                     },
41267a78d87STom Joseph                     entry.second.begin()->first, entry.first,
41367a78d87STom Joseph                     "org.freedesktop.DBus.Properties", "Set",
414002d39b4SEd Tanous                     "xyz.openbmc_project.Control.Service.Attributes", "Enabled",
415168e20c1SEd Tanous                     dbus::utility::DbusVariantType{protocolEnabled});
41667a78d87STom Joseph             }
41767a78d87STom Joseph         }
418e99073f5SGeorge Liu         });
41967a78d87STom Joseph }
42067a78d87STom Joseph 
4214f48d5f6SEd Tanous inline std::string getHostName()
422501be32bSraviteja-b {
4237e860f15SJohn Edward Broadbent     std::string hostName;
4248d1b46d7Szhanghch05 
425d3a9e084SEd Tanous     std::array<char, HOST_NAME_MAX> hostNameCStr{};
4267e860f15SJohn Edward Broadbent     if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0)
4277e860f15SJohn Edward Broadbent     {
4287e860f15SJohn Edward Broadbent         hostName = hostNameCStr.data();
4297e860f15SJohn Edward Broadbent     }
4307e860f15SJohn Edward Broadbent     return hostName;
4317e860f15SJohn Edward Broadbent }
4327e860f15SJohn Edward Broadbent 
4334f48d5f6SEd Tanous inline void
4344f48d5f6SEd Tanous     getNTPProtocolEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
4357e860f15SJohn Edward Broadbent {
4361e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
4371e1e598dSJonathan Doman         *crow::connections::systemBus, "xyz.openbmc_project.Settings",
4381e1e598dSJonathan Doman         "/xyz/openbmc_project/time/sync_method",
4391e1e598dSJonathan Doman         "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod",
4405e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& errorCode,
4411e1e598dSJonathan Doman                     const std::string& timeSyncMethod) {
4427e860f15SJohn Edward Broadbent         if (errorCode)
4437e860f15SJohn Edward Broadbent         {
4447e860f15SJohn Edward Broadbent             return;
4457e860f15SJohn Edward Broadbent         }
4467e860f15SJohn Edward Broadbent 
4471e1e598dSJonathan Doman         if (timeSyncMethod ==
4481e1e598dSJonathan Doman             "xyz.openbmc_project.Time.Synchronization.Method.NTP")
4497e860f15SJohn Edward Broadbent         {
4507e860f15SJohn Edward Broadbent             asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = true;
4517e860f15SJohn Edward Broadbent         }
452002d39b4SEd Tanous         else if (timeSyncMethod == "xyz.openbmc_project.Time.Synchronization."
4531e1e598dSJonathan Doman                                    "Method.Manual")
4547e860f15SJohn Edward Broadbent         {
4557e860f15SJohn Edward Broadbent             asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = false;
4567e860f15SJohn Edward Broadbent         }
4571e1e598dSJonathan Doman         });
4587e860f15SJohn Edward Broadbent }
4597e860f15SJohn Edward Broadbent 
46069320d54SJiaqing Zhao inline std::string encodeServiceObjectPath(const std::string& serviceName)
46169320d54SJiaqing Zhao {
46269320d54SJiaqing Zhao     sdbusplus::message::object_path objPath(
46369320d54SJiaqing Zhao         "/xyz/openbmc_project/control/service");
46469320d54SJiaqing Zhao     objPath /= serviceName;
46569320d54SJiaqing Zhao     return objPath.str;
46669320d54SJiaqing Zhao }
46769320d54SJiaqing Zhao 
4680f55d946SEd Tanous inline void handleBmcNetworkProtocolHead(
469e9f71672SEd Tanous     crow::App& app, const crow::Request& req,
470e9f71672SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
471e9f71672SEd Tanous {
472e9f71672SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
473e9f71672SEd Tanous     {
474e9f71672SEd Tanous         return;
475e9f71672SEd Tanous     }
476e9f71672SEd Tanous     asyncResp->res.addHeader(
477e9f71672SEd Tanous         boost::beast::http::field::link,
478e9f71672SEd Tanous         "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/ManagerNetworkProtocol.json>; rel=describedby");
479e9f71672SEd Tanous }
480e9f71672SEd Tanous 
481*e634b34cSEd Tanous inline void handleManagersNetworkProtocolPatch(
482*e634b34cSEd Tanous     App& app, const crow::Request& req,
483*e634b34cSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
4847e860f15SJohn Edward Broadbent {
485*e634b34cSEd Tanous 
4863ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
48745ca1b86SEd Tanous     {
48845ca1b86SEd Tanous         return;
48945ca1b86SEd Tanous     }
490501be32bSraviteja-b     std::optional<std::string> newHostName;
491b9e15228SEd Tanous     std::optional<std::vector<nlohmann::json>> ntpServerObjects;
4925f4c798dSJiaqing Zhao     std::optional<bool> ntpEnabled;
4935f4c798dSJiaqing Zhao     std::optional<bool> ipmiEnabled;
4945f4c798dSJiaqing Zhao     std::optional<bool> sshEnabled;
495501be32bSraviteja-b 
4965f4c798dSJiaqing Zhao     // clang-format off
4975f4c798dSJiaqing Zhao         if (!json_util::readJsonPatch(
4985f4c798dSJiaqing Zhao                 req, asyncResp->res,
4995f4c798dSJiaqing Zhao                 "HostName", newHostName,
500b9e15228SEd Tanous                 "NTP/NTPServers", ntpServerObjects,
5015f4c798dSJiaqing Zhao                 "NTP/ProtocolEnabled", ntpEnabled,
5025f4c798dSJiaqing Zhao                 "IPMI/ProtocolEnabled", ipmiEnabled,
5035f4c798dSJiaqing Zhao                 "SSH/ProtocolEnabled", sshEnabled))
504501be32bSraviteja-b         {
505501be32bSraviteja-b             return;
506501be32bSraviteja-b         }
5075f4c798dSJiaqing Zhao     // clang-format on
508cf05f9dcSJohnathan Mantey 
5098d1b46d7Szhanghch05     asyncResp->res.result(boost::beast::http::status::no_content);
510501be32bSraviteja-b     if (newHostName)
511501be32bSraviteja-b     {
5122db77d34SJohnathan Mantey         messages::propertyNotWritable(asyncResp->res, "HostName");
51344fad2aaSEd Tanous         return;
514cf05f9dcSJohnathan Mantey     }
515cf05f9dcSJohnathan Mantey 
51620e6ea5dSraviteja-b     if (ntpEnabled)
51720e6ea5dSraviteja-b     {
51820e6ea5dSraviteja-b         handleNTPProtocolEnabled(*ntpEnabled, asyncResp);
51920e6ea5dSraviteja-b     }
520b9e15228SEd Tanous     if (ntpServerObjects)
52120e6ea5dSraviteja-b     {
522b9e15228SEd Tanous         getEthernetIfaceData(
523b9e15228SEd Tanous             [asyncResp, ntpServerObjects](
524*e634b34cSEd Tanous                 const bool success, std::vector<std::string>& currentNtpServers,
525b9e15228SEd Tanous                 const std::vector<std::string>& /*domainNames*/) {
526b9e15228SEd Tanous             if (!success)
527b9e15228SEd Tanous             {
528b9e15228SEd Tanous                 messages::internalError(asyncResp->res);
529b9e15228SEd Tanous                 return;
530b9e15228SEd Tanous             }
531b9e15228SEd Tanous             handleNTPServersPatch(asyncResp, *ntpServerObjects,
532b9e15228SEd Tanous                                   std::move(currentNtpServers));
533b9e15228SEd Tanous         });
53420e6ea5dSraviteja-b     }
53567a78d87STom Joseph 
5365f4c798dSJiaqing Zhao     if (ipmiEnabled)
53767a78d87STom Joseph     {
538e5a99777SAlbert Zhang         handleProtocolEnabled(
5395f4c798dSJiaqing Zhao             *ipmiEnabled, asyncResp,
54069320d54SJiaqing Zhao             encodeServiceObjectPath(std::string(ipmiServiceName) + '@'));
541e5a99777SAlbert Zhang     }
542e5a99777SAlbert Zhang 
5435f4c798dSJiaqing Zhao     if (sshEnabled)
544e5a99777SAlbert Zhang     {
54569320d54SJiaqing Zhao         handleProtocolEnabled(*sshEnabled, asyncResp,
54669320d54SJiaqing Zhao                               encodeServiceObjectPath(sshServiceName));
54767a78d87STom Joseph     }
548*e634b34cSEd Tanous }
549*e634b34cSEd Tanous 
550*e634b34cSEd Tanous inline void handleManagersNetworkProtocolGet(
551*e634b34cSEd Tanous     App& app, const crow::Request& req,
552*e634b34cSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
553*e634b34cSEd Tanous {
554*e634b34cSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
555*e634b34cSEd Tanous     {
556*e634b34cSEd Tanous         return;
557*e634b34cSEd Tanous     }
558*e634b34cSEd Tanous     getNetworkData(asyncResp, req);
559*e634b34cSEd Tanous }
560*e634b34cSEd Tanous 
561*e634b34cSEd Tanous inline void requestRoutesNetworkProtocol(App& app)
562*e634b34cSEd Tanous {
563*e634b34cSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/")
564*e634b34cSEd Tanous         .privileges(redfish::privileges::patchManagerNetworkProtocol)
565*e634b34cSEd Tanous         .methods(boost::beast::http::verb::patch)(
566*e634b34cSEd Tanous             std::bind_front(handleManagersNetworkProtocolPatch, std::ref(app)));
5677e860f15SJohn Edward Broadbent 
5687e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/")
569e9f71672SEd Tanous         .privileges(redfish::privileges::headManagerNetworkProtocol)
570e9f71672SEd Tanous         .methods(boost::beast::http::verb::head)(
571e9f71672SEd Tanous             std::bind_front(handleBmcNetworkProtocolHead, std::ref(app)));
572e9f71672SEd Tanous 
573e9f71672SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/")
574ed398213SEd Tanous         .privileges(redfish::privileges::getManagerNetworkProtocol)
5757e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
576*e634b34cSEd Tanous             std::bind_front(handleManagersNetworkProtocolGet, std::ref(app)));
577cf05f9dcSJohnathan Mantey }
57870141561SBorawski.Lukasz 
57970141561SBorawski.Lukasz } // namespace redfish
580