1 /* 2 // Copyright (c) 2018 Intel Corporation 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 */ 16 #pragma once 17 18 #include "error_messages.hpp" 19 #include "node.hpp" 20 21 namespace redfish { 22 23 enum NetworkProtocolUnitStructFields { 24 NET_PROTO_UNIT_NAME, 25 NET_PROTO_UNIT_DESC, 26 NET_PROTO_UNIT_LOAD_STATE, 27 NET_PROTO_UNIT_ACTIVE_STATE, 28 NET_PROTO_UNIT_SUB_STATE, 29 NET_PROTO_UNIT_DEVICE, 30 NET_PROTO_UNIT_OBJ_PATH, 31 NET_PROTO_UNIT_ALWAYS_0, 32 NET_PROTO_UNIT_ALWAYS_EMPTY, 33 NET_PROTO_UNIT_ALWAYS_ROOT_PATH 34 }; 35 36 enum NetworkProtocolListenResponseElements { 37 NET_PROTO_LISTEN_TYPE, 38 NET_PROTO_LISTEN_STREAM 39 }; 40 41 /** 42 * @brief D-Bus Unit structure returned in array from ListUnits Method 43 */ 44 using UnitStruct = 45 std::tuple<std::string, std::string, std::string, std::string, std::string, 46 std::string, sdbusplus::message::object_path, uint32_t, 47 std::string, sdbusplus::message::object_path>; 48 49 struct ServiceConfiguration { 50 const char* serviceName; 51 const char* socketPath; 52 }; 53 54 const static boost::container::flat_map<const char*, ServiceConfiguration> 55 protocolToDBus{ 56 {"SSH", 57 {"dropbear.service", 58 "/org/freedesktop/systemd1/unit/dropbear_2esocket"}}, 59 {"HTTPS", 60 {"phosphor-gevent.service", 61 "/org/freedesktop/systemd1/unit/phosphor_2dgevent_2esocket"}}, 62 {"IPMI", 63 {"phosphor-ipmi-net.service", 64 "/org/freedesktop/systemd1/unit/phosphor_2dipmi_2dnet_2esocket"}}}; 65 66 class NetworkProtocol : public Node { 67 public: 68 NetworkProtocol(CrowApp& app) 69 : Node(app, "/redfish/v1/Managers/openbmc/NetworkProtocol") { 70 Node::json["@odata.type"] = 71 "#ManagerNetworkProtocol.v1_1_0.ManagerNetworkProtocol"; 72 Node::json["@odata.id"] = "/redfish/v1/Managers/openbmc/NetworkProtocol"; 73 Node::json["@odata.context"] = 74 "/redfish/v1/$metadata#ManagerNetworkProtocol.ManagerNetworkProtocol"; 75 Node::json["Id"] = "NetworkProtocol"; 76 Node::json["Name"] = "Manager Network Protocol"; 77 Node::json["Description"] = "Manager Network Service"; 78 Node::json["Status"]["Health"] = "OK"; 79 Node::json["Status"]["HealthRollup"] = "OK"; 80 Node::json["Status"]["State"] = "Enabled"; 81 82 for (auto& protocol : protocolToDBus) { 83 Node::json[protocol.first]["ProtocolEnabled"] = false; 84 } 85 86 entityPrivileges = { 87 {boost::beast::http::verb::get, {{"Login"}}}, 88 {boost::beast::http::verb::head, {{"Login"}}}, 89 {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 90 {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 91 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 92 {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 93 } 94 95 private: 96 void doGet(crow::Response& res, const crow::Request& req, 97 const std::vector<std::string>& params) override { 98 std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 99 100 getData(asyncResp); 101 } 102 103 std::string getHostName() const { 104 std::string hostName; 105 106 std::array<char, HOST_NAME_MAX> hostNameCStr; 107 if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0) { 108 hostName = hostNameCStr.data(); 109 } 110 return hostName; 111 } 112 113 void getData(const std::shared_ptr<AsyncResp>& asyncResp) { 114 Node::json["HostName"] = getHostName(); 115 asyncResp->res.jsonValue = Node::json; 116 117 crow::connections::systemBus->async_method_call( 118 [asyncResp](const boost::system::error_code ec, 119 const std::vector<UnitStruct>& resp) { 120 if (ec) { 121 asyncResp->res.jsonValue = nlohmann::json::object(); 122 messages::addMessageToErrorJson(asyncResp->res.jsonValue, 123 messages::internalError()); 124 asyncResp->res.result( 125 boost::beast::http::status::internal_server_error); 126 return; 127 } 128 129 for (auto& unit : resp) { 130 for (auto& kv : protocolToDBus) { 131 if (kv.second.serviceName == 132 std::get<NET_PROTO_UNIT_NAME>(unit)) { 133 continue; 134 } 135 const char* service = kv.first; 136 const char* socketPath = kv.second.socketPath; 137 138 asyncResp->res.jsonValue[service]["ProtocolEnabled"] = 139 std::get<NET_PROTO_UNIT_SUB_STATE>(unit) == "running"; 140 141 crow::connections::systemBus->async_method_call( 142 [ asyncResp, service{std::string(service)}, socketPath ]( 143 const boost::system::error_code ec, 144 const sdbusplus::message::variant<std::vector< 145 std::tuple<std::string, std::string>>>& resp) { 146 if (ec) { 147 messages::addMessageToJson(asyncResp->res.jsonValue, 148 messages::internalError(), 149 "/" + service); 150 return; 151 } 152 const std::vector<std::tuple<std::string, std::string>>* 153 responsePtr = mapbox::getPtr<const std::vector< 154 std::tuple<std::string, std::string>>>(resp); 155 if (responsePtr == nullptr || responsePtr->size() < 1) { 156 return; 157 } 158 159 const std::string& listenStream = 160 std::get<NET_PROTO_LISTEN_STREAM>((*responsePtr)[0]); 161 std::size_t lastColonPos = listenStream.rfind(":"); 162 if (lastColonPos == std::string::npos) { 163 // Not a port 164 return; 165 } 166 std::string portStr = listenStream.substr(lastColonPos + 1); 167 char* endPtr = nullptr; 168 // Use strtol instead of stroi to avoid exceptions 169 long port = std::strtol(portStr.c_str(), &endPtr, 10); 170 171 if (*endPtr != '\0' || portStr.empty()) { 172 // Invalid value 173 asyncResp->res.jsonValue[service]["Port"] = nullptr; 174 } else { 175 // Everything OK 176 asyncResp->res.jsonValue[service]["Port"] = port; 177 } 178 }, 179 "org.freedesktop.systemd1", socketPath, 180 "org.freedesktop.DBus.Properties", "Get", 181 "org.freedesktop.systemd1.Socket", "Listen"); 182 } 183 } 184 }, 185 "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 186 "org.freedesktop.systemd1.Manager", "ListUnits"); 187 } 188 }; 189 190 } // namespace redfish 191