xref: /openbmc/bmcweb/features/redfish/lib/network_protocol.hpp (revision abf2add6a35aaf42ba60c4ae955a4d8925b13b19)
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 
21*abf2add6SEd Tanous #include <variant>
22*abf2add6SEd Tanous 
231abe55efSEd Tanous namespace redfish
241abe55efSEd Tanous {
2570141561SBorawski.Lukasz 
261abe55efSEd Tanous enum NetworkProtocolUnitStructFields
271abe55efSEd Tanous {
283a8a0088SKowalski, Kamil     NET_PROTO_UNIT_NAME,
293a8a0088SKowalski, Kamil     NET_PROTO_UNIT_DESC,
303a8a0088SKowalski, Kamil     NET_PROTO_UNIT_LOAD_STATE,
313a8a0088SKowalski, Kamil     NET_PROTO_UNIT_ACTIVE_STATE,
323a8a0088SKowalski, Kamil     NET_PROTO_UNIT_SUB_STATE,
333a8a0088SKowalski, Kamil     NET_PROTO_UNIT_DEVICE,
343a8a0088SKowalski, Kamil     NET_PROTO_UNIT_OBJ_PATH,
353a8a0088SKowalski, Kamil     NET_PROTO_UNIT_ALWAYS_0,
363a8a0088SKowalski, Kamil     NET_PROTO_UNIT_ALWAYS_EMPTY,
373a8a0088SKowalski, Kamil     NET_PROTO_UNIT_ALWAYS_ROOT_PATH
383a8a0088SKowalski, Kamil };
393a8a0088SKowalski, Kamil 
401abe55efSEd Tanous enum NetworkProtocolListenResponseElements
411abe55efSEd Tanous {
423a8a0088SKowalski, Kamil     NET_PROTO_LISTEN_TYPE,
433a8a0088SKowalski, Kamil     NET_PROTO_LISTEN_STREAM
443a8a0088SKowalski, Kamil };
453a8a0088SKowalski, Kamil 
463a8a0088SKowalski, Kamil /**
473a8a0088SKowalski, Kamil  * @brief D-Bus Unit structure returned in array from ListUnits Method
483a8a0088SKowalski, Kamil  */
493a8a0088SKowalski, Kamil using UnitStruct =
503a8a0088SKowalski, Kamil     std::tuple<std::string, std::string, std::string, std::string, std::string,
513a8a0088SKowalski, Kamil                std::string, sdbusplus::message::object_path, uint32_t,
523a8a0088SKowalski, Kamil                std::string, sdbusplus::message::object_path>;
533a8a0088SKowalski, Kamil 
541abe55efSEd Tanous struct ServiceConfiguration
551abe55efSEd Tanous {
56865fbb75SEd Tanous     const char* serviceName;
57865fbb75SEd Tanous     const char* socketPath;
583a8a0088SKowalski, Kamil };
593a8a0088SKowalski, Kamil 
60865fbb75SEd Tanous const static boost::container::flat_map<const char*, ServiceConfiguration>
61865fbb75SEd Tanous     protocolToDBus{
62865fbb75SEd Tanous         {"SSH",
63865fbb75SEd Tanous          {"dropbear.service",
64865fbb75SEd Tanous           "/org/freedesktop/systemd1/unit/dropbear_2esocket"}},
65865fbb75SEd Tanous         {"HTTPS",
66865fbb75SEd Tanous          {"phosphor-gevent.service",
67865fbb75SEd Tanous           "/org/freedesktop/systemd1/unit/phosphor_2dgevent_2esocket"}},
68865fbb75SEd Tanous         {"IPMI",
69865fbb75SEd Tanous          {"phosphor-ipmi-net.service",
70865fbb75SEd Tanous           "/org/freedesktop/systemd1/unit/phosphor_2dipmi_2dnet_2esocket"}}};
713a8a0088SKowalski, Kamil 
721abe55efSEd Tanous class NetworkProtocol : public Node
731abe55efSEd Tanous {
7470141561SBorawski.Lukasz   public:
751abe55efSEd Tanous     NetworkProtocol(CrowApp& app) :
7697b7ccf3SEd Tanous         Node(app, "/redfish/v1/Managers/bmc/NetworkProtocol")
771abe55efSEd Tanous     {
784b1b8683SBorawski.Lukasz         entityPrivileges = {
794b1b8683SBorawski.Lukasz             {boost::beast::http::verb::get, {{"Login"}}},
80e0d918bcSEd Tanous             {boost::beast::http::verb::head, {{"Login"}}},
81e0d918bcSEd Tanous             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
82e0d918bcSEd Tanous             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
83e0d918bcSEd Tanous             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
84e0d918bcSEd Tanous             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
8570141561SBorawski.Lukasz     }
8670141561SBorawski.Lukasz 
8770141561SBorawski.Lukasz   private:
8855c7b7a2SEd Tanous     void doGet(crow::Response& res, const crow::Request& req,
891abe55efSEd Tanous                const std::vector<std::string>& params) override
901abe55efSEd Tanous     {
913a8a0088SKowalski, Kamil         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
923a8a0088SKowalski, Kamil 
933a8a0088SKowalski, Kamil         getData(asyncResp);
9470141561SBorawski.Lukasz     }
9570141561SBorawski.Lukasz 
961abe55efSEd Tanous     std::string getHostName() const
971abe55efSEd Tanous     {
9870141561SBorawski.Lukasz         std::string hostName;
9970141561SBorawski.Lukasz 
10070141561SBorawski.Lukasz         std::array<char, HOST_NAME_MAX> hostNameCStr;
1011abe55efSEd Tanous         if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0)
1021abe55efSEd Tanous         {
10370141561SBorawski.Lukasz             hostName = hostNameCStr.data();
10470141561SBorawski.Lukasz         }
10570141561SBorawski.Lukasz         return hostName;
10670141561SBorawski.Lukasz     }
10770141561SBorawski.Lukasz 
1081abe55efSEd Tanous     void getData(const std::shared_ptr<AsyncResp>& asyncResp)
1091abe55efSEd Tanous     {
1100f74e643SEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
1110f74e643SEd Tanous             "#ManagerNetworkProtocol.v1_1_0.ManagerNetworkProtocol";
1120f74e643SEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
1130f74e643SEd Tanous             "/redfish/v1/Managers/bmc/NetworkProtocol";
1140f74e643SEd Tanous         asyncResp->res.jsonValue["@odata.context"] =
1150f74e643SEd Tanous             "/redfish/v1/"
1160f74e643SEd Tanous             "$metadata#ManagerNetworkProtocol.ManagerNetworkProtocol";
1170f74e643SEd Tanous         asyncResp->res.jsonValue["Id"] = "NetworkProtocol";
1180f74e643SEd Tanous         asyncResp->res.jsonValue["Name"] = "Manager Network Protocol";
1190f74e643SEd Tanous         asyncResp->res.jsonValue["Description"] = "Manager Network Service";
1200f74e643SEd Tanous         asyncResp->res.jsonValue["Status"]["Health"] = "OK";
1210f74e643SEd Tanous         asyncResp->res.jsonValue["Status"]["HealthRollup"] = "OK";
1220f74e643SEd Tanous         asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
1230f74e643SEd Tanous 
1240f74e643SEd Tanous         for (auto& protocol : protocolToDBus)
1250f74e643SEd Tanous         {
1260f74e643SEd Tanous             asyncResp->res.jsonValue[protocol.first]["ProtocolEnabled"] = false;
1270f74e643SEd Tanous         }
1280f74e643SEd Tanous 
1290f74e643SEd Tanous         asyncResp->res.jsonValue["HostName"] = getHostName();
1303a8a0088SKowalski, Kamil 
131865fbb75SEd Tanous         crow::connections::systemBus->async_method_call(
132865fbb75SEd Tanous             [asyncResp](const boost::system::error_code ec,
1333a8a0088SKowalski, Kamil                         const std::vector<UnitStruct>& resp) {
1341abe55efSEd Tanous                 if (ec)
1351abe55efSEd Tanous                 {
1363a8a0088SKowalski, Kamil                     asyncResp->res.jsonValue = nlohmann::json::object();
137f12894f8SJason M. Bills                     messages::internalError(asyncResp->res);
138865fbb75SEd Tanous                     return;
1393a8a0088SKowalski, Kamil                 }
1403a8a0088SKowalski, Kamil 
1411abe55efSEd Tanous                 for (auto& unit : resp)
1421abe55efSEd Tanous                 {
1431abe55efSEd Tanous                     for (auto& kv : protocolToDBus)
1441abe55efSEd Tanous                     {
1453a8a0088SKowalski, Kamil                         if (kv.second.serviceName ==
1461abe55efSEd Tanous                             std::get<NET_PROTO_UNIT_NAME>(unit))
1471abe55efSEd Tanous                         {
148865fbb75SEd Tanous                             continue;
14970141561SBorawski.Lukasz                         }
150865fbb75SEd Tanous                         const char* service = kv.first;
151865fbb75SEd Tanous                         const char* socketPath = kv.second.socketPath;
15270141561SBorawski.Lukasz 
153865fbb75SEd Tanous                         asyncResp->res.jsonValue[service]["ProtocolEnabled"] =
1541abe55efSEd Tanous                             std::get<NET_PROTO_UNIT_SUB_STATE>(unit) ==
1551abe55efSEd Tanous                             "running";
156865fbb75SEd Tanous 
157865fbb75SEd Tanous                         crow::connections::systemBus->async_method_call(
1581abe55efSEd Tanous                             [asyncResp, service{std::string(service)},
1591abe55efSEd Tanous                              socketPath](
160865fbb75SEd Tanous                                 const boost::system::error_code ec,
161*abf2add6SEd Tanous                                 const std::variant<std::vector<std::tuple<
162*abf2add6SEd Tanous                                     std::string, std::string>>>& resp) {
1631abe55efSEd Tanous                                 if (ec)
1641abe55efSEd Tanous                                 {
165a08b46ccSJason M. Bills                                     messages::internalError(asyncResp->res);
166865fbb75SEd Tanous                                     return;
1673a8a0088SKowalski, Kamil                                 }
168*abf2add6SEd Tanous                                 const std::vector<
169*abf2add6SEd Tanous                                     std::tuple<std::string, std::string>>*
170*abf2add6SEd Tanous                                     responsePtr = std::get_if<std::vector<
171*abf2add6SEd Tanous                                         std::tuple<std::string, std::string>>>(
1721b6b96c5SEd Tanous                                         &resp);
1731abe55efSEd Tanous                                 if (responsePtr == nullptr ||
1741abe55efSEd Tanous                                     responsePtr->size() < 1)
1751abe55efSEd Tanous                                 {
176865fbb75SEd Tanous                                     return;
17770141561SBorawski.Lukasz                                 }
17870141561SBorawski.Lukasz 
179865fbb75SEd Tanous                                 const std::string& listenStream =
1801abe55efSEd Tanous                                     std::get<NET_PROTO_LISTEN_STREAM>(
1811abe55efSEd Tanous                                         (*responsePtr)[0]);
1821abe55efSEd Tanous                                 std::size_t lastColonPos =
1831abe55efSEd Tanous                                     listenStream.rfind(":");
1841abe55efSEd Tanous                                 if (lastColonPos == std::string::npos)
1851abe55efSEd Tanous                                 {
186865fbb75SEd Tanous                                     // Not a port
187865fbb75SEd Tanous                                     return;
188865fbb75SEd Tanous                                 }
1891abe55efSEd Tanous                                 std::string portStr =
1901abe55efSEd Tanous                                     listenStream.substr(lastColonPos + 1);
191865fbb75SEd Tanous                                 char* endPtr = nullptr;
1921abe55efSEd Tanous                                 // Use strtol instead of stroi to avoid
1931abe55efSEd Tanous                                 // exceptions
1941abe55efSEd Tanous                                 long port =
1951abe55efSEd Tanous                                     std::strtol(portStr.c_str(), &endPtr, 10);
196865fbb75SEd Tanous 
1971abe55efSEd Tanous                                 if (*endPtr != '\0' || portStr.empty())
1981abe55efSEd Tanous                                 {
199865fbb75SEd Tanous                                     // Invalid value
2001abe55efSEd Tanous                                     asyncResp->res.jsonValue[service]["Port"] =
2011abe55efSEd Tanous                                         nullptr;
2021abe55efSEd Tanous                                 }
2031abe55efSEd Tanous                                 else
2041abe55efSEd Tanous                                 {
205865fbb75SEd Tanous                                     // Everything OK
2061abe55efSEd Tanous                                     asyncResp->res.jsonValue[service]["Port"] =
2071abe55efSEd Tanous                                         port;
208865fbb75SEd Tanous                                 }
209865fbb75SEd Tanous                             },
210865fbb75SEd Tanous                             "org.freedesktop.systemd1", socketPath,
211865fbb75SEd Tanous                             "org.freedesktop.DBus.Properties", "Get",
212865fbb75SEd Tanous                             "org.freedesktop.systemd1.Socket", "Listen");
213865fbb75SEd Tanous                     }
214865fbb75SEd Tanous                 }
215865fbb75SEd Tanous             },
216865fbb75SEd Tanous             "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
217865fbb75SEd Tanous             "org.freedesktop.systemd1.Manager", "ListUnits");
218865fbb75SEd Tanous     }
21970141561SBorawski.Lukasz };
22070141561SBorawski.Lukasz 
22170141561SBorawski.Lukasz } // namespace redfish
222