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 24 enum NetworkProtocolUnitStructFields 25 { 26 NET_PROTO_UNIT_NAME, 27 NET_PROTO_UNIT_DESC, 28 NET_PROTO_UNIT_LOAD_STATE, 29 NET_PROTO_UNIT_ACTIVE_STATE, 30 NET_PROTO_UNIT_SUB_STATE, 31 NET_PROTO_UNIT_DEVICE, 32 NET_PROTO_UNIT_OBJ_PATH, 33 NET_PROTO_UNIT_ALWAYS_0, 34 NET_PROTO_UNIT_ALWAYS_EMPTY, 35 NET_PROTO_UNIT_ALWAYS_ROOT_PATH 36 }; 37 38 enum NetworkProtocolListenResponseElements 39 { 40 NET_PROTO_LISTEN_TYPE, 41 NET_PROTO_LISTEN_STREAM 42 }; 43 44 /** 45 * @brief D-Bus Unit structure returned in array from ListUnits Method 46 */ 47 using UnitStruct = 48 std::tuple<std::string, std::string, std::string, std::string, std::string, 49 std::string, sdbusplus::message::object_path, uint32_t, 50 std::string, sdbusplus::message::object_path>; 51 52 struct ServiceConfiguration 53 { 54 const char* serviceName; 55 const char* socketPath; 56 }; 57 58 const static boost::container::flat_map<const char*, ServiceConfiguration> 59 protocolToDBus{ 60 {"SSH", 61 {"dropbear.service", 62 "/org/freedesktop/systemd1/unit/dropbear_2esocket"}}, 63 {"HTTPS", 64 {"phosphor-gevent.service", 65 "/org/freedesktop/systemd1/unit/phosphor_2dgevent_2esocket"}}, 66 {"IPMI", 67 {"phosphor-ipmi-net.service", 68 "/org/freedesktop/systemd1/unit/phosphor_2dipmi_2dnet_2esocket"}}}; 69 70 class NetworkProtocol : public Node 71 { 72 public: 73 NetworkProtocol(CrowApp& app) : 74 Node(app, "/redfish/v1/Managers/openbmc/NetworkProtocol") 75 { 76 Node::json["@odata.type"] = 77 "#ManagerNetworkProtocol.v1_1_0.ManagerNetworkProtocol"; 78 Node::json["@odata.id"] = 79 "/redfish/v1/Managers/openbmc/NetworkProtocol"; 80 Node::json["@odata.context"] = 81 "/redfish/v1/" 82 "$metadata#ManagerNetworkProtocol.ManagerNetworkProtocol"; 83 Node::json["Id"] = "NetworkProtocol"; 84 Node::json["Name"] = "Manager Network Protocol"; 85 Node::json["Description"] = "Manager Network Service"; 86 Node::json["Status"]["Health"] = "OK"; 87 Node::json["Status"]["HealthRollup"] = "OK"; 88 Node::json["Status"]["State"] = "Enabled"; 89 90 for (auto& protocol : protocolToDBus) 91 { 92 Node::json[protocol.first]["ProtocolEnabled"] = false; 93 } 94 95 entityPrivileges = { 96 {boost::beast::http::verb::get, {{"Login"}}}, 97 {boost::beast::http::verb::head, {{"Login"}}}, 98 {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 99 {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 100 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 101 {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 102 } 103 104 private: 105 void doGet(crow::Response& res, const crow::Request& req, 106 const std::vector<std::string>& params) override 107 { 108 std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 109 110 getData(asyncResp); 111 } 112 113 std::string getHostName() const 114 { 115 std::string hostName; 116 117 std::array<char, HOST_NAME_MAX> hostNameCStr; 118 if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0) 119 { 120 hostName = hostNameCStr.data(); 121 } 122 return hostName; 123 } 124 125 void getData(const std::shared_ptr<AsyncResp>& asyncResp) 126 { 127 Node::json["HostName"] = getHostName(); 128 asyncResp->res.jsonValue = Node::json; 129 130 crow::connections::systemBus->async_method_call( 131 [asyncResp](const boost::system::error_code ec, 132 const std::vector<UnitStruct>& resp) { 133 if (ec) 134 { 135 asyncResp->res.jsonValue = nlohmann::json::object(); 136 messages::addMessageToErrorJson(asyncResp->res.jsonValue, 137 messages::internalError()); 138 asyncResp->res.result( 139 boost::beast::http::status::internal_server_error); 140 return; 141 } 142 143 for (auto& unit : resp) 144 { 145 for (auto& kv : protocolToDBus) 146 { 147 if (kv.second.serviceName == 148 std::get<NET_PROTO_UNIT_NAME>(unit)) 149 { 150 continue; 151 } 152 const char* service = kv.first; 153 const char* socketPath = kv.second.socketPath; 154 155 asyncResp->res.jsonValue[service]["ProtocolEnabled"] = 156 std::get<NET_PROTO_UNIT_SUB_STATE>(unit) == 157 "running"; 158 159 crow::connections::systemBus->async_method_call( 160 [asyncResp, service{std::string(service)}, 161 socketPath]( 162 const boost::system::error_code ec, 163 const sdbusplus::message::variant<std::vector< 164 std::tuple<std::string, std::string>>>& 165 resp) { 166 if (ec) 167 { 168 messages::addMessageToJson( 169 asyncResp->res.jsonValue, 170 messages::internalError(), 171 "/" + service); 172 return; 173 } 174 const std::vector<std::tuple< 175 std::string, std::string>>* responsePtr = 176 mapbox::getPtr<const std::vector< 177 std::tuple<std::string, std::string>>>( 178 resp); 179 if (responsePtr == nullptr || 180 responsePtr->size() < 1) 181 { 182 return; 183 } 184 185 const std::string& listenStream = 186 std::get<NET_PROTO_LISTEN_STREAM>( 187 (*responsePtr)[0]); 188 std::size_t lastColonPos = 189 listenStream.rfind(":"); 190 if (lastColonPos == std::string::npos) 191 { 192 // Not a port 193 return; 194 } 195 std::string portStr = 196 listenStream.substr(lastColonPos + 1); 197 char* endPtr = nullptr; 198 // Use strtol instead of stroi to avoid 199 // exceptions 200 long port = 201 std::strtol(portStr.c_str(), &endPtr, 10); 202 203 if (*endPtr != '\0' || portStr.empty()) 204 { 205 // Invalid value 206 asyncResp->res.jsonValue[service]["Port"] = 207 nullptr; 208 } 209 else 210 { 211 // Everything OK 212 asyncResp->res.jsonValue[service]["Port"] = 213 port; 214 } 215 }, 216 "org.freedesktop.systemd1", socketPath, 217 "org.freedesktop.DBus.Properties", "Get", 218 "org.freedesktop.systemd1.Socket", "Listen"); 219 } 220 } 221 }, 222 "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 223 "org.freedesktop.systemd1.Manager", "ListUnits"); 224 } 225 }; 226 227 } // namespace redfish 228