xref: /openbmc/bmcweb/features/redfish/lib/network_protocol.hpp (revision 1214b7e7d921e331fb1480c7e5d579ffa5811cda)
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"
1970141561SBorawski.Lukasz #include "node.hpp"
2070141561SBorawski.Lukasz 
2120e6ea5dSraviteja-b #include <utils/json_utils.hpp>
22*1214b7e7SGunnar Mills 
23*1214b7e7SGunnar Mills #include <optional>
24abf2add6SEd Tanous #include <variant>
251abe55efSEd Tanous namespace redfish
261abe55efSEd Tanous {
2770141561SBorawski.Lukasz 
281abe55efSEd Tanous enum NetworkProtocolUnitStructFields
291abe55efSEd Tanous {
303a8a0088SKowalski, Kamil     NET_PROTO_UNIT_NAME,
313a8a0088SKowalski, Kamil     NET_PROTO_UNIT_DESC,
323a8a0088SKowalski, Kamil     NET_PROTO_UNIT_LOAD_STATE,
333a8a0088SKowalski, Kamil     NET_PROTO_UNIT_ACTIVE_STATE,
343a8a0088SKowalski, Kamil     NET_PROTO_UNIT_SUB_STATE,
353a8a0088SKowalski, Kamil     NET_PROTO_UNIT_DEVICE,
363a8a0088SKowalski, Kamil     NET_PROTO_UNIT_OBJ_PATH,
373a8a0088SKowalski, Kamil     NET_PROTO_UNIT_ALWAYS_0,
383a8a0088SKowalski, Kamil     NET_PROTO_UNIT_ALWAYS_EMPTY,
393a8a0088SKowalski, Kamil     NET_PROTO_UNIT_ALWAYS_ROOT_PATH
403a8a0088SKowalski, Kamil };
413a8a0088SKowalski, Kamil 
421abe55efSEd Tanous enum NetworkProtocolListenResponseElements
431abe55efSEd Tanous {
443a8a0088SKowalski, Kamil     NET_PROTO_LISTEN_TYPE,
453a8a0088SKowalski, Kamil     NET_PROTO_LISTEN_STREAM
463a8a0088SKowalski, Kamil };
473a8a0088SKowalski, Kamil 
483a8a0088SKowalski, Kamil /**
493a8a0088SKowalski, Kamil  * @brief D-Bus Unit structure returned in array from ListUnits Method
503a8a0088SKowalski, Kamil  */
513a8a0088SKowalski, Kamil using UnitStruct =
523a8a0088SKowalski, Kamil     std::tuple<std::string, std::string, std::string, std::string, std::string,
533a8a0088SKowalski, Kamil                std::string, sdbusplus::message::object_path, uint32_t,
543a8a0088SKowalski, Kamil                std::string, sdbusplus::message::object_path>;
553a8a0088SKowalski, Kamil 
56ec4974ddSAppaRao Puli const static boost::container::flat_map<const char*, std::string>
57ec4974ddSAppaRao Puli     protocolToDBus{{"SSH", "dropbear"},
58ec4974ddSAppaRao Puli                    {"HTTPS", "bmcweb"},
59ec4974ddSAppaRao Puli                    {"IPMI", "phosphor-ipmi-net"}};
603a8a0088SKowalski, Kamil 
61d24bfc7aSJennifer Lee inline void
62d24bfc7aSJennifer Lee     extractNTPServersAndDomainNamesData(const GetManagedObjects& dbus_data,
63d24bfc7aSJennifer Lee                                         std::vector<std::string>& ntpData,
64d24bfc7aSJennifer Lee                                         std::vector<std::string>& dnData)
6520e6ea5dSraviteja-b {
6620e6ea5dSraviteja-b     for (const auto& obj : dbus_data)
6720e6ea5dSraviteja-b     {
6820e6ea5dSraviteja-b         for (const auto& ifacePair : obj.second)
6920e6ea5dSraviteja-b         {
7020e6ea5dSraviteja-b             if (obj.first == "/xyz/openbmc_project/network/eth0")
7120e6ea5dSraviteja-b             {
7220e6ea5dSraviteja-b                 if (ifacePair.first ==
7320e6ea5dSraviteja-b                     "xyz.openbmc_project.Network.EthernetInterface")
7420e6ea5dSraviteja-b                 {
7520e6ea5dSraviteja-b                     for (const auto& propertyPair : ifacePair.second)
7620e6ea5dSraviteja-b                     {
7720e6ea5dSraviteja-b                         if (propertyPair.first == "NTPServers")
7820e6ea5dSraviteja-b                         {
7920e6ea5dSraviteja-b                             const std::vector<std::string>* ntpServers =
808d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
8120e6ea5dSraviteja-b                                     &propertyPair.second);
8220e6ea5dSraviteja-b                             if (ntpServers != nullptr)
8320e6ea5dSraviteja-b                             {
8420e6ea5dSraviteja-b                                 ntpData = std::move(*ntpServers);
8520e6ea5dSraviteja-b                             }
8620e6ea5dSraviteja-b                         }
87d24bfc7aSJennifer Lee                         else if (propertyPair.first == "DomainName")
88d24bfc7aSJennifer Lee                         {
89d24bfc7aSJennifer Lee                             const std::vector<std::string>* domainNames =
908d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
91d24bfc7aSJennifer Lee                                     &propertyPair.second);
92d24bfc7aSJennifer Lee                             if (domainNames != nullptr)
93d24bfc7aSJennifer Lee                             {
94d24bfc7aSJennifer Lee                                 dnData = std::move(*domainNames);
95d24bfc7aSJennifer Lee                             }
96d24bfc7aSJennifer Lee                         }
9720e6ea5dSraviteja-b                     }
9820e6ea5dSraviteja-b                 }
9920e6ea5dSraviteja-b             }
10020e6ea5dSraviteja-b         }
10120e6ea5dSraviteja-b     }
10220e6ea5dSraviteja-b }
10320e6ea5dSraviteja-b 
10420e6ea5dSraviteja-b template <typename CallbackFunc>
10520e6ea5dSraviteja-b void getEthernetIfaceData(CallbackFunc&& callback)
10620e6ea5dSraviteja-b {
10720e6ea5dSraviteja-b     crow::connections::systemBus->async_method_call(
10820e6ea5dSraviteja-b         [callback{std::move(callback)}](
10920e6ea5dSraviteja-b             const boost::system::error_code error_code,
11020e6ea5dSraviteja-b             const GetManagedObjects& dbus_data) {
11120e6ea5dSraviteja-b             std::vector<std::string> ntpServers;
112d24bfc7aSJennifer Lee             std::vector<std::string> domainNames;
11320e6ea5dSraviteja-b 
11420e6ea5dSraviteja-b             if (error_code)
11520e6ea5dSraviteja-b             {
116d24bfc7aSJennifer Lee                 callback(false, ntpServers, domainNames);
11720e6ea5dSraviteja-b                 return;
11820e6ea5dSraviteja-b             }
11920e6ea5dSraviteja-b 
120d24bfc7aSJennifer Lee             extractNTPServersAndDomainNamesData(dbus_data, ntpServers,
121d24bfc7aSJennifer Lee                                                 domainNames);
12220e6ea5dSraviteja-b 
123d24bfc7aSJennifer Lee             callback(true, ntpServers, domainNames);
12420e6ea5dSraviteja-b         },
12520e6ea5dSraviteja-b         "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
12620e6ea5dSraviteja-b         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
127271584abSEd Tanous }
12820e6ea5dSraviteja-b 
1291abe55efSEd Tanous class NetworkProtocol : public Node
1301abe55efSEd Tanous {
13170141561SBorawski.Lukasz   public:
1321abe55efSEd Tanous     NetworkProtocol(CrowApp& app) :
1337af91514SGunnar Mills         Node(app, "/redfish/v1/Managers/bmc/NetworkProtocol/")
1341abe55efSEd Tanous     {
1354b1b8683SBorawski.Lukasz         entityPrivileges = {
1364b1b8683SBorawski.Lukasz             {boost::beast::http::verb::get, {{"Login"}}},
137e0d918bcSEd Tanous             {boost::beast::http::verb::head, {{"Login"}}},
138e0d918bcSEd Tanous             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
139e0d918bcSEd Tanous             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
140e0d918bcSEd Tanous             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
141e0d918bcSEd Tanous             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
14270141561SBorawski.Lukasz     }
14370141561SBorawski.Lukasz 
14470141561SBorawski.Lukasz   private:
14555c7b7a2SEd Tanous     void doGet(crow::Response& res, const crow::Request& req,
1461abe55efSEd Tanous                const std::vector<std::string>& params) override
1471abe55efSEd Tanous     {
1483a8a0088SKowalski, Kamil         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
1493a8a0088SKowalski, Kamil 
1503a8a0088SKowalski, Kamil         getData(asyncResp);
15170141561SBorawski.Lukasz     }
15270141561SBorawski.Lukasz 
1531abe55efSEd Tanous     std::string getHostName() const
1541abe55efSEd Tanous     {
15570141561SBorawski.Lukasz         std::string hostName;
15670141561SBorawski.Lukasz 
15770141561SBorawski.Lukasz         std::array<char, HOST_NAME_MAX> hostNameCStr;
1581abe55efSEd Tanous         if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0)
1591abe55efSEd Tanous         {
16070141561SBorawski.Lukasz             hostName = hostNameCStr.data();
16170141561SBorawski.Lukasz         }
16270141561SBorawski.Lukasz         return hostName;
16370141561SBorawski.Lukasz     }
16470141561SBorawski.Lukasz 
16520e6ea5dSraviteja-b     void getNTPProtocolEnabled(const std::shared_ptr<AsyncResp>& asyncResp)
16620e6ea5dSraviteja-b     {
16720e6ea5dSraviteja-b         crow::connections::systemBus->async_method_call(
16820e6ea5dSraviteja-b             [asyncResp](const boost::system::error_code error_code,
16920e6ea5dSraviteja-b                         const std::variant<std::string>& timeSyncMethod) {
17020e6ea5dSraviteja-b                 const std::string* s =
17120e6ea5dSraviteja-b                     std::get_if<std::string>(&timeSyncMethod);
17220e6ea5dSraviteja-b 
17320e6ea5dSraviteja-b                 if (*s == "xyz.openbmc_project.Time.Synchronization.Method.NTP")
17420e6ea5dSraviteja-b                 {
17520e6ea5dSraviteja-b                     asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = true;
17620e6ea5dSraviteja-b                 }
17720e6ea5dSraviteja-b                 else if (*s == "xyz.openbmc_project.Time.Synchronization."
17820e6ea5dSraviteja-b                                "Method.Manual")
17920e6ea5dSraviteja-b                 {
18020e6ea5dSraviteja-b                     asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = false;
18120e6ea5dSraviteja-b                 }
18220e6ea5dSraviteja-b             },
18320e6ea5dSraviteja-b             "xyz.openbmc_project.Settings",
18420e6ea5dSraviteja-b             "/xyz/openbmc_project/time/sync_method",
18520e6ea5dSraviteja-b             "org.freedesktop.DBus.Properties", "Get",
18620e6ea5dSraviteja-b             "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod");
18720e6ea5dSraviteja-b     }
18820e6ea5dSraviteja-b 
1891abe55efSEd Tanous     void getData(const std::shared_ptr<AsyncResp>& asyncResp)
1901abe55efSEd Tanous     {
1910f74e643SEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
19261932318SXiaochao Ma             "#ManagerNetworkProtocol.v1_5_0.ManagerNetworkProtocol";
1930f74e643SEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
1940f74e643SEd Tanous             "/redfish/v1/Managers/bmc/NetworkProtocol";
1950f74e643SEd Tanous         asyncResp->res.jsonValue["Id"] = "NetworkProtocol";
1960f74e643SEd Tanous         asyncResp->res.jsonValue["Name"] = "Manager Network Protocol";
1970f74e643SEd Tanous         asyncResp->res.jsonValue["Description"] = "Manager Network Service";
1980f74e643SEd Tanous         asyncResp->res.jsonValue["Status"]["Health"] = "OK";
1990f74e643SEd Tanous         asyncResp->res.jsonValue["Status"]["HealthRollup"] = "OK";
2000f74e643SEd Tanous         asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
20161932318SXiaochao Ma         asyncResp->res.jsonValue["SNMP"]["ProtocolEnabled"] = true;
20261932318SXiaochao Ma         asyncResp->res.jsonValue["SNMP"]["Port"] = 161;
20361932318SXiaochao Ma         asyncResp->res.jsonValue["SNMP"]["AuthenticationProtocol"] =
20461932318SXiaochao Ma             "CommunityString";
20561932318SXiaochao Ma         asyncResp->res.jsonValue["SNMP"]["CommunityAccessMode"] = "Full";
20661932318SXiaochao Ma         asyncResp->res.jsonValue["SNMP"]["HideCommunityStrings"] = true;
20761932318SXiaochao Ma         asyncResp->res
20861932318SXiaochao Ma             .jsonValue["SNMP"]["EngineId"]["EnterpriseSpecificMethod"] =
20961932318SXiaochao Ma             nullptr;
21061932318SXiaochao Ma         asyncResp->res.jsonValue["SNMP"]["EngineId"]["PrivateEnterpriseId"] =
21161932318SXiaochao Ma             nullptr;
21261932318SXiaochao Ma         asyncResp->res.jsonValue["SNMP"]["EnableSNMPv1"] = false;
21361932318SXiaochao Ma         asyncResp->res.jsonValue["SNMP"]["EnableSNMPv2c"] = true;
21461932318SXiaochao Ma         asyncResp->res.jsonValue["SNMP"]["EnableSNMPv3"] = false;
21561932318SXiaochao Ma         asyncResp->res.jsonValue["SNMP"]["EncryptionProtocol"] = "None";
21661932318SXiaochao Ma         nlohmann::json& memberArray =
21761932318SXiaochao Ma             asyncResp->res.jsonValue["SNMP"]["CommunityStrings"];
21861932318SXiaochao Ma         memberArray = nlohmann::json::array();
21961932318SXiaochao Ma         memberArray.push_back({{"AccessMode", "Full"}});
22061932318SXiaochao Ma         memberArray.push_back({{"CommunityString", ""}});
22161932318SXiaochao Ma         memberArray.push_back({{"Name", ""}});
2220f74e643SEd Tanous 
22361932318SXiaochao Ma         // HTTP is Mandatory attribute as per OCP Baseline Profile - v1.0.0,
224818ea7b8SJoshi-Mansi         // but from security perspective it is not recommended to use.
225818ea7b8SJoshi-Mansi         // Hence using protocolEnabled as false to make it OCP and security-wise
226818ea7b8SJoshi-Mansi         // compliant
227818ea7b8SJoshi-Mansi         asyncResp->res.jsonValue["HTTP"]["Port"] = 0;
228818ea7b8SJoshi-Mansi         asyncResp->res.jsonValue["HTTP"]["ProtocolEnabled"] = false;
229818ea7b8SJoshi-Mansi 
2300f74e643SEd Tanous         for (auto& protocol : protocolToDBus)
2310f74e643SEd Tanous         {
2320f74e643SEd Tanous             asyncResp->res.jsonValue[protocol.first]["ProtocolEnabled"] = false;
2330f74e643SEd Tanous         }
2340f74e643SEd Tanous 
235d24bfc7aSJennifer Lee         std::string hostName = getHostName();
236d24bfc7aSJennifer Lee 
237d24bfc7aSJennifer Lee         asyncResp->res.jsonValue["HostName"] = hostName;
2383a8a0088SKowalski, Kamil 
23920e6ea5dSraviteja-b         getNTPProtocolEnabled(asyncResp);
24020e6ea5dSraviteja-b 
24120e6ea5dSraviteja-b         // TODO Get eth0 interface data, and call the below callback for JSON
24220e6ea5dSraviteja-b         // preparation
243271584abSEd Tanous         getEthernetIfaceData(
244271584abSEd Tanous             [hostName, asyncResp](const bool& success,
245d24bfc7aSJennifer Lee                                   const std::vector<std::string>& ntpServers,
246d24bfc7aSJennifer Lee                                   const std::vector<std::string>& domainNames) {
24720e6ea5dSraviteja-b                 if (!success)
24820e6ea5dSraviteja-b                 {
249271584abSEd Tanous                     messages::resourceNotFound(asyncResp->res,
250271584abSEd Tanous                                                "EthernetInterface", "eth0");
25120e6ea5dSraviteja-b                     return;
25220e6ea5dSraviteja-b                 }
25320e6ea5dSraviteja-b                 asyncResp->res.jsonValue["NTP"]["NTPServers"] = ntpServers;
254d24bfc7aSJennifer Lee                 if (hostName.empty() == false)
255d24bfc7aSJennifer Lee                 {
256749dad7dSRatan Gupta                     std::string FQDN = std::move(hostName);
257d24bfc7aSJennifer Lee                     if (domainNames.empty() == false)
258d24bfc7aSJennifer Lee                     {
259749dad7dSRatan Gupta                         FQDN += "." + domainNames[0];
260d24bfc7aSJennifer Lee                     }
261749dad7dSRatan Gupta                     asyncResp->res.jsonValue["FQDN"] = std::move(FQDN);
262d24bfc7aSJennifer Lee                 }
26320e6ea5dSraviteja-b             });
26420e6ea5dSraviteja-b 
265865fbb75SEd Tanous         crow::connections::systemBus->async_method_call(
266271584abSEd Tanous             [asyncResp](const boost::system::error_code e,
267271584abSEd Tanous                         const std::vector<UnitStruct>& r) {
268271584abSEd Tanous                 if (e)
2691abe55efSEd Tanous                 {
2703a8a0088SKowalski, Kamil                     asyncResp->res.jsonValue = nlohmann::json::object();
271f12894f8SJason M. Bills                     messages::internalError(asyncResp->res);
272865fbb75SEd Tanous                     return;
2733a8a0088SKowalski, Kamil                 }
2745968caeeSMarri Devender Rao                 asyncResp->res.jsonValue["HTTPS"]["Certificates"] = {
2755968caeeSMarri Devender Rao                     {"@odata.id", "/redfish/v1/Managers/bmc/NetworkProtocol/"
276659dd62eSJason M. Bills                                   "HTTPS/Certificates"}};
2773a8a0088SKowalski, Kamil 
278271584abSEd Tanous                 for (auto& unit : r)
2791abe55efSEd Tanous                 {
280ec4974ddSAppaRao Puli                     /* Only traverse through <xyz>.socket units */
281ec4974ddSAppaRao Puli                     std::string unitName = std::get<NET_PROTO_UNIT_NAME>(unit);
282ec4974ddSAppaRao Puli                     if (!boost::ends_with(unitName, ".socket"))
2831abe55efSEd Tanous                     {
284865fbb75SEd Tanous                         continue;
28570141561SBorawski.Lukasz                     }
28670141561SBorawski.Lukasz 
287ec4974ddSAppaRao Puli                     for (auto& kv : protocolToDBus)
288ec4974ddSAppaRao Puli                     {
289ec4974ddSAppaRao Puli                         // We are interested in services, which starts with
290ec4974ddSAppaRao Puli                         // mapped service name
291ec4974ddSAppaRao Puli                         if (!boost::starts_with(unitName, kv.second))
292ec4974ddSAppaRao Puli                         {
293ec4974ddSAppaRao Puli                             continue;
294ec4974ddSAppaRao Puli                         }
295ec4974ddSAppaRao Puli                         const char* rfServiceKey = kv.first;
296ec4974ddSAppaRao Puli                         std::string socketPath =
297ec4974ddSAppaRao Puli                             std::get<NET_PROTO_UNIT_OBJ_PATH>(unit);
298ec4974ddSAppaRao Puli                         std::string unitState =
299ec4974ddSAppaRao Puli                             std::get<NET_PROTO_UNIT_SUB_STATE>(unit);
300ec4974ddSAppaRao Puli 
301ec4974ddSAppaRao Puli                         asyncResp->res
302ec4974ddSAppaRao Puli                             .jsonValue[rfServiceKey]["ProtocolEnabled"] =
303ec4974ddSAppaRao Puli                             (unitState == "running") ||
304ec4974ddSAppaRao Puli                             (unitState == "listening");
305ec4974ddSAppaRao Puli 
306865fbb75SEd Tanous                         crow::connections::systemBus->async_method_call(
307ec4974ddSAppaRao Puli                             [asyncResp,
308ec4974ddSAppaRao Puli                              rfServiceKey{std::string(rfServiceKey)}](
309865fbb75SEd Tanous                                 const boost::system::error_code ec,
310abf2add6SEd Tanous                                 const std::variant<std::vector<std::tuple<
311abf2add6SEd Tanous                                     std::string, std::string>>>& resp) {
3121abe55efSEd Tanous                                 if (ec)
3131abe55efSEd Tanous                                 {
314a08b46ccSJason M. Bills                                     messages::internalError(asyncResp->res);
315865fbb75SEd Tanous                                     return;
3163a8a0088SKowalski, Kamil                                 }
317abf2add6SEd Tanous                                 const std::vector<
318abf2add6SEd Tanous                                     std::tuple<std::string, std::string>>*
319abf2add6SEd Tanous                                     responsePtr = std::get_if<std::vector<
320abf2add6SEd Tanous                                         std::tuple<std::string, std::string>>>(
3211b6b96c5SEd Tanous                                         &resp);
3221abe55efSEd Tanous                                 if (responsePtr == nullptr ||
3231abe55efSEd Tanous                                     responsePtr->size() < 1)
3241abe55efSEd Tanous                                 {
325865fbb75SEd Tanous                                     return;
32670141561SBorawski.Lukasz                                 }
32770141561SBorawski.Lukasz 
328865fbb75SEd Tanous                                 const std::string& listenStream =
3291abe55efSEd Tanous                                     std::get<NET_PROTO_LISTEN_STREAM>(
3301abe55efSEd Tanous                                         (*responsePtr)[0]);
3311abe55efSEd Tanous                                 std::size_t lastColonPos =
3321abe55efSEd Tanous                                     listenStream.rfind(":");
3331abe55efSEd Tanous                                 if (lastColonPos == std::string::npos)
3341abe55efSEd Tanous                                 {
335865fbb75SEd Tanous                                     // Not a port
336865fbb75SEd Tanous                                     return;
337865fbb75SEd Tanous                                 }
3381abe55efSEd Tanous                                 std::string portStr =
3391abe55efSEd Tanous                                     listenStream.substr(lastColonPos + 1);
340ec4974ddSAppaRao Puli                                 if (portStr.empty())
341ec4974ddSAppaRao Puli                                 {
342ec4974ddSAppaRao Puli                                     return;
343ec4974ddSAppaRao Puli                                 }
344865fbb75SEd Tanous                                 char* endPtr = nullptr;
345ec4974ddSAppaRao Puli                                 errno = 0;
3461abe55efSEd Tanous                                 // Use strtol instead of stroi to avoid
3471abe55efSEd Tanous                                 // exceptions
3481abe55efSEd Tanous                                 long port =
3491abe55efSEd Tanous                                     std::strtol(portStr.c_str(), &endPtr, 10);
350ec4974ddSAppaRao Puli                                 if ((errno == 0) && (*endPtr == '\0'))
3511abe55efSEd Tanous                                 {
352ec4974ddSAppaRao Puli                                     asyncResp->res
353ec4974ddSAppaRao Puli                                         .jsonValue[rfServiceKey]["Port"] = port;
3541abe55efSEd Tanous                                 }
355ec4974ddSAppaRao Puli                                 return;
356865fbb75SEd Tanous                             },
357865fbb75SEd Tanous                             "org.freedesktop.systemd1", socketPath,
358865fbb75SEd Tanous                             "org.freedesktop.DBus.Properties", "Get",
359865fbb75SEd Tanous                             "org.freedesktop.systemd1.Socket", "Listen");
360ec4974ddSAppaRao Puli 
361ec4974ddSAppaRao Puli                         // We found service, break the inner loop.
362ec4974ddSAppaRao Puli                         break;
363865fbb75SEd Tanous                     }
364865fbb75SEd Tanous                 }
365865fbb75SEd Tanous             },
366865fbb75SEd Tanous             "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
367865fbb75SEd Tanous             "org.freedesktop.systemd1.Manager", "ListUnits");
368865fbb75SEd Tanous     }
369501be32bSraviteja-b 
370501be32bSraviteja-b     void handleHostnamePatch(const std::string& hostName,
371501be32bSraviteja-b                              const std::shared_ptr<AsyncResp>& asyncResp)
372501be32bSraviteja-b     {
373501be32bSraviteja-b         crow::connections::systemBus->async_method_call(
374501be32bSraviteja-b             [asyncResp](const boost::system::error_code ec) {
375501be32bSraviteja-b                 if (ec)
376501be32bSraviteja-b                 {
377501be32bSraviteja-b                     messages::internalError(asyncResp->res);
378501be32bSraviteja-b                     return;
379501be32bSraviteja-b                 }
380501be32bSraviteja-b             },
381501be32bSraviteja-b             "xyz.openbmc_project.Network",
382501be32bSraviteja-b             "/xyz/openbmc_project/network/config",
383501be32bSraviteja-b             "org.freedesktop.DBus.Properties", "Set",
384501be32bSraviteja-b             "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
385501be32bSraviteja-b             std::variant<std::string>(hostName));
386501be32bSraviteja-b     }
387501be32bSraviteja-b 
38820e6ea5dSraviteja-b     void handleNTPProtocolEnabled(const bool& ntpEnabled,
38920e6ea5dSraviteja-b                                   const std::shared_ptr<AsyncResp>& asyncResp)
39020e6ea5dSraviteja-b     {
39120e6ea5dSraviteja-b         std::string timeSyncMethod;
39220e6ea5dSraviteja-b         if (ntpEnabled)
39320e6ea5dSraviteja-b         {
39420e6ea5dSraviteja-b             timeSyncMethod =
39520e6ea5dSraviteja-b                 "xyz.openbmc_project.Time.Synchronization.Method.NTP";
39620e6ea5dSraviteja-b         }
39720e6ea5dSraviteja-b         else
39820e6ea5dSraviteja-b         {
39920e6ea5dSraviteja-b             timeSyncMethod =
40020e6ea5dSraviteja-b                 "xyz.openbmc_project.Time.Synchronization.Method.Manual";
40120e6ea5dSraviteja-b         }
40220e6ea5dSraviteja-b 
40320e6ea5dSraviteja-b         crow::connections::systemBus->async_method_call(
404cf05f9dcSJohnathan Mantey             [asyncResp](const boost::system::error_code error_code) {},
40520e6ea5dSraviteja-b             "xyz.openbmc_project.Settings",
40620e6ea5dSraviteja-b             "/xyz/openbmc_project/time/sync_method",
40720e6ea5dSraviteja-b             "org.freedesktop.DBus.Properties", "Set",
40820e6ea5dSraviteja-b             "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod",
40920e6ea5dSraviteja-b             std::variant<std::string>{timeSyncMethod});
41020e6ea5dSraviteja-b     }
41120e6ea5dSraviteja-b 
41220e6ea5dSraviteja-b     void handleNTPServersPatch(const std::vector<std::string>& ntpServers,
41320e6ea5dSraviteja-b                                const std::shared_ptr<AsyncResp>& asyncResp)
41420e6ea5dSraviteja-b     {
41520e6ea5dSraviteja-b         crow::connections::systemBus->async_method_call(
416cf05f9dcSJohnathan Mantey             [asyncResp](const boost::system::error_code ec) {
41720e6ea5dSraviteja-b                 if (ec)
41820e6ea5dSraviteja-b                 {
41920e6ea5dSraviteja-b                     messages::internalError(asyncResp->res);
42020e6ea5dSraviteja-b                     return;
42120e6ea5dSraviteja-b                 }
42220e6ea5dSraviteja-b             },
42320e6ea5dSraviteja-b             "xyz.openbmc_project.Network", "/xyz/openbmc_project/network/eth0",
42420e6ea5dSraviteja-b             "org.freedesktop.DBus.Properties", "Set",
42520e6ea5dSraviteja-b             "xyz.openbmc_project.Network.EthernetInterface", "NTPServers",
42620e6ea5dSraviteja-b             std::variant<std::vector<std::string>>{ntpServers});
42720e6ea5dSraviteja-b     }
42820e6ea5dSraviteja-b 
429501be32bSraviteja-b     void doPatch(crow::Response& res, const crow::Request& req,
430501be32bSraviteja-b                  const std::vector<std::string>& params) override
431501be32bSraviteja-b     {
432501be32bSraviteja-b         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
433501be32bSraviteja-b         std::optional<std::string> newHostName;
434cf05f9dcSJohnathan Mantey         std::optional<nlohmann::json> ntp;
435501be32bSraviteja-b 
436cf05f9dcSJohnathan Mantey         if (!json_util::readJson(req, res, "HostName", newHostName, "NTP", ntp))
437501be32bSraviteja-b         {
438501be32bSraviteja-b             return;
439501be32bSraviteja-b         }
440cf05f9dcSJohnathan Mantey 
441cf05f9dcSJohnathan Mantey         res.result(boost::beast::http::status::no_content);
442501be32bSraviteja-b         if (newHostName)
443501be32bSraviteja-b         {
444501be32bSraviteja-b             handleHostnamePatch(*newHostName, asyncResp);
445cf05f9dcSJohnathan Mantey         }
446cf05f9dcSJohnathan Mantey 
447cf05f9dcSJohnathan Mantey         if (ntp)
448cf05f9dcSJohnathan Mantey         {
449cf05f9dcSJohnathan Mantey             std::optional<std::vector<std::string>> ntpServers;
450cf05f9dcSJohnathan Mantey             std::optional<bool> ntpEnabled;
451cf05f9dcSJohnathan Mantey             if (!json_util::readJson(*ntp, res, "NTPServers", ntpServers,
452cf05f9dcSJohnathan Mantey                                      "ProtocolEnabled", ntpEnabled))
453cf05f9dcSJohnathan Mantey             {
454501be32bSraviteja-b                 return;
455501be32bSraviteja-b             }
456cf05f9dcSJohnathan Mantey 
45720e6ea5dSraviteja-b             if (ntpEnabled)
45820e6ea5dSraviteja-b             {
45920e6ea5dSraviteja-b                 handleNTPProtocolEnabled(*ntpEnabled, asyncResp);
46020e6ea5dSraviteja-b             }
461cf05f9dcSJohnathan Mantey 
46220e6ea5dSraviteja-b             if (ntpServers)
46320e6ea5dSraviteja-b             {
464dc3fbbd0STony Lee                 std::sort((*ntpServers).begin(), (*ntpServers).end());
465dc3fbbd0STony Lee                 (*ntpServers)
466dc3fbbd0STony Lee                     .erase(
467dc3fbbd0STony Lee                         std::unique((*ntpServers).begin(), (*ntpServers).end()),
468dc3fbbd0STony Lee                         (*ntpServers).end());
46920e6ea5dSraviteja-b                 handleNTPServersPatch(*ntpServers, asyncResp);
47020e6ea5dSraviteja-b             }
471501be32bSraviteja-b         }
472cf05f9dcSJohnathan Mantey     }
47370141561SBorawski.Lukasz };
47470141561SBorawski.Lukasz 
47570141561SBorawski.Lukasz } // namespace redfish
476