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 21abf2add6SEd Tanous #include <variant> 22abf2add6SEd 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", 63*5ded8c79SJennifer Lee {"dropbear.socket", 64865fbb75SEd Tanous "/org/freedesktop/systemd1/unit/dropbear_2esocket"}}, 65865fbb75SEd Tanous {"HTTPS", 66*5ded8c79SJennifer Lee {"bmcweb.service", 67*5ded8c79SJennifer Lee "/org/freedesktop/systemd1/unit/" 68*5ded8c79SJennifer Lee "bmcweb_2esocket"}}, //"/org/freedesktop/systemd1/unit/phosphor_2dgevent_2esocket"}}, 69865fbb75SEd Tanous {"IPMI", 70*5ded8c79SJennifer Lee {"phosphor-ipmi-net.socket", "/org/freedesktop/systemd1/unit/" 71*5ded8c79SJennifer Lee "phosphor_2dipmi_2dnet_2esocket"}}}; 723a8a0088SKowalski, Kamil 731abe55efSEd Tanous class NetworkProtocol : public Node 741abe55efSEd Tanous { 7570141561SBorawski.Lukasz public: 761abe55efSEd Tanous NetworkProtocol(CrowApp& app) : 7797b7ccf3SEd Tanous Node(app, "/redfish/v1/Managers/bmc/NetworkProtocol") 781abe55efSEd Tanous { 794b1b8683SBorawski.Lukasz entityPrivileges = { 804b1b8683SBorawski.Lukasz {boost::beast::http::verb::get, {{"Login"}}}, 81e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 82e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 83e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 84e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 85e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 8670141561SBorawski.Lukasz } 8770141561SBorawski.Lukasz 8870141561SBorawski.Lukasz private: 8955c7b7a2SEd Tanous void doGet(crow::Response& res, const crow::Request& req, 901abe55efSEd Tanous const std::vector<std::string>& params) override 911abe55efSEd Tanous { 923a8a0088SKowalski, Kamil std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 933a8a0088SKowalski, Kamil 943a8a0088SKowalski, Kamil getData(asyncResp); 9570141561SBorawski.Lukasz } 9670141561SBorawski.Lukasz 971abe55efSEd Tanous std::string getHostName() const 981abe55efSEd Tanous { 9970141561SBorawski.Lukasz std::string hostName; 10070141561SBorawski.Lukasz 10170141561SBorawski.Lukasz std::array<char, HOST_NAME_MAX> hostNameCStr; 1021abe55efSEd Tanous if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0) 1031abe55efSEd Tanous { 10470141561SBorawski.Lukasz hostName = hostNameCStr.data(); 10570141561SBorawski.Lukasz } 10670141561SBorawski.Lukasz return hostName; 10770141561SBorawski.Lukasz } 10870141561SBorawski.Lukasz 1091abe55efSEd Tanous void getData(const std::shared_ptr<AsyncResp>& asyncResp) 1101abe55efSEd Tanous { 1110f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1120f74e643SEd Tanous "#ManagerNetworkProtocol.v1_1_0.ManagerNetworkProtocol"; 1130f74e643SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 1140f74e643SEd Tanous "/redfish/v1/Managers/bmc/NetworkProtocol"; 1150f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 1160f74e643SEd Tanous "/redfish/v1/" 1170f74e643SEd Tanous "$metadata#ManagerNetworkProtocol.ManagerNetworkProtocol"; 1180f74e643SEd Tanous asyncResp->res.jsonValue["Id"] = "NetworkProtocol"; 1190f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Network Protocol"; 1200f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = "Manager Network Service"; 1210f74e643SEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = "OK"; 1220f74e643SEd Tanous asyncResp->res.jsonValue["Status"]["HealthRollup"] = "OK"; 1230f74e643SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 1240f74e643SEd Tanous 1250f74e643SEd Tanous for (auto& protocol : protocolToDBus) 1260f74e643SEd Tanous { 1270f74e643SEd Tanous asyncResp->res.jsonValue[protocol.first]["ProtocolEnabled"] = false; 1280f74e643SEd Tanous } 1290f74e643SEd Tanous 1300f74e643SEd Tanous asyncResp->res.jsonValue["HostName"] = getHostName(); 1313a8a0088SKowalski, Kamil 132865fbb75SEd Tanous crow::connections::systemBus->async_method_call( 133865fbb75SEd Tanous [asyncResp](const boost::system::error_code ec, 1343a8a0088SKowalski, Kamil const std::vector<UnitStruct>& resp) { 1351abe55efSEd Tanous if (ec) 1361abe55efSEd Tanous { 1373a8a0088SKowalski, Kamil asyncResp->res.jsonValue = nlohmann::json::object(); 138f12894f8SJason M. Bills messages::internalError(asyncResp->res); 139865fbb75SEd Tanous return; 1403a8a0088SKowalski, Kamil } 1413a8a0088SKowalski, Kamil 1421abe55efSEd Tanous for (auto& unit : resp) 1431abe55efSEd Tanous { 1441abe55efSEd Tanous for (auto& kv : protocolToDBus) 1451abe55efSEd Tanous { 146*5ded8c79SJennifer Lee if (kv.second.serviceName != 1471abe55efSEd Tanous std::get<NET_PROTO_UNIT_NAME>(unit)) 1481abe55efSEd Tanous { 149865fbb75SEd Tanous continue; 15070141561SBorawski.Lukasz } 151865fbb75SEd Tanous const char* service = kv.first; 152865fbb75SEd Tanous const char* socketPath = kv.second.socketPath; 15370141561SBorawski.Lukasz 154865fbb75SEd Tanous asyncResp->res.jsonValue[service]["ProtocolEnabled"] = 155*5ded8c79SJennifer Lee (std::get<NET_PROTO_UNIT_SUB_STATE>(unit) == 156*5ded8c79SJennifer Lee "running") || 157*5ded8c79SJennifer Lee (std::get<NET_PROTO_UNIT_SUB_STATE>(unit) == 158*5ded8c79SJennifer Lee "listening"); 159865fbb75SEd Tanous 160865fbb75SEd Tanous crow::connections::systemBus->async_method_call( 16143b761d0SEd Tanous [asyncResp, service{std::string(service)}]( 162865fbb75SEd Tanous const boost::system::error_code ec, 163abf2add6SEd Tanous const std::variant<std::vector<std::tuple< 164abf2add6SEd Tanous std::string, std::string>>>& resp) { 1651abe55efSEd Tanous if (ec) 1661abe55efSEd Tanous { 167a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 168865fbb75SEd Tanous return; 1693a8a0088SKowalski, Kamil } 170abf2add6SEd Tanous const std::vector< 171abf2add6SEd Tanous std::tuple<std::string, std::string>>* 172abf2add6SEd Tanous responsePtr = std::get_if<std::vector< 173abf2add6SEd Tanous std::tuple<std::string, std::string>>>( 1741b6b96c5SEd Tanous &resp); 1751abe55efSEd Tanous if (responsePtr == nullptr || 1761abe55efSEd Tanous responsePtr->size() < 1) 1771abe55efSEd Tanous { 178865fbb75SEd Tanous return; 17970141561SBorawski.Lukasz } 18070141561SBorawski.Lukasz 181865fbb75SEd Tanous const std::string& listenStream = 1821abe55efSEd Tanous std::get<NET_PROTO_LISTEN_STREAM>( 1831abe55efSEd Tanous (*responsePtr)[0]); 1841abe55efSEd Tanous std::size_t lastColonPos = 1851abe55efSEd Tanous listenStream.rfind(":"); 1861abe55efSEd Tanous if (lastColonPos == std::string::npos) 1871abe55efSEd Tanous { 188865fbb75SEd Tanous // Not a port 189865fbb75SEd Tanous return; 190865fbb75SEd Tanous } 1911abe55efSEd Tanous std::string portStr = 1921abe55efSEd Tanous listenStream.substr(lastColonPos + 1); 193865fbb75SEd Tanous char* endPtr = nullptr; 1941abe55efSEd Tanous // Use strtol instead of stroi to avoid 1951abe55efSEd Tanous // exceptions 1961abe55efSEd Tanous long port = 1971abe55efSEd Tanous std::strtol(portStr.c_str(), &endPtr, 10); 198865fbb75SEd Tanous 1991abe55efSEd Tanous if (*endPtr != '\0' || portStr.empty()) 2001abe55efSEd Tanous { 201865fbb75SEd Tanous // Invalid value 2021abe55efSEd Tanous asyncResp->res.jsonValue[service]["Port"] = 2031abe55efSEd Tanous nullptr; 2041abe55efSEd Tanous } 2051abe55efSEd Tanous else 2061abe55efSEd Tanous { 207865fbb75SEd Tanous // Everything OK 2081abe55efSEd Tanous asyncResp->res.jsonValue[service]["Port"] = 2091abe55efSEd Tanous port; 210865fbb75SEd Tanous } 211865fbb75SEd Tanous }, 212865fbb75SEd Tanous "org.freedesktop.systemd1", socketPath, 213865fbb75SEd Tanous "org.freedesktop.DBus.Properties", "Get", 214865fbb75SEd Tanous "org.freedesktop.systemd1.Socket", "Listen"); 215865fbb75SEd Tanous } 216865fbb75SEd Tanous } 217865fbb75SEd Tanous }, 218865fbb75SEd Tanous "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 219865fbb75SEd Tanous "org.freedesktop.systemd1.Manager", "ListUnits"); 220865fbb75SEd Tanous } 221501be32bSraviteja-b 222501be32bSraviteja-b void handleHostnamePatch(const std::string& hostName, 223501be32bSraviteja-b const std::shared_ptr<AsyncResp>& asyncResp) 224501be32bSraviteja-b { 225501be32bSraviteja-b crow::connections::systemBus->async_method_call( 226501be32bSraviteja-b [asyncResp](const boost::system::error_code ec) { 227501be32bSraviteja-b if (ec) 228501be32bSraviteja-b { 229501be32bSraviteja-b messages::internalError(asyncResp->res); 230501be32bSraviteja-b return; 231501be32bSraviteja-b } 232501be32bSraviteja-b messages::success(asyncResp->res); 233501be32bSraviteja-b }, 234501be32bSraviteja-b "xyz.openbmc_project.Network", 235501be32bSraviteja-b "/xyz/openbmc_project/network/config", 236501be32bSraviteja-b "org.freedesktop.DBus.Properties", "Set", 237501be32bSraviteja-b "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 238501be32bSraviteja-b std::variant<std::string>(hostName)); 239501be32bSraviteja-b } 240501be32bSraviteja-b 241501be32bSraviteja-b void doPatch(crow::Response& res, const crow::Request& req, 242501be32bSraviteja-b const std::vector<std::string>& params) override 243501be32bSraviteja-b { 244501be32bSraviteja-b std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 245501be32bSraviteja-b std::optional<std::string> newHostName; 246501be32bSraviteja-b 247501be32bSraviteja-b if (!json_util::readJson(req, res, "HostName", newHostName)) 248501be32bSraviteja-b { 249501be32bSraviteja-b return; 250501be32bSraviteja-b } 251501be32bSraviteja-b if (newHostName) 252501be32bSraviteja-b { 253501be32bSraviteja-b handleHostnamePatch(*newHostName, asyncResp); 254501be32bSraviteja-b return; 255501be32bSraviteja-b } 256501be32bSraviteja-b } 25770141561SBorawski.Lukasz }; 25870141561SBorawski.Lukasz 25970141561SBorawski.Lukasz } // namespace redfish 260