xref: /openbmc/bmcweb/features/redfish/lib/network_protocol.hpp (revision 865fbb756377c462b30fac259b359706598525ce)
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 
2170141561SBorawski.Lukasz namespace redfish {
2270141561SBorawski.Lukasz 
233a8a0088SKowalski, Kamil enum NetworkProtocolUnitStructFields {
243a8a0088SKowalski, Kamil   NET_PROTO_UNIT_NAME,
253a8a0088SKowalski, Kamil   NET_PROTO_UNIT_DESC,
263a8a0088SKowalski, Kamil   NET_PROTO_UNIT_LOAD_STATE,
273a8a0088SKowalski, Kamil   NET_PROTO_UNIT_ACTIVE_STATE,
283a8a0088SKowalski, Kamil   NET_PROTO_UNIT_SUB_STATE,
293a8a0088SKowalski, Kamil   NET_PROTO_UNIT_DEVICE,
303a8a0088SKowalski, Kamil   NET_PROTO_UNIT_OBJ_PATH,
313a8a0088SKowalski, Kamil   NET_PROTO_UNIT_ALWAYS_0,
323a8a0088SKowalski, Kamil   NET_PROTO_UNIT_ALWAYS_EMPTY,
333a8a0088SKowalski, Kamil   NET_PROTO_UNIT_ALWAYS_ROOT_PATH
343a8a0088SKowalski, Kamil };
353a8a0088SKowalski, Kamil 
363a8a0088SKowalski, Kamil enum NetworkProtocolListenResponseElements {
373a8a0088SKowalski, Kamil   NET_PROTO_LISTEN_TYPE,
383a8a0088SKowalski, Kamil   NET_PROTO_LISTEN_STREAM
393a8a0088SKowalski, Kamil };
403a8a0088SKowalski, Kamil 
413a8a0088SKowalski, Kamil /**
423a8a0088SKowalski, Kamil  * @brief D-Bus Unit structure returned in array from ListUnits Method
433a8a0088SKowalski, Kamil  */
443a8a0088SKowalski, Kamil using UnitStruct =
453a8a0088SKowalski, Kamil     std::tuple<std::string, std::string, std::string, std::string, std::string,
463a8a0088SKowalski, Kamil                std::string, sdbusplus::message::object_path, uint32_t,
473a8a0088SKowalski, Kamil                std::string, sdbusplus::message::object_path>;
483a8a0088SKowalski, Kamil 
493a8a0088SKowalski, Kamil struct ServiceConfiguration {
50*865fbb75SEd Tanous   const char* serviceName;
51*865fbb75SEd Tanous   const char* socketPath;
523a8a0088SKowalski, Kamil };
533a8a0088SKowalski, Kamil 
54*865fbb75SEd Tanous const static boost::container::flat_map<const char*, ServiceConfiguration>
55*865fbb75SEd Tanous     protocolToDBus{
56*865fbb75SEd Tanous         {"SSH",
57*865fbb75SEd Tanous          {"dropbear.service",
58*865fbb75SEd Tanous           "/org/freedesktop/systemd1/unit/dropbear_2esocket"}},
59*865fbb75SEd Tanous         {"HTTPS",
60*865fbb75SEd Tanous          {"phosphor-gevent.service",
61*865fbb75SEd Tanous           "/org/freedesktop/systemd1/unit/phosphor_2dgevent_2esocket"}},
62*865fbb75SEd Tanous         {"IPMI",
63*865fbb75SEd Tanous          {"phosphor-ipmi-net.service",
64*865fbb75SEd Tanous           "/org/freedesktop/systemd1/unit/phosphor_2dipmi_2dnet_2esocket"}}};
653a8a0088SKowalski, Kamil 
6670141561SBorawski.Lukasz class NetworkProtocol : public Node {
6770141561SBorawski.Lukasz  public:
6870141561SBorawski.Lukasz   NetworkProtocol(CrowApp& app)
694b1b8683SBorawski.Lukasz       : Node(app, "/redfish/v1/Managers/openbmc/NetworkProtocol") {
7070141561SBorawski.Lukasz     Node::json["@odata.type"] =
7170141561SBorawski.Lukasz         "#ManagerNetworkProtocol.v1_1_0.ManagerNetworkProtocol";
7270141561SBorawski.Lukasz     Node::json["@odata.id"] = "/redfish/v1/Managers/openbmc/NetworkProtocol";
7370141561SBorawski.Lukasz     Node::json["@odata.context"] =
7470141561SBorawski.Lukasz         "/redfish/v1/$metadata#ManagerNetworkProtocol.ManagerNetworkProtocol";
7570141561SBorawski.Lukasz     Node::json["Id"] = "NetworkProtocol";
7670141561SBorawski.Lukasz     Node::json["Name"] = "Manager Network Protocol";
7770141561SBorawski.Lukasz     Node::json["Description"] = "Manager Network Service";
7870141561SBorawski.Lukasz     Node::json["Status"]["Health"] = "OK";
7970141561SBorawski.Lukasz     Node::json["Status"]["HealthRollup"] = "OK";
8070141561SBorawski.Lukasz     Node::json["Status"]["State"] = "Enabled";
813ebd75f7SEd Tanous 
823a8a0088SKowalski, Kamil     for (auto& protocol : protocolToDBus) {
833a8a0088SKowalski, Kamil       Node::json[protocol.first]["ProtocolEnabled"] = false;
843a8a0088SKowalski, Kamil     }
853a8a0088SKowalski, Kamil 
864b1b8683SBorawski.Lukasz     entityPrivileges = {
874b1b8683SBorawski.Lukasz         {boost::beast::http::verb::get, {{"Login"}}},
88e0d918bcSEd Tanous         {boost::beast::http::verb::head, {{"Login"}}},
89e0d918bcSEd Tanous         {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
90e0d918bcSEd Tanous         {boost::beast::http::verb::put, {{"ConfigureManager"}}},
91e0d918bcSEd Tanous         {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
92e0d918bcSEd Tanous         {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
9370141561SBorawski.Lukasz   }
9470141561SBorawski.Lukasz 
9570141561SBorawski.Lukasz  private:
9655c7b7a2SEd Tanous   void doGet(crow::Response& res, const crow::Request& req,
9770141561SBorawski.Lukasz              const std::vector<std::string>& params) override {
983a8a0088SKowalski, Kamil     std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
993a8a0088SKowalski, Kamil 
1003a8a0088SKowalski, Kamil     getData(asyncResp);
10170141561SBorawski.Lukasz   }
10270141561SBorawski.Lukasz 
10370141561SBorawski.Lukasz   std::string getHostName() const {
10470141561SBorawski.Lukasz     std::string hostName;
10570141561SBorawski.Lukasz 
10670141561SBorawski.Lukasz     std::array<char, HOST_NAME_MAX> hostNameCStr;
10770141561SBorawski.Lukasz     if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0) {
10870141561SBorawski.Lukasz       hostName = hostNameCStr.data();
10970141561SBorawski.Lukasz     }
11070141561SBorawski.Lukasz     return hostName;
11170141561SBorawski.Lukasz   }
11270141561SBorawski.Lukasz 
1133a8a0088SKowalski, Kamil   void getData(const std::shared_ptr<AsyncResp>& asyncResp) {
1143a8a0088SKowalski, Kamil     Node::json["HostName"] = getHostName();
1153a8a0088SKowalski, Kamil     asyncResp->res.jsonValue = Node::json;
1163a8a0088SKowalski, Kamil 
117*865fbb75SEd Tanous     crow::connections::systemBus->async_method_call(
118*865fbb75SEd Tanous         [asyncResp](const boost::system::error_code ec,
1193a8a0088SKowalski, Kamil                     const std::vector<UnitStruct>& resp) {
120*865fbb75SEd Tanous           if (ec) {
1213a8a0088SKowalski, Kamil             asyncResp->res.jsonValue = nlohmann::json::object();
1223a8a0088SKowalski, Kamil             messages::addMessageToErrorJson(asyncResp->res.jsonValue,
1233a8a0088SKowalski, Kamil                                             messages::internalError());
1243a8a0088SKowalski, Kamil             asyncResp->res.result(
1253a8a0088SKowalski, Kamil                 boost::beast::http::status::internal_server_error);
126*865fbb75SEd Tanous             return;
1273a8a0088SKowalski, Kamil           }
1283a8a0088SKowalski, Kamil 
1293a8a0088SKowalski, Kamil           for (auto& unit : resp) {
1303a8a0088SKowalski, Kamil             for (auto& kv : protocolToDBus) {
1313a8a0088SKowalski, Kamil               if (kv.second.serviceName ==
1323a8a0088SKowalski, Kamil                   std::get<NET_PROTO_UNIT_NAME>(unit)) {
133*865fbb75SEd Tanous                 continue;
13470141561SBorawski.Lukasz               }
135*865fbb75SEd Tanous               const char* service = kv.first;
136*865fbb75SEd Tanous               const char* socketPath = kv.second.socketPath;
13770141561SBorawski.Lukasz 
138*865fbb75SEd Tanous               asyncResp->res.jsonValue[service]["ProtocolEnabled"] =
139*865fbb75SEd Tanous                   std::get<NET_PROTO_UNIT_SUB_STATE>(unit) == "running";
140*865fbb75SEd Tanous 
141*865fbb75SEd Tanous               crow::connections::systemBus->async_method_call(
142*865fbb75SEd Tanous                   [ asyncResp, service{std::string(service)}, socketPath ](
143*865fbb75SEd Tanous                       const boost::system::error_code ec,
144*865fbb75SEd Tanous                       const sdbusplus::message::variant<std::vector<
145*865fbb75SEd Tanous                           std::tuple<std::string, std::string>>>& resp) {
146*865fbb75SEd Tanous                     if (ec) {
1473a8a0088SKowalski, Kamil                       messages::addMessageToJson(asyncResp->res.jsonValue,
1483a8a0088SKowalski, Kamil                                                  messages::internalError(),
1493a8a0088SKowalski, Kamil                                                  "/" + service);
150*865fbb75SEd Tanous                       return;
1513a8a0088SKowalski, Kamil                     }
152*865fbb75SEd Tanous                     const std::vector<std::tuple<std::string, std::string>>*
153*865fbb75SEd Tanous                         responsePtr = mapbox::getPtr<const std::vector<
154*865fbb75SEd Tanous                             std::tuple<std::string, std::string>>>(resp);
155*865fbb75SEd Tanous                     if (responsePtr == nullptr || responsePtr->size() < 1) {
156*865fbb75SEd Tanous                       return;
15770141561SBorawski.Lukasz                     }
15870141561SBorawski.Lukasz 
159*865fbb75SEd Tanous                     const std::string& listenStream =
160*865fbb75SEd Tanous                         std::get<NET_PROTO_LISTEN_STREAM>((*responsePtr)[0]);
161*865fbb75SEd Tanous                     std::size_t lastColonPos = listenStream.rfind(":");
162*865fbb75SEd Tanous                     if (lastColonPos == std::string::npos) {
163*865fbb75SEd Tanous                       // Not a port
164*865fbb75SEd Tanous                       return;
165*865fbb75SEd Tanous                     }
166*865fbb75SEd Tanous                     std::string portStr = listenStream.substr(lastColonPos + 1);
167*865fbb75SEd Tanous                     char* endPtr = nullptr;
168*865fbb75SEd Tanous                     // Use strtol instead of stroi to avoid exceptions
169*865fbb75SEd Tanous                     long port = std::strtol(portStr.c_str(), &endPtr, 10);
170*865fbb75SEd Tanous 
171*865fbb75SEd Tanous                     if (*endPtr != '\0' || portStr.empty()) {
172*865fbb75SEd Tanous                       // Invalid value
173*865fbb75SEd Tanous                       asyncResp->res.jsonValue[service]["Port"] = nullptr;
174*865fbb75SEd Tanous                     } else {
175*865fbb75SEd Tanous                       // Everything OK
176*865fbb75SEd Tanous                       asyncResp->res.jsonValue[service]["Port"] = port;
177*865fbb75SEd Tanous                     }
178*865fbb75SEd Tanous                   },
179*865fbb75SEd Tanous                   "org.freedesktop.systemd1", socketPath,
180*865fbb75SEd Tanous                   "org.freedesktop.DBus.Properties", "Get",
181*865fbb75SEd Tanous                   "org.freedesktop.systemd1.Socket", "Listen");
182*865fbb75SEd Tanous             }
183*865fbb75SEd Tanous           }
184*865fbb75SEd Tanous         },
185*865fbb75SEd Tanous         "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
186*865fbb75SEd Tanous         "org.freedesktop.systemd1.Manager", "ListUnits");
187*865fbb75SEd Tanous   }
18870141561SBorawski.Lukasz };
18970141561SBorawski.Lukasz 
19070141561SBorawski.Lukasz }  // namespace redfish
191