blob: 6211fccfa2e0f31ac81c273aa2ab61786db92085 [file] [log] [blame]
James Feist5b4aa862018-08-16 14:07:01 -07001// Copyright (c) 2018 Intel Corporation
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
Ed Tanousb9b2e0b2018-09-13 13:47:50 -070014
James Feist5b4aa862018-08-16 14:07:01 -070015#pragma once
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080016#include "app.hpp"
17#include "async_resp.hpp"
18#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080019#include "dbus_utility.hpp"
Nan Zhoud5c80ad2022-07-11 01:16:31 +000020#include "http_request.hpp"
21#include "http_response.hpp"
22#include "logging.hpp"
Ed Tanous1aa0c2b2022-02-08 12:24:30 +010023#include "parsing.hpp"
Nan Zhoud5c80ad2022-07-11 01:16:31 +000024#include "routing.hpp"
Ed Tanous50ebd4a2023-01-19 19:03:17 -080025#include "str_utility.hpp"
Nan Zhoud5c80ad2022-07-11 01:16:31 +000026
27#include <systemd/sd-bus-protocol.h>
28#include <systemd/sd-bus.h>
Ed Tanous911ac312017-08-15 09:37:42 -070029#include <tinyxml2.h>
Ed Tanous1abe55e2018-09-05 08:30:59 -070030
Ed Tanous11ba3972022-07-11 09:50:41 -070031#include <boost/algorithm/string/classification.hpp>
32#include <boost/algorithm/string/predicate.hpp>
Nan Zhoud5c80ad2022-07-11 01:16:31 +000033#include <boost/beast/http/status.hpp>
34#include <boost/beast/http/verb.hpp>
35#include <boost/container/flat_map.hpp>
36#include <boost/container/vector.hpp>
37#include <boost/iterator/iterator_facade.hpp>
George Liue99073f2022-12-09 11:06:16 +080038#include <boost/system/error_code.hpp>
Nan Zhoud5c80ad2022-07-11 01:16:31 +000039#include <nlohmann/json.hpp>
40#include <sdbusplus/asio/connection.hpp>
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +020041#include <sdbusplus/asio/property.hpp>
Nan Zhoud5c80ad2022-07-11 01:16:31 +000042#include <sdbusplus/exception.hpp>
43#include <sdbusplus/message.hpp>
44#include <sdbusplus/message/native_types.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050045
Nan Zhoud5c80ad2022-07-11 01:16:31 +000046#include <algorithm>
47#include <array>
48#include <cerrno>
49#include <cstdint>
50#include <cstring>
James Feist4418c7f2019-04-15 11:09:15 -070051#include <filesystem>
Ed Tanousd4bb9bb2018-05-16 13:36:42 -070052#include <fstream>
Nan Zhoud5c80ad2022-07-11 01:16:31 +000053#include <functional>
54#include <initializer_list>
55#include <iterator>
56#include <limits>
57#include <map>
58#include <memory>
Ramesh Iyyard9207042019-07-05 08:04:42 -050059#include <regex>
Nan Zhoud5c80ad2022-07-11 01:16:31 +000060#include <string>
61#include <string_view>
62#include <type_traits>
Ed Tanousb5a76932020-09-29 16:16:58 -070063#include <utility>
Nan Zhoud5c80ad2022-07-11 01:16:31 +000064#include <variant>
65#include <vector>
66
67// IWYU pragma: no_include <boost/algorithm/string/detail/classification.hpp>
68// IWYU pragma: no_include <boost/system/detail/error_code.hpp>
69// IWYU pragma: no_include <boost/system/detail/error_category.hpp>
70// IWYU pragma: no_include <errno.h>
71// IWYU pragma: no_include <string.h>
72// IWYU pragma: no_include <ext/alloc_traits.h>
73// IWYU pragma: no_include <exception>
74// IWYU pragma: no_include <boost/type_index/type_index_facade.hpp>
Ed Tanous911ac312017-08-15 09:37:42 -070075
Ed Tanous1abe55e2018-09-05 08:30:59 -070076namespace crow
77{
78namespace openbmc_mapper
79{
Ed Tanous23a21a12020-07-25 04:45:05 +000080const constexpr char* notFoundMsg = "404 Not Found";
81const constexpr char* badReqMsg = "400 Bad Request";
82const constexpr char* methodNotAllowedMsg = "405 Method Not Allowed";
83const constexpr char* forbiddenMsg = "403 Forbidden";
Ed Tanous1aa0c2b2022-02-08 12:24:30 +010084const constexpr char* unsupportedMediaMsg = "415 Unsupported Media Type";
Ed Tanous23a21a12020-07-25 04:45:05 +000085const constexpr char* methodFailedMsg = "500 Method Call Failed";
86const constexpr char* methodOutputFailedMsg = "500 Method Output Error";
87const constexpr char* notFoundDesc =
Matt Spinler2ae60092018-12-06 10:35:36 -060088 "org.freedesktop.DBus.Error.FileNotFound: path or object not found";
Ed Tanous23a21a12020-07-25 04:45:05 +000089const constexpr char* propNotFoundDesc =
90 "The specified property cannot be found";
91const constexpr char* noJsonDesc = "No JSON object could be decoded";
Ed Tanous1aa0c2b2022-02-08 12:24:30 +010092const constexpr char* invalidContentType =
93 "Content-type header is missing or invalid";
Ed Tanous23a21a12020-07-25 04:45:05 +000094const constexpr char* methodNotFoundDesc =
95 "The specified method cannot be found";
96const constexpr char* methodNotAllowedDesc = "Method not allowed";
97const constexpr char* forbiddenPropDesc =
98 "The specified property cannot be created";
99const constexpr char* forbiddenResDesc =
100 "The specified resource cannot be created";
Matt Spinler2ae60092018-12-06 10:35:36 -0600101
Josh Lehan482c45a2022-03-29 17:10:44 -0700102inline bool validateFilename(const std::string& filename)
103{
Ed Tanous4b242742023-05-11 09:51:51 -0700104 static std::regex validFilename(R"(^[\w\- ]+(\.?[\w\- ]*)$)");
Josh Lehan482c45a2022-03-29 17:10:44 -0700105
106 return std::regex_match(filename, validFilename);
107}
108
Ed Tanous23a21a12020-07-25 04:45:05 +0000109inline void setErrorResponse(crow::Response& res,
110 boost::beast::http::status result,
Ed Tanous26ccae32023-02-16 10:28:44 -0800111 const std::string& desc, std::string_view msg)
Matt Spinler2ae60092018-12-06 10:35:36 -0600112{
113 res.result(result);
Ed Tanous14766872022-03-15 10:44:42 -0700114 res.jsonValue["data"]["description"] = desc;
115 res.jsonValue["message"] = msg;
116 res.jsonValue["status"] = "error";
Matt Spinler2ae60092018-12-06 10:35:36 -0600117}
118
Ed Tanousb5a76932020-09-29 16:16:58 -0700119inline void
120 introspectObjects(const std::string& processName,
121 const std::string& objectPath,
122 const std::shared_ptr<bmcweb::AsyncResp>& transaction)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700123{
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700124 if (transaction->res.jsonValue.is_null())
125 {
Ed Tanous14766872022-03-15 10:44:42 -0700126 transaction->res.jsonValue["status"] = "ok";
127 transaction->res.jsonValue["bus_name"] = processName;
128 transaction->res.jsonValue["objects"] = nlohmann::json::array();
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700129 }
130
Ed Tanous1abe55e2018-09-05 08:30:59 -0700131 crow::connections::systemBus->async_method_call(
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700132 [transaction, processName{std::string(processName)},
133 objectPath{std::string(objectPath)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800134 const boost::system::error_code& ec,
Ed Tanous81ce6092020-12-17 16:54:55 +0000135 const std::string& introspectXml) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700136 if (ec)
137 {
Ed Tanous62598e32023-07-17 17:06:25 -0700138 BMCWEB_LOG_ERROR(
139 "Introspect call failed with error: {} on process: {} path: {}",
140 ec.message(), processName, objectPath);
Ed Tanous002d39b2022-05-31 08:59:27 -0700141 return;
142 }
143 nlohmann::json::object_t object;
144 object["path"] = objectPath;
Ed Tanous14766872022-03-15 10:44:42 -0700145
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500146 transaction->res.jsonValue["objects"].emplace_back(std::move(object));
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700147
Ed Tanous002d39b2022-05-31 08:59:27 -0700148 tinyxml2::XMLDocument doc;
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700149
Ed Tanous002d39b2022-05-31 08:59:27 -0700150 doc.Parse(introspectXml.c_str());
151 tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
152 if (pRoot == nullptr)
153 {
Ed Tanous62598e32023-07-17 17:06:25 -0700154 BMCWEB_LOG_ERROR("XML document failed to parse {} {}", processName,
155 objectPath);
Ed Tanous002d39b2022-05-31 08:59:27 -0700156 }
157 else
158 {
159 tinyxml2::XMLElement* node = pRoot->FirstChildElement("node");
160 while (node != nullptr)
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700161 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700162 const char* childPath = node->Attribute("name");
163 if (childPath != nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700164 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700165 std::string newpath;
166 if (objectPath != "/")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700167 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700168 newpath += objectPath;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700169 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700170 newpath += std::string("/") + childPath;
171 // introspect the subobjects as well
172 introspectObjects(processName, newpath, transaction);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700173 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700174
175 node = node->NextSiblingElement("node");
Ed Tanous1abe55e2018-09-05 08:30:59 -0700176 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700177 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700178 },
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700179 processName, objectPath, "org.freedesktop.DBus.Introspectable",
Ed Tanous1abe55e2018-09-05 08:30:59 -0700180 "Introspect");
Ed Tanous911ac312017-08-15 09:37:42 -0700181}
Ed Tanous64530012018-02-06 17:08:16 -0800182
Ed Tanous23a21a12020-07-25 04:45:05 +0000183inline void getPropertiesForEnumerate(
184 const std::string& objectPath, const std::string& service,
Ed Tanousb5a76932020-09-29 16:16:58 -0700185 const std::string& interface,
186 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Matt Spinler2df1e7d2018-12-05 15:53:16 -0600187{
Ed Tanous62598e32023-07-17 17:06:25 -0700188 BMCWEB_LOG_DEBUG("getPropertiesForEnumerate {} {} {}", objectPath, service,
189 interface);
Matt Spinler2df1e7d2018-12-05 15:53:16 -0600190
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200191 sdbusplus::asio::getAllProperties(
192 *crow::connections::systemBus, service, objectPath, interface,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800193 [asyncResp, objectPath, service,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800194 interface](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800195 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700196 if (ec)
197 {
Ed Tanous62598e32023-07-17 17:06:25 -0700198 BMCWEB_LOG_ERROR(
199 "GetAll on path {} iface {} service {} failed with code {}",
200 objectPath, interface, service, ec);
Ed Tanous002d39b2022-05-31 08:59:27 -0700201 return;
202 }
Matt Spinler2df1e7d2018-12-05 15:53:16 -0600203
Ed Tanous002d39b2022-05-31 08:59:27 -0700204 nlohmann::json& dataJson = asyncResp->res.jsonValue["data"];
205 nlohmann::json& objectJson = dataJson[objectPath];
206 if (objectJson.is_null())
207 {
208 objectJson = nlohmann::json::object();
209 }
Matt Spinler2df1e7d2018-12-05 15:53:16 -0600210
Ed Tanous002d39b2022-05-31 08:59:27 -0700211 for (const auto& [name, value] : propertiesList)
212 {
213 nlohmann::json& propertyJson = objectJson[name];
214 std::visit(
215 [&propertyJson](auto&& val) {
216 if constexpr (std::is_same_v<std::decay_t<decltype(val)>,
217 sdbusplus::message::unix_fd>)
218 {
219 propertyJson = val.fd;
220 }
221 else
222 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700223 propertyJson = val;
224 }
225 },
226 value);
227 }
Krzysztof Grobelnyc1343bf2022-08-31 13:15:26 +0200228 });
Matt Spinler2df1e7d2018-12-05 15:53:16 -0600229}
230
231// Find any results that weren't picked up by ObjectManagers, to be
232// called after all ObjectManagers are searched for and called.
Ed Tanous23a21a12020-07-25 04:45:05 +0000233inline void findRemainingObjectsForEnumerate(
Ed Tanousb5a76932020-09-29 16:16:58 -0700234 const std::string& objectPath,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800235 const std::shared_ptr<dbus::utility::MapperGetSubTreeResponse>& subtree,
Ed Tanousb5a76932020-09-29 16:16:58 -0700236 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Matt Spinler2df1e7d2018-12-05 15:53:16 -0600237{
Ed Tanous62598e32023-07-17 17:06:25 -0700238 BMCWEB_LOG_DEBUG("findRemainingObjectsForEnumerate");
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500239 const nlohmann::json& dataJson = asyncResp->res.jsonValue["data"];
Matt Spinler2df1e7d2018-12-05 15:53:16 -0600240
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500241 for (const auto& [path, interface_map] : *subtree)
Matt Spinler2df1e7d2018-12-05 15:53:16 -0600242 {
243 if (path == objectPath)
244 {
245 // An enumerate does not return the target path's properties
246 continue;
247 }
248 if (dataJson.find(path) == dataJson.end())
249 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500250 for (const auto& [service, interfaces] : interface_map)
Matt Spinler2df1e7d2018-12-05 15:53:16 -0600251 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500252 for (const auto& interface : interfaces)
Matt Spinler2df1e7d2018-12-05 15:53:16 -0600253 {
Ed Tanous11ba3972022-07-11 09:50:41 -0700254 if (!interface.starts_with("org.freedesktop.DBus"))
Matt Spinler2df1e7d2018-12-05 15:53:16 -0600255 {
256 getPropertiesForEnumerate(path, service, interface,
257 asyncResp);
258 }
259 }
260 }
261 }
262 }
263}
264
Matt Spinler3ae4ba72018-12-05 14:01:22 -0600265struct InProgressEnumerateData
266{
zhanghch058d1b46d2021-04-01 11:18:24 +0800267 InProgressEnumerateData(
268 const std::string& objectPathIn,
269 const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) :
Ed Tanous23a21a12020-07-25 04:45:05 +0000270 objectPath(objectPathIn),
zhanghch058d1b46d2021-04-01 11:18:24 +0800271 asyncResp(asyncRespIn)
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500272 {}
Matt Spinler3ae4ba72018-12-05 14:01:22 -0600273
274 ~InProgressEnumerateData()
275 {
Ed Tanous24b2fe82022-01-06 12:45:54 -0800276 try
277 {
278 findRemainingObjectsForEnumerate(objectPath, subtree, asyncResp);
279 }
280 catch (...)
281 {
Ed Tanous62598e32023-07-17 17:06:25 -0700282 BMCWEB_LOG_CRITICAL(
283 "findRemainingObjectsForEnumerate threw exception");
Ed Tanous24b2fe82022-01-06 12:45:54 -0800284 }
Matt Spinler3ae4ba72018-12-05 14:01:22 -0600285 }
286
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800287 InProgressEnumerateData(const InProgressEnumerateData&) = delete;
288 InProgressEnumerateData(InProgressEnumerateData&&) = delete;
289 InProgressEnumerateData& operator=(const InProgressEnumerateData&) = delete;
290 InProgressEnumerateData& operator=(InProgressEnumerateData&&) = delete;
Matt Spinler3ae4ba72018-12-05 14:01:22 -0600291 const std::string objectPath;
Ed Tanousb9d36b42022-02-26 21:42:46 -0800292 std::shared_ptr<dbus::utility::MapperGetSubTreeResponse> subtree;
Matt Spinler3ae4ba72018-12-05 14:01:22 -0600293 std::shared_ptr<bmcweb::AsyncResp> asyncResp;
294};
295
Ed Tanous23a21a12020-07-25 04:45:05 +0000296inline void getManagedObjectsForEnumerate(
Ed Tanous81ce6092020-12-17 16:54:55 +0000297 const std::string& objectName, const std::string& objectManagerPath,
298 const std::string& connectionName,
Ed Tanousb5a76932020-09-29 16:16:58 -0700299 const std::shared_ptr<InProgressEnumerateData>& transaction)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700300{
Ed Tanous62598e32023-07-17 17:06:25 -0700301 BMCWEB_LOG_DEBUG(
302 "getManagedObjectsForEnumerate {} object_manager_path {} connection_name {}",
303 objectName, objectManagerPath, connectionName);
George Liu5eb468d2023-06-20 17:03:24 +0800304 sdbusplus::message::object_path path(objectManagerPath);
305 dbus::utility::getManagedObjects(
306 connectionName, path,
Ed Tanous81ce6092020-12-17 16:54:55 +0000307 [transaction, objectName,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800308 connectionName](const boost::system::error_code& ec,
Ed Tanous81ce6092020-12-17 16:54:55 +0000309 const dbus::utility::ManagedObjectType& objects) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700310 if (ec)
311 {
Ed Tanous62598e32023-07-17 17:06:25 -0700312 BMCWEB_LOG_ERROR(
313 "GetManagedObjects on path {} on connection {} failed with code {}",
314 objectName, connectionName, ec);
Ed Tanous002d39b2022-05-31 08:59:27 -0700315 return;
316 }
Ed Tanous64530012018-02-06 17:08:16 -0800317
Ed Tanous002d39b2022-05-31 08:59:27 -0700318 nlohmann::json& dataJson =
319 transaction->asyncResp->res.jsonValue["data"];
Ed Tanous049a0512018-11-01 13:58:42 -0700320
Ed Tanous002d39b2022-05-31 08:59:27 -0700321 for (const auto& objectPath : objects)
322 {
Ed Tanous11ba3972022-07-11 09:50:41 -0700323 if (objectPath.first.str.starts_with(objectName))
Ed Tanous049a0512018-11-01 13:58:42 -0700324 {
Ed Tanous62598e32023-07-17 17:06:25 -0700325 BMCWEB_LOG_DEBUG("Reading object {}", objectPath.first.str);
Ed Tanous002d39b2022-05-31 08:59:27 -0700326 nlohmann::json& objectJson = dataJson[objectPath.first.str];
327 if (objectJson.is_null())
Ed Tanous1abe55e2018-09-05 08:30:59 -0700328 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700329 objectJson = nlohmann::json::object();
Ed Tanous1abe55e2018-09-05 08:30:59 -0700330 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500331 for (const auto& interface : objectPath.second)
Ed Tanous049a0512018-11-01 13:58:42 -0700332 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700333 for (const auto& property : interface.second)
Ed Tanous049a0512018-11-01 13:58:42 -0700334 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700335 nlohmann::json& propertyJson =
336 objectJson[property.first];
337 std::visit(
338 [&propertyJson](auto&& val) {
339 if constexpr (std::is_same_v<
340 std::decay_t<decltype(val)>,
341 sdbusplus::message::unix_fd>)
342 {
343 propertyJson = val.fd;
344 }
345 else
346 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700347 propertyJson = val;
348 }
349 },
350 property.second);
Ed Tanous049a0512018-11-01 13:58:42 -0700351 }
352 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700353 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700354 for (const auto& interface : objectPath.second)
355 {
356 if (interface.first == "org.freedesktop.DBus.ObjectManager")
357 {
358 getManagedObjectsForEnumerate(objectPath.first.str,
359 objectPath.first.str,
360 connectionName, transaction);
361 }
362 }
363 }
George Liu5eb468d2023-06-20 17:03:24 +0800364 });
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700365}
366
Ed Tanous23a21a12020-07-25 04:45:05 +0000367inline void findObjectManagerPathForEnumerate(
Ed Tanous81ce6092020-12-17 16:54:55 +0000368 const std::string& objectName, const std::string& connectionName,
Ed Tanousb5a76932020-09-29 16:16:58 -0700369 const std::shared_ptr<InProgressEnumerateData>& transaction)
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700370{
Ed Tanous62598e32023-07-17 17:06:25 -0700371 BMCWEB_LOG_DEBUG("Finding objectmanager for path {} on connection:{}",
372 objectName, connectionName);
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700373 crow::connections::systemBus->async_method_call(
Ed Tanous81ce6092020-12-17 16:54:55 +0000374 [transaction, objectName, connectionName](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800375 const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800376 const dbus::utility::MapperGetAncestorsResponse& objects) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700377 if (ec)
378 {
Ed Tanous62598e32023-07-17 17:06:25 -0700379 BMCWEB_LOG_ERROR("GetAncestors on path {} failed with code {}",
380 objectName, ec);
Ed Tanous002d39b2022-05-31 08:59:27 -0700381 return;
382 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700383
Ed Tanous002d39b2022-05-31 08:59:27 -0700384 for (const auto& pathGroup : objects)
385 {
386 for (const auto& connectionGroup : pathGroup.second)
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700387 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700388 if (connectionGroup.first == connectionName)
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700389 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700390 // Found the object manager path for this resource.
391 getManagedObjectsForEnumerate(objectName, pathGroup.first,
392 connectionName, transaction);
393 return;
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700394 }
395 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700396 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700397 },
398 "xyz.openbmc_project.ObjectMapper",
399 "/xyz/openbmc_project/object_mapper",
Ed Tanous81ce6092020-12-17 16:54:55 +0000400 "xyz.openbmc_project.ObjectMapper", "GetAncestors", objectName,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500401 std::array<const char*, 1>{"org.freedesktop.DBus.ObjectManager"});
Ed Tanousaa2e59c2018-04-12 12:17:20 -0700402}
Ed Tanous64530012018-02-06 17:08:16 -0800403
Ed Tanous7c091622019-05-23 11:42:36 -0700404// Uses GetObject to add the object info about the target /enumerate path to
405// the results of GetSubTree, as GetSubTree will not return info for the
Matt Spinler3ae4ba72018-12-05 14:01:22 -0600406// target path, and then continues on enumerating the rest of the tree.
Ed Tanousb5a76932020-09-29 16:16:58 -0700407inline void getObjectAndEnumerate(
408 const std::shared_ptr<InProgressEnumerateData>& transaction)
Matt Spinler3ae4ba72018-12-05 14:01:22 -0600409{
George Liu2b731192023-01-11 16:27:13 +0800410 dbus::utility::getDbusObject(
411 transaction->objectPath, {},
412 [transaction](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800413 const dbus::utility::MapperGetObject& objects) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700414 if (ec)
415 {
Ed Tanous62598e32023-07-17 17:06:25 -0700416 BMCWEB_LOG_ERROR("GetObject for path {} failed with code {}",
417 transaction->objectPath, ec);
Ed Tanous002d39b2022-05-31 08:59:27 -0700418 return;
419 }
Matt Spinler3ae4ba72018-12-05 14:01:22 -0600420
Ed Tanous62598e32023-07-17 17:06:25 -0700421 BMCWEB_LOG_DEBUG("GetObject for {} has {} entries",
422 transaction->objectPath, objects.size());
Ed Tanous002d39b2022-05-31 08:59:27 -0700423 if (!objects.empty())
424 {
425 transaction->subtree->emplace_back(transaction->objectPath,
426 objects);
427 }
Matt Spinler3ae4ba72018-12-05 14:01:22 -0600428
Ed Tanous002d39b2022-05-31 08:59:27 -0700429 // Map indicating connection name, and the path where the object
430 // manager exists
431 boost::container::flat_map<std::string, std::string> connections;
Matt Spinler3ae4ba72018-12-05 14:01:22 -0600432
Ed Tanous002d39b2022-05-31 08:59:27 -0700433 for (const auto& object : *(transaction->subtree))
434 {
435 for (const auto& connection : object.second)
Matt Spinler3ae4ba72018-12-05 14:01:22 -0600436 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700437 for (const auto& interface : connection.second)
Matt Spinler3ae4ba72018-12-05 14:01:22 -0600438 {
Ed Tanous62598e32023-07-17 17:06:25 -0700439 BMCWEB_LOG_DEBUG("{} has interface {}", connection.first,
440 interface);
Ed Tanous002d39b2022-05-31 08:59:27 -0700441 if (interface == "org.freedesktop.DBus.ObjectManager")
Matt Spinler3ae4ba72018-12-05 14:01:22 -0600442 {
Ed Tanous62598e32023-07-17 17:06:25 -0700443 BMCWEB_LOG_DEBUG("found object manager path {}",
444 object.first);
Ed Tanousf8fe53e2022-06-30 15:55:45 -0700445 connections[connection.first] = object.first;
Matt Spinler3ae4ba72018-12-05 14:01:22 -0600446 }
447 }
448 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700449 }
Ed Tanous62598e32023-07-17 17:06:25 -0700450 BMCWEB_LOG_DEBUG("Got {} connections", connections.size());
Matt Spinler3ae4ba72018-12-05 14:01:22 -0600451
Ed Tanous002d39b2022-05-31 08:59:27 -0700452 for (const auto& connection : connections)
453 {
454 // If we already know where the object manager is, we don't
455 // need to search for it, we can call directly in to
456 // getManagedObjects
457 if (!connection.second.empty())
Matt Spinler3ae4ba72018-12-05 14:01:22 -0600458 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700459 getManagedObjectsForEnumerate(transaction->objectPath,
460 connection.second,
461 connection.first, transaction);
Matt Spinler3ae4ba72018-12-05 14:01:22 -0600462 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700463 else
464 {
465 // otherwise we need to find the object manager path
466 // before we can continue
467 findObjectManagerPathForEnumerate(
468 transaction->objectPath, connection.first, transaction);
469 }
470 }
George Liu2b731192023-01-11 16:27:13 +0800471 });
Matt Spinler3ae4ba72018-12-05 14:01:22 -0600472}
Ed Tanous64530012018-02-06 17:08:16 -0800473
Ed Tanousd4bb9bb2018-05-16 13:36:42 -0700474// Structure for storing data on an in progress action
Ed Tanous1abe55e2018-09-05 08:30:59 -0700475struct InProgressActionData
476{
Lei YU28dd5ca2023-03-17 13:17:05 +0800477 explicit InProgressActionData(
478 const std::shared_ptr<bmcweb::AsyncResp>& res) :
479 asyncResp(res)
Ed Tanous23a21a12020-07-25 04:45:05 +0000480 {}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700481 ~InProgressActionData()
482 {
Matt Spinler16caaee2019-01-15 11:40:34 -0600483 // Methods could have been called across different owners
484 // and interfaces, where some calls failed and some passed.
485 //
486 // The rules for this are:
487 // * if no method was called - error
488 // * if a method failed and none passed - error
489 // (converse: if at least one method passed - OK)
490 // * for the method output:
491 // * if output processing didn't fail, return the data
492
493 // Only deal with method returns if nothing failed earlier
Lei YU28dd5ca2023-03-17 13:17:05 +0800494 if (asyncResp->res.result() == boost::beast::http::status::ok)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700495 {
Matt Spinler16caaee2019-01-15 11:40:34 -0600496 if (!methodPassed)
497 {
Matt Spinler06b1b632019-06-18 16:09:25 -0500498 if (!methodFailed)
Matt Spinler16caaee2019-01-15 11:40:34 -0600499 {
Lei YU28dd5ca2023-03-17 13:17:05 +0800500 setErrorResponse(asyncResp->res,
501 boost::beast::http::status::not_found,
Matt Spinler16caaee2019-01-15 11:40:34 -0600502 methodNotFoundDesc, notFoundMsg);
503 }
504 }
505 else
506 {
507 if (outputFailed)
508 {
509 setErrorResponse(
Lei YU28dd5ca2023-03-17 13:17:05 +0800510 asyncResp->res,
511 boost::beast::http::status::internal_server_error,
Matt Spinler16caaee2019-01-15 11:40:34 -0600512 "Method output failure", methodOutputFailedMsg);
513 }
514 else
515 {
Lei YU28dd5ca2023-03-17 13:17:05 +0800516 asyncResp->res.jsonValue["status"] = "ok";
517 asyncResp->res.jsonValue["message"] = "200 OK";
518 asyncResp->res.jsonValue["data"] = methodResponse;
Matt Spinler16caaee2019-01-15 11:40:34 -0600519 }
520 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700521 }
Ed Tanousd4bb9bb2018-05-16 13:36:42 -0700522 }
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800523 InProgressActionData(const InProgressActionData&) = delete;
524 InProgressActionData(InProgressActionData&&) = delete;
525 InProgressActionData& operator=(const InProgressActionData&) = delete;
526 InProgressActionData& operator=(InProgressActionData&&) = delete;
Ed Tanousd4bb9bb2018-05-16 13:36:42 -0700527
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500528 void setErrorStatus(const std::string& desc)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700529 {
Lei YU28dd5ca2023-03-17 13:17:05 +0800530 setErrorResponse(asyncResp->res,
531 boost::beast::http::status::bad_request, desc,
Matt Spinlerc0eb9bd2019-01-09 15:22:30 -0600532 badReqMsg);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700533 }
Lei YU28dd5ca2023-03-17 13:17:05 +0800534 std::shared_ptr<bmcweb::AsyncResp> asyncResp;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700535 std::string path;
536 std::string methodName;
Matt Spinlerde818812018-12-11 16:39:20 -0600537 std::string interfaceName;
Matt Spinler16caaee2019-01-15 11:40:34 -0600538 bool methodPassed = false;
539 bool methodFailed = false;
540 bool outputFailed = false;
Matt Spinler39a4e392019-01-15 11:53:13 -0600541 bool convertedToArray = false;
Matt Spinler16caaee2019-01-15 11:40:34 -0600542 nlohmann::json methodResponse;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700543 nlohmann::json arguments;
Ed Tanousd4bb9bb2018-05-16 13:36:42 -0700544};
545
Ed Tanous23a21a12020-07-25 04:45:05 +0000546inline std::vector<std::string> dbusArgSplit(const std::string& string)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700547{
548 std::vector<std::string> ret;
549 if (string.empty())
550 {
551 return ret;
Ed Tanousd4bb9bb2018-05-16 13:36:42 -0700552 }
Ed Tanous0f0353b2019-10-24 11:37:51 -0700553 ret.emplace_back("");
Ed Tanous1abe55e2018-09-05 08:30:59 -0700554 int containerDepth = 0;
555
556 for (std::string::const_iterator character = string.begin();
557 character != string.end(); character++)
558 {
559 ret.back() += *character;
560 switch (*character)
561 {
562 case ('a'):
563 break;
564 case ('('):
565 case ('{'):
566 containerDepth++;
567 break;
568 case ('}'):
569 case (')'):
570 containerDepth--;
571 if (containerDepth == 0)
572 {
573 if (character + 1 != string.end())
574 {
Ed Tanous0f0353b2019-10-24 11:37:51 -0700575 ret.emplace_back("");
Ed Tanous1abe55e2018-09-05 08:30:59 -0700576 }
577 }
578 break;
579 default:
580 if (containerDepth == 0)
581 {
582 if (character + 1 != string.end())
583 {
Ed Tanous0f0353b2019-10-24 11:37:51 -0700584 ret.emplace_back("");
Ed Tanous1abe55e2018-09-05 08:30:59 -0700585 }
586 }
587 break;
588 }
589 }
Matt Spinler4ae611d2019-01-11 15:37:06 -0600590
591 return ret;
Ed Tanousd4bb9bb2018-05-16 13:36:42 -0700592}
593
Ed Tanous81ce6092020-12-17 16:54:55 +0000594inline int convertJsonToDbus(sd_bus_message* m, const std::string& argType,
595 const nlohmann::json& inputJson)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700596{
597 int r = 0;
Ed Tanous62598e32023-07-17 17:06:25 -0700598 BMCWEB_LOG_DEBUG(
599 "Converting {} to type: {}",
600 inputJson.dump(2, ' ', true, nlohmann::json::error_handler_t::replace),
601 argType);
Ed Tanous81ce6092020-12-17 16:54:55 +0000602 const std::vector<std::string> argTypes = dbusArgSplit(argType);
Ed Tanousd4bb9bb2018-05-16 13:36:42 -0700603
Ed Tanous1abe55e2018-09-05 08:30:59 -0700604 // Assume a single object for now.
Ed Tanous81ce6092020-12-17 16:54:55 +0000605 const nlohmann::json* j = &inputJson;
606 nlohmann::json::const_iterator jIt = inputJson.begin();
Ed Tanousd4bb9bb2018-05-16 13:36:42 -0700607
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500608 for (const std::string& argCode : argTypes)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700609 {
610 // If we are decoding multiple objects, grab the pointer to the
611 // iterator, and increment it for the next loop
612 if (argTypes.size() > 1)
613 {
Ed Tanous81ce6092020-12-17 16:54:55 +0000614 if (jIt == inputJson.end())
Ed Tanous1abe55e2018-09-05 08:30:59 -0700615 {
616 return -2;
617 }
618 j = &*jIt;
619 jIt++;
620 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500621 const int64_t* intValue = j->get_ptr<const int64_t*>();
622 const std::string* stringValue = j->get_ptr<const std::string*>();
623 const double* doubleValue = j->get_ptr<const double*>();
624 const bool* b = j->get_ptr<const bool*>();
Ed Tanous1abe55e2018-09-05 08:30:59 -0700625 int64_t v = 0;
626 double d = 0.0;
Ed Tanousd4bb9bb2018-05-16 13:36:42 -0700627
Ed Tanous1abe55e2018-09-05 08:30:59 -0700628 // Do some basic type conversions that make sense. uint can be
629 // converted to int. int and uint can be converted to double
Ed Tanous66664f22019-10-11 13:05:49 -0700630 if (intValue == nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700631 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500632 const uint64_t* uintValue = j->get_ptr<const uint64_t*>();
Ed Tanous66664f22019-10-11 13:05:49 -0700633 if (uintValue != nullptr)
634 {
635 v = static_cast<int64_t>(*uintValue);
636 intValue = &v;
637 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700638 }
Ed Tanous66664f22019-10-11 13:05:49 -0700639 if (doubleValue == nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700640 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500641 const uint64_t* uintValue = j->get_ptr<const uint64_t*>();
Ed Tanous66664f22019-10-11 13:05:49 -0700642 if (uintValue != nullptr)
643 {
644 d = static_cast<double>(*uintValue);
645 doubleValue = &d;
646 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700647 }
Ed Tanous66664f22019-10-11 13:05:49 -0700648 if (doubleValue == nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700649 {
Ed Tanous66664f22019-10-11 13:05:49 -0700650 if (intValue != nullptr)
651 {
652 d = static_cast<double>(*intValue);
653 doubleValue = &d;
654 }
Ed Tanousd4bb9bb2018-05-16 13:36:42 -0700655 }
656
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700657 if (argCode == "s")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700658 {
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700659 if (stringValue == nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700660 {
661 return -1;
662 }
Ed Tanous271584a2019-07-09 16:24:22 -0700663 r = sd_bus_message_append_basic(
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500664 m, argCode[0], static_cast<const void*>(stringValue->data()));
Ed Tanous1abe55e2018-09-05 08:30:59 -0700665 if (r < 0)
666 {
667 return r;
668 }
Ed Tanousd4bb9bb2018-05-16 13:36:42 -0700669 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700670 else if (argCode == "i")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700671 {
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700672 if (intValue == nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700673 {
674 return -1;
675 }
Adriana Kobylakc66c8592019-08-06 15:08:05 -0500676 if ((*intValue < std::numeric_limits<int32_t>::lowest()) ||
677 (*intValue > std::numeric_limits<int32_t>::max()))
678 {
679 return -ERANGE;
680 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700681 int32_t i = static_cast<int32_t>(*intValue);
682 r = sd_bus_message_append_basic(m, argCode[0], &i);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700683 if (r < 0)
684 {
685 return r;
686 }
Ed Tanousd4bb9bb2018-05-16 13:36:42 -0700687 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700688 else if (argCode == "b")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700689 {
690 // lots of ways bool could be represented here. Try them all
Ed Tanouse662eae2022-01-25 10:39:19 -0800691 int boolInt = 0;
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700692 if (intValue != nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700693 {
Adriana Kobylakc66c8592019-08-06 15:08:05 -0500694 if (*intValue == 1)
695 {
Ed Tanouse662eae2022-01-25 10:39:19 -0800696 boolInt = 1;
Adriana Kobylakc66c8592019-08-06 15:08:05 -0500697 }
698 else if (*intValue == 0)
699 {
Ed Tanouse662eae2022-01-25 10:39:19 -0800700 boolInt = 0;
Adriana Kobylakc66c8592019-08-06 15:08:05 -0500701 }
702 else
703 {
704 return -ERANGE;
705 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700706 }
707 else if (b != nullptr)
708 {
Matt Spinlera2f02632019-01-18 10:15:35 -0600709 boolInt = *b ? 1 : 0;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700710 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700711 else if (stringValue != nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700712 {
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700713 boolInt = boost::istarts_with(*stringValue, "t") ? 1 : 0;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700714 }
715 else
716 {
717 return -1;
718 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700719 r = sd_bus_message_append_basic(m, argCode[0], &boolInt);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700720 if (r < 0)
721 {
722 return r;
723 }
724 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700725 else if (argCode == "n")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700726 {
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700727 if (intValue == nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700728 {
729 return -1;
730 }
Adriana Kobylakc66c8592019-08-06 15:08:05 -0500731 if ((*intValue < std::numeric_limits<int16_t>::lowest()) ||
732 (*intValue > std::numeric_limits<int16_t>::max()))
733 {
734 return -ERANGE;
735 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700736 int16_t n = static_cast<int16_t>(*intValue);
737 r = sd_bus_message_append_basic(m, argCode[0], &n);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700738 if (r < 0)
739 {
740 return r;
741 }
742 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700743 else if (argCode == "x")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700744 {
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700745 if (intValue == nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700746 {
747 return -1;
748 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700749 r = sd_bus_message_append_basic(m, argCode[0], intValue);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700750 if (r < 0)
751 {
752 return r;
753 }
754 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700755 else if (argCode == "y")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700756 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500757 const uint64_t* uintValue = j->get_ptr<const uint64_t*>();
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700758 if (uintValue == nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700759 {
760 return -1;
761 }
Ed Tanous23a21a12020-07-25 04:45:05 +0000762 if (*uintValue > std::numeric_limits<uint8_t>::max())
Adriana Kobylakc66c8592019-08-06 15:08:05 -0500763 {
764 return -ERANGE;
765 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700766 uint8_t y = static_cast<uint8_t>(*uintValue);
767 r = sd_bus_message_append_basic(m, argCode[0], &y);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700768 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700769 else if (argCode == "q")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700770 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500771 const uint64_t* uintValue = j->get_ptr<const uint64_t*>();
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700772 if (uintValue == nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700773 {
774 return -1;
775 }
Ed Tanous23a21a12020-07-25 04:45:05 +0000776 if (*uintValue > std::numeric_limits<uint16_t>::max())
Adriana Kobylakc66c8592019-08-06 15:08:05 -0500777 {
778 return -ERANGE;
779 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700780 uint16_t q = static_cast<uint16_t>(*uintValue);
781 r = sd_bus_message_append_basic(m, argCode[0], &q);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700782 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700783 else if (argCode == "u")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700784 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500785 const uint64_t* uintValue = j->get_ptr<const uint64_t*>();
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700786 if (uintValue == nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700787 {
788 return -1;
789 }
Ed Tanous23a21a12020-07-25 04:45:05 +0000790 if (*uintValue > std::numeric_limits<uint32_t>::max())
Adriana Kobylakc66c8592019-08-06 15:08:05 -0500791 {
792 return -ERANGE;
793 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700794 uint32_t u = static_cast<uint32_t>(*uintValue);
795 r = sd_bus_message_append_basic(m, argCode[0], &u);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700796 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700797 else if (argCode == "t")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700798 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500799 const uint64_t* uintValue = j->get_ptr<const uint64_t*>();
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700800 if (uintValue == nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700801 {
802 return -1;
803 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700804 r = sd_bus_message_append_basic(m, argCode[0], uintValue);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700805 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700806 else if (argCode == "d")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700807 {
Adriana Kobylakc66c8592019-08-06 15:08:05 -0500808 if (doubleValue == nullptr)
809 {
810 return -1;
811 }
812 if ((*doubleValue < std::numeric_limits<double>::lowest()) ||
813 (*doubleValue > std::numeric_limits<double>::max()))
814 {
815 return -ERANGE;
816 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700817 sd_bus_message_append_basic(m, argCode[0], doubleValue);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700818 }
Ed Tanous11ba3972022-07-11 09:50:41 -0700819 else if (argCode.starts_with("a"))
Ed Tanous1abe55e2018-09-05 08:30:59 -0700820 {
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700821 std::string containedType = argCode.substr(1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700822 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY,
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700823 containedType.c_str());
Ed Tanous1abe55e2018-09-05 08:30:59 -0700824 if (r < 0)
825 {
826 return r;
827 }
828
Ed Tanous0dfeda62019-10-24 11:21:38 -0700829 for (const auto& it : *j)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700830 {
Ed Tanous0dfeda62019-10-24 11:21:38 -0700831 r = convertJsonToDbus(m, containedType, it);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700832 if (r < 0)
833 {
834 return r;
835 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700836 }
837 sd_bus_message_close_container(m);
838 }
Ed Tanous11ba3972022-07-11 09:50:41 -0700839 else if (argCode.starts_with("v"))
Ed Tanous1abe55e2018-09-05 08:30:59 -0700840 {
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700841 std::string containedType = argCode.substr(1);
Ed Tanous62598e32023-07-17 17:06:25 -0700842 BMCWEB_LOG_DEBUG("variant type: {} appending variant of type: {}",
843 argCode, containedType);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700844 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT,
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700845 containedType.c_str());
Ed Tanous1abe55e2018-09-05 08:30:59 -0700846 if (r < 0)
847 {
848 return r;
849 }
850
Ed Tanous81ce6092020-12-17 16:54:55 +0000851 r = convertJsonToDbus(m, containedType, inputJson);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700852 if (r < 0)
853 {
854 return r;
855 }
856
857 r = sd_bus_message_close_container(m);
858 if (r < 0)
859 {
860 return r;
861 }
862 }
Ed Tanous11ba3972022-07-11 09:50:41 -0700863 else if (argCode.starts_with("(") && argCode.ends_with(")"))
Ed Tanous1abe55e2018-09-05 08:30:59 -0700864 {
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700865 std::string containedType = argCode.substr(1, argCode.size() - 1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700866 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT,
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700867 containedType.c_str());
Ed Tanousf1eebf02019-03-04 15:57:09 -0800868 if (r < 0)
869 {
870 return r;
871 }
872
Ed Tanous1abe55e2018-09-05 08:30:59 -0700873 nlohmann::json::const_iterator it = j->begin();
Ed Tanous81ce6092020-12-17 16:54:55 +0000874 for (const std::string& argCode2 : dbusArgSplit(argType))
Ed Tanous1abe55e2018-09-05 08:30:59 -0700875 {
876 if (it == j->end())
877 {
878 return -1;
879 }
Ed Tanouscb13a392020-07-25 19:02:03 +0000880 r = convertJsonToDbus(m, argCode2, *it);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700881 if (r < 0)
882 {
883 return r;
884 }
885 it++;
886 }
887 r = sd_bus_message_close_container(m);
888 }
Ed Tanous11ba3972022-07-11 09:50:41 -0700889 else if (argCode.starts_with("{") && argCode.ends_with("}"))
Ed Tanous1abe55e2018-09-05 08:30:59 -0700890 {
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700891 std::string containedType = argCode.substr(1, argCode.size() - 1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700892 r = sd_bus_message_open_container(m, SD_BUS_TYPE_DICT_ENTRY,
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700893 containedType.c_str());
Ed Tanousf1eebf02019-03-04 15:57:09 -0800894 if (r < 0)
895 {
896 return r;
897 }
898
Ed Tanouse3cb5a32018-08-08 14:16:49 -0700899 std::vector<std::string> codes = dbusArgSplit(containedType);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700900 if (codes.size() != 2)
901 {
902 return -1;
903 }
Ed Tanous2c70f802020-09-28 14:29:23 -0700904 const std::string& keyType = codes[0];
905 const std::string& valueType = codes[1];
Ed Tanous3174e4d2020-10-07 11:41:22 -0700906 for (const auto& it : j->items())
Ed Tanous1abe55e2018-09-05 08:30:59 -0700907 {
Ed Tanous2c70f802020-09-28 14:29:23 -0700908 r = convertJsonToDbus(m, keyType, it.key());
Ed Tanous1abe55e2018-09-05 08:30:59 -0700909 if (r < 0)
910 {
911 return r;
912 }
913
Ed Tanous2c70f802020-09-28 14:29:23 -0700914 r = convertJsonToDbus(m, valueType, it.value());
Ed Tanous1abe55e2018-09-05 08:30:59 -0700915 if (r < 0)
916 {
917 return r;
918 }
919 }
920 r = sd_bus_message_close_container(m);
921 }
922 else
923 {
924 return -2;
925 }
926 if (r < 0)
927 {
928 return r;
Ed Tanous75db20e2018-07-27 13:44:44 -0700929 }
Ed Tanousd4bb9bb2018-05-16 13:36:42 -0700930
Ed Tanous1abe55e2018-09-05 08:30:59 -0700931 if (argTypes.size() > 1)
932 {
933 jIt++;
Ed Tanousd4bb9bb2018-05-16 13:36:42 -0700934 }
Ed Tanousd4bb9bb2018-05-16 13:36:42 -0700935 }
Matt Spinler127ea542019-01-14 11:04:28 -0600936
937 return r;
Ed Tanousd4bb9bb2018-05-16 13:36:42 -0700938}
939
Matt Spinlerd22a7132019-01-14 12:14:30 -0600940template <typename T>
Patrick Williams59d494e2022-07-22 19:26:55 -0500941int readMessageItem(const std::string& typeCode, sdbusplus::message_t& m,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500942 nlohmann::json& data)
Matt Spinlerd22a7132019-01-14 12:14:30 -0600943{
944 T value;
945
946 int r = sd_bus_message_read_basic(m.get(), typeCode.front(), &value);
947 if (r < 0)
948 {
Ed Tanous62598e32023-07-17 17:06:25 -0700949 BMCWEB_LOG_ERROR("sd_bus_message_read_basic on type {} failed!",
950 typeCode);
Matt Spinlerd22a7132019-01-14 12:14:30 -0600951 return r;
952 }
953
954 data = value;
955 return 0;
956}
957
Patrick Williams59d494e2022-07-22 19:26:55 -0500958int convertDBusToJSON(const std::string& returnType, sdbusplus::message_t& m,
959 nlohmann::json& response);
Matt Spinler6df8f992019-01-14 12:47:47 -0600960
Ed Tanous23a21a12020-07-25 04:45:05 +0000961inline int readDictEntryFromMessage(const std::string& typeCode,
Patrick Williams59d494e2022-07-22 19:26:55 -0500962 sdbusplus::message_t& m,
Ed Tanous23a21a12020-07-25 04:45:05 +0000963 nlohmann::json& object)
Matt Spinler6df8f992019-01-14 12:47:47 -0600964{
965 std::vector<std::string> types = dbusArgSplit(typeCode);
966 if (types.size() != 2)
967 {
Ed Tanous62598e32023-07-17 17:06:25 -0700968 BMCWEB_LOG_ERROR("wrong number contained types in dictionary: {}",
969 types.size());
Matt Spinler6df8f992019-01-14 12:47:47 -0600970 return -1;
971 }
972
973 int r = sd_bus_message_enter_container(m.get(), SD_BUS_TYPE_DICT_ENTRY,
974 typeCode.c_str());
975 if (r < 0)
976 {
Ed Tanous62598e32023-07-17 17:06:25 -0700977 BMCWEB_LOG_ERROR("sd_bus_message_enter_container with rc {}", r);
Matt Spinler6df8f992019-01-14 12:47:47 -0600978 return r;
979 }
980
981 nlohmann::json key;
982 r = convertDBusToJSON(types[0], m, key);
983 if (r < 0)
984 {
985 return r;
986 }
987
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500988 const std::string* keyPtr = key.get_ptr<const std::string*>();
Matt Spinler6df8f992019-01-14 12:47:47 -0600989 if (keyPtr == nullptr)
990 {
991 // json doesn't support non-string keys. If we hit this condition,
992 // convert the result to a string so we can proceed
Ed Tanous71f52d92021-02-19 08:51:17 -0800993 key = key.dump(2, ' ', true, nlohmann::json::error_handler_t::replace);
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500994 keyPtr = key.get_ptr<const std::string*>();
Ed Tanous7c091622019-05-23 11:42:36 -0700995 // in theory this can't fail now, but lets be paranoid about it
996 // anyway
Matt Spinler6df8f992019-01-14 12:47:47 -0600997 if (keyPtr == nullptr)
998 {
999 return -1;
1000 }
1001 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001002 nlohmann::json& value = object[*keyPtr];
Matt Spinler6df8f992019-01-14 12:47:47 -06001003
1004 r = convertDBusToJSON(types[1], m, value);
1005 if (r < 0)
1006 {
1007 return r;
1008 }
1009
1010 r = sd_bus_message_exit_container(m.get());
1011 if (r < 0)
1012 {
Ed Tanous62598e32023-07-17 17:06:25 -07001013 BMCWEB_LOG_ERROR("sd_bus_message_exit_container failed");
Matt Spinler6df8f992019-01-14 12:47:47 -06001014 return r;
1015 }
1016
1017 return 0;
1018}
1019
Ed Tanous23a21a12020-07-25 04:45:05 +00001020inline int readArrayFromMessage(const std::string& typeCode,
Patrick Williams59d494e2022-07-22 19:26:55 -05001021 sdbusplus::message_t& m, nlohmann::json& data)
Matt Spinler6df8f992019-01-14 12:47:47 -06001022{
1023 if (typeCode.size() < 2)
1024 {
Ed Tanous62598e32023-07-17 17:06:25 -07001025 BMCWEB_LOG_ERROR("Type code {} too small for an array", typeCode);
Matt Spinler6df8f992019-01-14 12:47:47 -06001026 return -1;
1027 }
1028
1029 std::string containedType = typeCode.substr(1);
1030
1031 int r = sd_bus_message_enter_container(m.get(), SD_BUS_TYPE_ARRAY,
1032 containedType.c_str());
1033 if (r < 0)
1034 {
Ed Tanous62598e32023-07-17 17:06:25 -07001035 BMCWEB_LOG_ERROR("sd_bus_message_enter_container failed with rc {}", r);
Matt Spinler6df8f992019-01-14 12:47:47 -06001036 return r;
1037 }
1038
Ed Tanous11ba3972022-07-11 09:50:41 -07001039 bool dict = containedType.starts_with("{") && containedType.ends_with("}");
Matt Spinler6df8f992019-01-14 12:47:47 -06001040
1041 if (dict)
1042 {
1043 // Remove the { }
1044 containedType = containedType.substr(1, containedType.size() - 2);
1045 data = nlohmann::json::object();
1046 }
1047 else
1048 {
1049 data = nlohmann::json::array();
1050 }
1051
1052 while (true)
1053 {
Ed Tanouse662eae2022-01-25 10:39:19 -08001054 r = sd_bus_message_at_end(m.get(), 0);
Matt Spinler6df8f992019-01-14 12:47:47 -06001055 if (r < 0)
1056 {
Ed Tanous62598e32023-07-17 17:06:25 -07001057 BMCWEB_LOG_ERROR("sd_bus_message_at_end failed");
Matt Spinler6df8f992019-01-14 12:47:47 -06001058 return r;
1059 }
1060
1061 if (r > 0)
1062 {
1063 break;
1064 }
1065
1066 // Dictionaries are only ever seen in an array
1067 if (dict)
1068 {
1069 r = readDictEntryFromMessage(containedType, m, data);
1070 if (r < 0)
1071 {
1072 return r;
1073 }
1074 }
1075 else
1076 {
1077 data.push_back(nlohmann::json());
1078
1079 r = convertDBusToJSON(containedType, m, data.back());
1080 if (r < 0)
1081 {
1082 return r;
1083 }
1084 }
1085 }
1086
1087 r = sd_bus_message_exit_container(m.get());
1088 if (r < 0)
1089 {
Ed Tanous62598e32023-07-17 17:06:25 -07001090 BMCWEB_LOG_ERROR("sd_bus_message_exit_container failed");
Matt Spinler6df8f992019-01-14 12:47:47 -06001091 return r;
1092 }
1093
1094 return 0;
1095}
1096
Ed Tanous23a21a12020-07-25 04:45:05 +00001097inline int readStructFromMessage(const std::string& typeCode,
Patrick Williams59d494e2022-07-22 19:26:55 -05001098 sdbusplus::message_t& m, nlohmann::json& data)
Matt Spinler75c6c672019-01-14 13:01:46 -06001099{
1100 if (typeCode.size() < 3)
1101 {
Ed Tanous62598e32023-07-17 17:06:25 -07001102 BMCWEB_LOG_ERROR("Type code {} too small for a struct", typeCode);
Matt Spinler75c6c672019-01-14 13:01:46 -06001103 return -1;
1104 }
1105
1106 std::string containedTypes = typeCode.substr(1, typeCode.size() - 2);
1107 std::vector<std::string> types = dbusArgSplit(containedTypes);
1108
1109 int r = sd_bus_message_enter_container(m.get(), SD_BUS_TYPE_STRUCT,
1110 containedTypes.c_str());
1111 if (r < 0)
1112 {
Ed Tanous62598e32023-07-17 17:06:25 -07001113 BMCWEB_LOG_ERROR("sd_bus_message_enter_container failed with rc {}", r);
Matt Spinler75c6c672019-01-14 13:01:46 -06001114 return r;
1115 }
1116
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001117 for (const std::string& type : types)
Matt Spinler75c6c672019-01-14 13:01:46 -06001118 {
1119 data.push_back(nlohmann::json());
1120 r = convertDBusToJSON(type, m, data.back());
1121 if (r < 0)
1122 {
1123 return r;
1124 }
1125 }
1126
1127 r = sd_bus_message_exit_container(m.get());
1128 if (r < 0)
1129 {
Ed Tanous62598e32023-07-17 17:06:25 -07001130 BMCWEB_LOG_ERROR("sd_bus_message_exit_container failed");
Matt Spinler75c6c672019-01-14 13:01:46 -06001131 return r;
1132 }
1133 return 0;
1134}
1135
Patrick Williams59d494e2022-07-22 19:26:55 -05001136inline int readVariantFromMessage(sdbusplus::message_t& m, nlohmann::json& data)
Matt Spinler89c19702019-01-14 13:13:00 -06001137{
Ed Tanous543f4402022-01-06 13:12:53 -08001138 const char* containerType = nullptr;
Ed Tanous99131cd2019-10-24 11:12:47 -07001139 int r = sd_bus_message_peek_type(m.get(), nullptr, &containerType);
Matt Spinler89c19702019-01-14 13:13:00 -06001140 if (r < 0)
1141 {
Ed Tanous62598e32023-07-17 17:06:25 -07001142 BMCWEB_LOG_ERROR("sd_bus_message_peek_type failed");
Matt Spinler89c19702019-01-14 13:13:00 -06001143 return r;
1144 }
1145
1146 r = sd_bus_message_enter_container(m.get(), SD_BUS_TYPE_VARIANT,
1147 containerType);
1148 if (r < 0)
1149 {
Ed Tanous62598e32023-07-17 17:06:25 -07001150 BMCWEB_LOG_ERROR("sd_bus_message_enter_container failed with rc {}", r);
Matt Spinler89c19702019-01-14 13:13:00 -06001151 return r;
1152 }
1153
1154 r = convertDBusToJSON(containerType, m, data);
1155 if (r < 0)
1156 {
1157 return r;
1158 }
1159
1160 r = sd_bus_message_exit_container(m.get());
1161 if (r < 0)
1162 {
Ed Tanous62598e32023-07-17 17:06:25 -07001163 BMCWEB_LOG_ERROR("sd_bus_message_enter_container failed");
Matt Spinler89c19702019-01-14 13:13:00 -06001164 return r;
1165 }
1166
1167 return 0;
1168}
1169
Ed Tanous23a21a12020-07-25 04:45:05 +00001170inline int convertDBusToJSON(const std::string& returnType,
Patrick Williams59d494e2022-07-22 19:26:55 -05001171 sdbusplus::message_t& m, nlohmann::json& response)
Matt Spinler16caaee2019-01-15 11:40:34 -06001172{
Matt Spinlerd22a7132019-01-14 12:14:30 -06001173 int r = 0;
1174 const std::vector<std::string> returnTypes = dbusArgSplit(returnType);
1175
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001176 for (const std::string& typeCode : returnTypes)
Matt Spinlerd22a7132019-01-14 12:14:30 -06001177 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001178 nlohmann::json* thisElement = &response;
Matt Spinlerf39420c2019-01-30 12:57:18 -06001179 if (returnTypes.size() > 1)
Matt Spinlerd22a7132019-01-14 12:14:30 -06001180 {
1181 response.push_back(nlohmann::json{});
Matt Spinlerf39420c2019-01-30 12:57:18 -06001182 thisElement = &response.back();
Matt Spinlerd22a7132019-01-14 12:14:30 -06001183 }
1184
Ed Tanousd4d25792020-09-29 15:15:03 -07001185 if (typeCode == "s" || typeCode == "g" || typeCode == "o")
Matt Spinlerd22a7132019-01-14 12:14:30 -06001186 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001187 r = readMessageItem<char*>(typeCode, m, *thisElement);
Matt Spinlerd22a7132019-01-14 12:14:30 -06001188 if (r < 0)
1189 {
1190 return r;
1191 }
1192 }
1193 else if (typeCode == "b")
1194 {
Matt Spinlerf39420c2019-01-30 12:57:18 -06001195 r = readMessageItem<int>(typeCode, m, *thisElement);
Matt Spinlerd22a7132019-01-14 12:14:30 -06001196 if (r < 0)
1197 {
1198 return r;
1199 }
1200
Matt Spinlerf39420c2019-01-30 12:57:18 -06001201 *thisElement = static_cast<bool>(thisElement->get<int>());
Matt Spinlerd22a7132019-01-14 12:14:30 -06001202 }
1203 else if (typeCode == "u")
1204 {
Matt Spinlerf39420c2019-01-30 12:57:18 -06001205 r = readMessageItem<uint32_t>(typeCode, m, *thisElement);
Matt Spinlerd22a7132019-01-14 12:14:30 -06001206 if (r < 0)
1207 {
1208 return r;
1209 }
1210 }
1211 else if (typeCode == "i")
1212 {
Matt Spinlerf39420c2019-01-30 12:57:18 -06001213 r = readMessageItem<int32_t>(typeCode, m, *thisElement);
Matt Spinlerd22a7132019-01-14 12:14:30 -06001214 if (r < 0)
1215 {
1216 return r;
1217 }
1218 }
1219 else if (typeCode == "x")
1220 {
Matt Spinlerf39420c2019-01-30 12:57:18 -06001221 r = readMessageItem<int64_t>(typeCode, m, *thisElement);
Matt Spinlerd22a7132019-01-14 12:14:30 -06001222 if (r < 0)
1223 {
1224 return r;
1225 }
1226 }
1227 else if (typeCode == "t")
1228 {
Matt Spinlerf39420c2019-01-30 12:57:18 -06001229 r = readMessageItem<uint64_t>(typeCode, m, *thisElement);
Matt Spinlerd22a7132019-01-14 12:14:30 -06001230 if (r < 0)
1231 {
1232 return r;
1233 }
1234 }
1235 else if (typeCode == "n")
1236 {
Matt Spinlerf39420c2019-01-30 12:57:18 -06001237 r = readMessageItem<int16_t>(typeCode, m, *thisElement);
Matt Spinlerd22a7132019-01-14 12:14:30 -06001238 if (r < 0)
1239 {
1240 return r;
1241 }
1242 }
1243 else if (typeCode == "q")
1244 {
Matt Spinlerf39420c2019-01-30 12:57:18 -06001245 r = readMessageItem<uint16_t>(typeCode, m, *thisElement);
Matt Spinlerd22a7132019-01-14 12:14:30 -06001246 if (r < 0)
1247 {
1248 return r;
1249 }
1250 }
1251 else if (typeCode == "y")
1252 {
Matt Spinlerf39420c2019-01-30 12:57:18 -06001253 r = readMessageItem<uint8_t>(typeCode, m, *thisElement);
Matt Spinlerd22a7132019-01-14 12:14:30 -06001254 if (r < 0)
1255 {
1256 return r;
1257 }
1258 }
1259 else if (typeCode == "d")
1260 {
Matt Spinlerf39420c2019-01-30 12:57:18 -06001261 r = readMessageItem<double>(typeCode, m, *thisElement);
Matt Spinlerd22a7132019-01-14 12:14:30 -06001262 if (r < 0)
1263 {
1264 return r;
1265 }
1266 }
1267 else if (typeCode == "h")
1268 {
Matt Spinlerf39420c2019-01-30 12:57:18 -06001269 r = readMessageItem<int>(typeCode, m, *thisElement);
Matt Spinlerd22a7132019-01-14 12:14:30 -06001270 if (r < 0)
1271 {
1272 return r;
1273 }
1274 }
Ed Tanous11ba3972022-07-11 09:50:41 -07001275 else if (typeCode.starts_with("a"))
Matt Spinler6df8f992019-01-14 12:47:47 -06001276 {
Matt Spinlerf39420c2019-01-30 12:57:18 -06001277 r = readArrayFromMessage(typeCode, m, *thisElement);
Matt Spinler6df8f992019-01-14 12:47:47 -06001278 if (r < 0)
1279 {
1280 return r;
1281 }
1282 }
Ed Tanous11ba3972022-07-11 09:50:41 -07001283 else if (typeCode.starts_with("(") && typeCode.ends_with(")"))
Matt Spinler75c6c672019-01-14 13:01:46 -06001284 {
Matt Spinlerf39420c2019-01-30 12:57:18 -06001285 r = readStructFromMessage(typeCode, m, *thisElement);
Matt Spinler75c6c672019-01-14 13:01:46 -06001286 if (r < 0)
1287 {
1288 return r;
1289 }
1290 }
Ed Tanous11ba3972022-07-11 09:50:41 -07001291 else if (typeCode.starts_with("v"))
Matt Spinler89c19702019-01-14 13:13:00 -06001292 {
Matt Spinlerf39420c2019-01-30 12:57:18 -06001293 r = readVariantFromMessage(m, *thisElement);
Matt Spinler89c19702019-01-14 13:13:00 -06001294 if (r < 0)
1295 {
1296 return r;
1297 }
1298 }
Matt Spinlerd22a7132019-01-14 12:14:30 -06001299 else
1300 {
Ed Tanous62598e32023-07-17 17:06:25 -07001301 BMCWEB_LOG_ERROR("Invalid D-Bus signature type {}", typeCode);
Matt Spinlerd22a7132019-01-14 12:14:30 -06001302 return -2;
1303 }
1304 }
1305
Matt Spinler16caaee2019-01-15 11:40:34 -06001306 return 0;
1307}
1308
Ed Tanousb5a76932020-09-29 16:16:58 -07001309inline void handleMethodResponse(
1310 const std::shared_ptr<InProgressActionData>& transaction,
Patrick Williams59d494e2022-07-22 19:26:55 -05001311 sdbusplus::message_t& m, const std::string& returnType)
Matt Spinler16caaee2019-01-15 11:40:34 -06001312{
Matt Spinler39a4e392019-01-15 11:53:13 -06001313 nlohmann::json data;
1314
1315 int r = convertDBusToJSON(returnType, m, data);
1316 if (r < 0)
1317 {
1318 transaction->outputFailed = true;
1319 return;
1320 }
1321
1322 if (data.is_null())
1323 {
1324 return;
1325 }
1326
1327 if (transaction->methodResponse.is_null())
1328 {
1329 transaction->methodResponse = std::move(data);
1330 return;
1331 }
1332
1333 // If they're both dictionaries or arrays, merge into one.
1334 // Otherwise, make the results an array with every result
1335 // an entry. Could also just fail in that case, but it
1336 // seems better to get the data back somehow.
1337
1338 if (transaction->methodResponse.is_object() && data.is_object())
1339 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001340 for (const auto& obj : data.items())
Matt Spinler39a4e392019-01-15 11:53:13 -06001341 {
1342 // Note: Will overwrite the data for a duplicate key
1343 transaction->methodResponse.emplace(obj.key(),
1344 std::move(obj.value()));
1345 }
1346 return;
1347 }
1348
1349 if (transaction->methodResponse.is_array() && data.is_array())
1350 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001351 for (auto& obj : data)
Matt Spinler39a4e392019-01-15 11:53:13 -06001352 {
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001353 transaction->methodResponse.emplace_back(std::move(obj));
Matt Spinler39a4e392019-01-15 11:53:13 -06001354 }
1355 return;
1356 }
1357
1358 if (!transaction->convertedToArray)
1359 {
1360 // They are different types. May as well turn them into an array
1361 nlohmann::json j = std::move(transaction->methodResponse);
1362 transaction->methodResponse = nlohmann::json::array();
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001363 transaction->methodResponse.emplace_back(std::move(j));
1364 transaction->methodResponse.emplace_back(std::move(data));
Matt Spinler39a4e392019-01-15 11:53:13 -06001365 transaction->convertedToArray = true;
1366 }
1367 else
1368 {
Patrick Williamsb2ba3072023-05-12 10:27:39 -05001369 transaction->methodResponse.emplace_back(std::move(data));
Matt Spinler39a4e392019-01-15 11:53:13 -06001370 }
Matt Spinler16caaee2019-01-15 11:40:34 -06001371}
1372
Ed Tanousb5a76932020-09-29 16:16:58 -07001373inline void findActionOnInterface(
1374 const std::shared_ptr<InProgressActionData>& transaction,
1375 const std::string& connectionName)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001376{
Ed Tanous62598e32023-07-17 17:06:25 -07001377 BMCWEB_LOG_DEBUG("findActionOnInterface for connection {}", connectionName);
Ed Tanous1abe55e2018-09-05 08:30:59 -07001378 crow::connections::systemBus->async_method_call(
1379 [transaction, connectionName{std::string(connectionName)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001380 const boost::system::error_code& ec,
Ed Tanous81ce6092020-12-17 16:54:55 +00001381 const std::string& introspectXml) {
Ed Tanous62598e32023-07-17 17:06:25 -07001382 BMCWEB_LOG_DEBUG("got xml:\n {}", introspectXml);
Ed Tanous002d39b2022-05-31 08:59:27 -07001383 if (ec)
1384 {
Ed Tanous62598e32023-07-17 17:06:25 -07001385 BMCWEB_LOG_ERROR(
1386 "Introspect call failed with error: {} on process: {}",
1387 ec.message(), connectionName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001388 return;
1389 }
1390 tinyxml2::XMLDocument doc;
Matt Spinler318bd892019-01-15 09:59:20 -06001391
Ed Tanous002d39b2022-05-31 08:59:27 -07001392 doc.Parse(introspectXml.data(), introspectXml.size());
1393 tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
1394 if (pRoot == nullptr)
1395 {
Ed Tanous62598e32023-07-17 17:06:25 -07001396 BMCWEB_LOG_ERROR("XML document failed to parse {}", connectionName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001397 return;
1398 }
1399 tinyxml2::XMLElement* interfaceNode =
1400 pRoot->FirstChildElement("interface");
1401 while (interfaceNode != nullptr)
1402 {
1403 const char* thisInterfaceName = interfaceNode->Attribute("name");
1404 if (thisInterfaceName != nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001405 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001406 if (!transaction->interfaceName.empty() &&
1407 (transaction->interfaceName != thisInterfaceName))
Ed Tanous1abe55e2018-09-05 08:30:59 -07001408 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001409 interfaceNode =
1410 interfaceNode->NextSiblingElement("interface");
1411 continue;
Ed Tanous1abe55e2018-09-05 08:30:59 -07001412 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001413
1414 tinyxml2::XMLElement* methodNode =
1415 interfaceNode->FirstChildElement("method");
1416 while (methodNode != nullptr)
1417 {
1418 const char* thisMethodName = methodNode->Attribute("name");
Ed Tanous62598e32023-07-17 17:06:25 -07001419 BMCWEB_LOG_DEBUG("Found method: {}", thisMethodName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001420 if (thisMethodName != nullptr &&
1421 thisMethodName == transaction->methodName)
1422 {
Ed Tanous62598e32023-07-17 17:06:25 -07001423 BMCWEB_LOG_DEBUG(
1424 "Found method named {} on interface {}",
1425 thisMethodName, thisInterfaceName);
Patrick Williams59d494e2022-07-22 19:26:55 -05001426 sdbusplus::message_t m =
Ed Tanous002d39b2022-05-31 08:59:27 -07001427 crow::connections::systemBus->new_method_call(
1428 connectionName.c_str(),
1429 transaction->path.c_str(), thisInterfaceName,
1430 transaction->methodName.c_str());
1431
1432 tinyxml2::XMLElement* argumentNode =
1433 methodNode->FirstChildElement("arg");
1434
1435 std::string returnType;
1436
1437 // Find the output type
1438 while (argumentNode != nullptr)
1439 {
1440 const char* argDirection =
1441 argumentNode->Attribute("direction");
1442 const char* argType =
1443 argumentNode->Attribute("type");
1444 if (argDirection != nullptr && argType != nullptr &&
1445 std::string(argDirection) == "out")
1446 {
1447 returnType = argType;
1448 break;
1449 }
1450 argumentNode =
1451 argumentNode->NextSiblingElement("arg");
1452 }
1453
Nan Zhoub2ec0ce2022-06-02 23:57:38 +00001454 auto argIt = transaction->arguments.begin();
Ed Tanous002d39b2022-05-31 08:59:27 -07001455
1456 argumentNode = methodNode->FirstChildElement("arg");
1457
1458 while (argumentNode != nullptr)
1459 {
1460 const char* argDirection =
1461 argumentNode->Attribute("direction");
1462 const char* argType =
1463 argumentNode->Attribute("type");
1464 if (argDirection != nullptr && argType != nullptr &&
1465 std::string(argDirection) == "in")
1466 {
1467 if (argIt == transaction->arguments.end())
1468 {
1469 transaction->setErrorStatus(
1470 "Invalid method args");
1471 return;
1472 }
1473 if (convertJsonToDbus(m.get(),
1474 std::string(argType),
1475 *argIt) < 0)
1476 {
1477 transaction->setErrorStatus(
1478 "Invalid method arg type");
1479 return;
1480 }
1481
1482 argIt++;
1483 }
1484 argumentNode =
1485 argumentNode->NextSiblingElement("arg");
1486 }
1487
1488 crow::connections::systemBus->async_send(
1489 m,
1490 [transaction,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001491 returnType](const boost::system::error_code& ec2,
Patrick Williams59d494e2022-07-22 19:26:55 -05001492 sdbusplus::message_t& m2) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001493 if (ec2)
1494 {
1495 transaction->methodFailed = true;
1496 const sd_bus_error* e = m2.get_error();
1497
1498 if (e != nullptr)
1499 {
1500 setErrorResponse(
Lei YU28dd5ca2023-03-17 13:17:05 +08001501 transaction->asyncResp->res,
Ed Tanous002d39b2022-05-31 08:59:27 -07001502 boost::beast::http::status::bad_request,
1503 e->name, e->message);
1504 }
1505 else
1506 {
1507 setErrorResponse(
Lei YU28dd5ca2023-03-17 13:17:05 +08001508 transaction->asyncResp->res,
Ed Tanous002d39b2022-05-31 08:59:27 -07001509 boost::beast::http::status::bad_request,
1510 "Method call failed", methodFailedMsg);
1511 }
1512 return;
1513 }
1514 transaction->methodPassed = true;
1515
1516 handleMethodResponse(transaction, m2, returnType);
1517 });
1518 break;
1519 }
1520 methodNode = methodNode->NextSiblingElement("method");
1521 }
Ed Tanous1abe55e2018-09-05 08:30:59 -07001522 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001523 interfaceNode = interfaceNode->NextSiblingElement("interface");
1524 }
Ed Tanous1abe55e2018-09-05 08:30:59 -07001525 },
1526 connectionName, transaction->path,
1527 "org.freedesktop.DBus.Introspectable", "Introspect");
Ed Tanousd4bb9bb2018-05-16 13:36:42 -07001528}
1529
zhanghch058d1b46d2021-04-01 11:18:24 +08001530inline void handleAction(const crow::Request& req,
1531 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous23a21a12020-07-25 04:45:05 +00001532 const std::string& objectPath,
1533 const std::string& methodName)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001534{
Ed Tanous62598e32023-07-17 17:06:25 -07001535 BMCWEB_LOG_DEBUG("handleAction on path: {} and method {}", objectPath,
1536 methodName);
Ed Tanous1aa0c2b2022-02-08 12:24:30 +01001537 nlohmann::json requestDbusData;
Ed Tanousd4bb9bb2018-05-16 13:36:42 -07001538
Ed Tanous1aa0c2b2022-02-08 12:24:30 +01001539 JsonParseResult ret = parseRequestAsJson(req, requestDbusData);
1540 if (ret == JsonParseResult::BadContentType)
1541 {
1542 setErrorResponse(asyncResp->res,
1543 boost::beast::http::status::unsupported_media_type,
1544 invalidContentType, unsupportedMediaMsg);
1545 return;
1546 }
1547 if (ret != JsonParseResult::Success)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001548 {
zhanghch058d1b46d2021-04-01 11:18:24 +08001549 setErrorResponse(asyncResp->res,
1550 boost::beast::http::status::bad_request, noJsonDesc,
1551 badReqMsg);
Ed Tanous1abe55e2018-09-05 08:30:59 -07001552 return;
1553 }
Ed Tanouse3cb5a32018-08-08 14:16:49 -07001554 nlohmann::json::iterator data = requestDbusData.find("data");
1555 if (data == requestDbusData.end())
1556 {
zhanghch058d1b46d2021-04-01 11:18:24 +08001557 setErrorResponse(asyncResp->res,
1558 boost::beast::http::status::bad_request, noJsonDesc,
1559 badReqMsg);
Ed Tanouse3cb5a32018-08-08 14:16:49 -07001560 return;
1561 }
1562
1563 if (!data->is_array())
Ed Tanous1abe55e2018-09-05 08:30:59 -07001564 {
zhanghch058d1b46d2021-04-01 11:18:24 +08001565 setErrorResponse(asyncResp->res,
1566 boost::beast::http::status::bad_request, noJsonDesc,
1567 badReqMsg);
Ed Tanous1abe55e2018-09-05 08:30:59 -07001568 return;
1569 }
Lei YU28dd5ca2023-03-17 13:17:05 +08001570 auto transaction = std::make_shared<InProgressActionData>(asyncResp);
Ed Tanous1abe55e2018-09-05 08:30:59 -07001571
1572 transaction->path = objectPath;
1573 transaction->methodName = methodName;
Ed Tanouse3cb5a32018-08-08 14:16:49 -07001574 transaction->arguments = std::move(*data);
George Liu2b731192023-01-11 16:27:13 +08001575 dbus::utility::getDbusObject(
1576 objectPath, {},
Ed Tanous1abe55e2018-09-05 08:30:59 -07001577 [transaction](
George Liu2b731192023-01-11 16:27:13 +08001578 const boost::system::error_code& ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001579 const std::vector<std::pair<std::string, std::vector<std::string>>>&
1580 interfaceNames) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001581 if (ec || interfaceNames.empty())
1582 {
Ed Tanous62598e32023-07-17 17:06:25 -07001583 BMCWEB_LOG_ERROR("Can't find object");
Lei YU28dd5ca2023-03-17 13:17:05 +08001584 setErrorResponse(transaction->asyncResp->res,
Ed Tanous002d39b2022-05-31 08:59:27 -07001585 boost::beast::http::status::not_found,
1586 notFoundDesc, notFoundMsg);
1587 return;
1588 }
Ed Tanous1abe55e2018-09-05 08:30:59 -07001589
Ed Tanous62598e32023-07-17 17:06:25 -07001590 BMCWEB_LOG_DEBUG("GetObject returned {} object(s)",
1591 interfaceNames.size());
Ed Tanous1abe55e2018-09-05 08:30:59 -07001592
Ed Tanous002d39b2022-05-31 08:59:27 -07001593 for (const std::pair<std::string, std::vector<std::string>>& object :
1594 interfaceNames)
1595 {
1596 findActionOnInterface(transaction, object.first);
1597 }
George Liu2b731192023-01-11 16:27:13 +08001598 });
Ed Tanousd4bb9bb2018-05-16 13:36:42 -07001599}
1600
zhanghch058d1b46d2021-04-01 11:18:24 +08001601inline void handleDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1602 const std::string& objectPath)
Matt Spinlerde818812018-12-11 16:39:20 -06001603{
Ed Tanous62598e32023-07-17 17:06:25 -07001604 BMCWEB_LOG_DEBUG("handleDelete on path: {}", objectPath);
Matt Spinlerde818812018-12-11 16:39:20 -06001605
George Liu2b731192023-01-11 16:27:13 +08001606 dbus::utility::getDbusObject(
1607 objectPath, {},
zhanghch058d1b46d2021-04-01 11:18:24 +08001608 [asyncResp, objectPath](
George Liu2b731192023-01-11 16:27:13 +08001609 const boost::system::error_code& ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001610 const std::vector<std::pair<std::string, std::vector<std::string>>>&
1611 interfaceNames) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001612 if (ec || interfaceNames.empty())
1613 {
Ed Tanous62598e32023-07-17 17:06:25 -07001614 BMCWEB_LOG_ERROR("Can't find object");
Ed Tanous002d39b2022-05-31 08:59:27 -07001615 setErrorResponse(asyncResp->res,
1616 boost::beast::http::status::method_not_allowed,
1617 methodNotAllowedDesc, methodNotAllowedMsg);
1618 return;
1619 }
Matt Spinlerde818812018-12-11 16:39:20 -06001620
Lei YU28dd5ca2023-03-17 13:17:05 +08001621 auto transaction = std::make_shared<InProgressActionData>(asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07001622 transaction->path = objectPath;
1623 transaction->methodName = "Delete";
1624 transaction->interfaceName = "xyz.openbmc_project.Object.Delete";
Matt Spinlerde818812018-12-11 16:39:20 -06001625
Ed Tanous002d39b2022-05-31 08:59:27 -07001626 for (const std::pair<std::string, std::vector<std::string>>& object :
1627 interfaceNames)
1628 {
1629 findActionOnInterface(transaction, object.first);
1630 }
George Liu2b731192023-01-11 16:27:13 +08001631 });
Matt Spinlerde818812018-12-11 16:39:20 -06001632}
1633
zhanghch058d1b46d2021-04-01 11:18:24 +08001634inline void handleList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1635 const std::string& objectPath, int32_t depth = 0)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001636{
George Liu7a1dbc42022-12-07 16:03:22 +08001637 dbus::utility::getSubTreePaths(
1638 objectPath, depth, {},
Ed Tanousb9d36b42022-02-26 21:42:46 -08001639 [asyncResp](
George Liu7a1dbc42022-12-07 16:03:22 +08001640 const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001641 const dbus::utility::MapperGetSubTreePathsResponse& objectPaths) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001642 if (ec)
1643 {
1644 setErrorResponse(asyncResp->res,
1645 boost::beast::http::status::not_found,
1646 notFoundDesc, notFoundMsg);
1647 }
1648 else
1649 {
1650 asyncResp->res.jsonValue["status"] = "ok";
1651 asyncResp->res.jsonValue["message"] = "200 OK";
1652 asyncResp->res.jsonValue["data"] = objectPaths;
1653 }
George Liu7a1dbc42022-12-07 16:03:22 +08001654 });
Ed Tanous1abe55e2018-09-05 08:30:59 -07001655}
Ed Tanousd4bb9bb2018-05-16 13:36:42 -07001656
zhanghch058d1b46d2021-04-01 11:18:24 +08001657inline void handleEnumerate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1658 const std::string& objectPath)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001659{
Ed Tanous62598e32023-07-17 17:06:25 -07001660 BMCWEB_LOG_DEBUG("Doing enumerate on {}", objectPath);
Ed Tanous049a0512018-11-01 13:58:42 -07001661
Ed Tanous14766872022-03-15 10:44:42 -07001662 asyncResp->res.jsonValue["message"] = "200 OK";
1663 asyncResp->res.jsonValue["status"] = "ok";
1664 asyncResp->res.jsonValue["data"] = nlohmann::json::object();
Ed Tanous049a0512018-11-01 13:58:42 -07001665
George Liue99073f2022-12-09 11:06:16 +08001666 dbus::utility::getSubTree(
1667 objectPath, 0, {},
Ed Tanousb9d36b42022-02-26 21:42:46 -08001668 [objectPath, asyncResp](
George Liue99073f2022-12-09 11:06:16 +08001669 const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001670 const dbus::utility::MapperGetSubTreeResponse& objectNames) {
Patrick Williams89492a12023-05-10 07:51:34 -05001671 auto transaction = std::make_shared<InProgressEnumerateData>(objectPath,
1672 asyncResp);
Matt Spinler3ae4ba72018-12-05 14:01:22 -06001673
Ed Tanous002d39b2022-05-31 08:59:27 -07001674 transaction->subtree =
1675 std::make_shared<dbus::utility::MapperGetSubTreeResponse>(
1676 objectNames);
Matt Spinler3ae4ba72018-12-05 14:01:22 -06001677
Ed Tanous002d39b2022-05-31 08:59:27 -07001678 if (ec)
1679 {
Ed Tanous62598e32023-07-17 17:06:25 -07001680 BMCWEB_LOG_ERROR("GetSubTree failed on {}",
1681 transaction->objectPath);
Ed Tanous002d39b2022-05-31 08:59:27 -07001682 setErrorResponse(transaction->asyncResp->res,
1683 boost::beast::http::status::not_found,
1684 notFoundDesc, notFoundMsg);
1685 return;
1686 }
Ed Tanous64530012018-02-06 17:08:16 -08001687
Ed Tanous002d39b2022-05-31 08:59:27 -07001688 // Add the data for the path passed in to the results
1689 // as if GetSubTree returned it, and continue on enumerating
1690 getObjectAndEnumerate(transaction);
George Liue99073f2022-12-09 11:06:16 +08001691 });
Ed Tanous64530012018-02-06 17:08:16 -08001692}
Ed Tanous911ac312017-08-15 09:37:42 -07001693
zhanghch058d1b46d2021-04-01 11:18:24 +08001694inline void handleGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1695 std::string& objectPath, std::string& destProperty)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001696{
Ed Tanous62598e32023-07-17 17:06:25 -07001697 BMCWEB_LOG_DEBUG("handleGet: {} prop:{}", objectPath, destProperty);
Ed Tanouse3cb5a32018-08-08 14:16:49 -07001698 std::shared_ptr<std::string> propertyName =
Ed Tanous1abe55e2018-09-05 08:30:59 -07001699 std::make_shared<std::string>(std::move(destProperty));
Ed Tanous75db20e2018-07-27 13:44:44 -07001700
Ed Tanous1abe55e2018-09-05 08:30:59 -07001701 std::shared_ptr<std::string> path =
1702 std::make_shared<std::string>(std::move(objectPath));
Ed Tanous75db20e2018-07-27 13:44:44 -07001703
George Liu2b731192023-01-11 16:27:13 +08001704 dbus::utility::getDbusObject(
1705 *path, {},
Ed Tanousb9d36b42022-02-26 21:42:46 -08001706 [asyncResp, path,
George Liu2b731192023-01-11 16:27:13 +08001707 propertyName](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001708 const dbus::utility::MapperGetObject& objectNames) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001709 if (ec || objectNames.empty())
1710 {
1711 setErrorResponse(asyncResp->res,
1712 boost::beast::http::status::not_found,
1713 notFoundDesc, notFoundMsg);
1714 return;
1715 }
1716 std::shared_ptr<nlohmann::json> response =
1717 std::make_shared<nlohmann::json>(nlohmann::json::object());
1718 // The mapper should never give us an empty interface names
1719 // list, but check anyway
1720 for (const std::pair<std::string, std::vector<std::string>>&
1721 connection : objectNames)
1722 {
1723 const std::vector<std::string>& interfaceNames = connection.second;
1724
1725 if (interfaceNames.empty())
Ed Tanous1abe55e2018-09-05 08:30:59 -07001726 {
zhanghch058d1b46d2021-04-01 11:18:24 +08001727 setErrorResponse(asyncResp->res,
1728 boost::beast::http::status::not_found,
Matt Spinlerdc2f9f12018-12-06 13:53:53 -06001729 notFoundDesc, notFoundMsg);
Ed Tanous1abe55e2018-09-05 08:30:59 -07001730 return;
1731 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001732
1733 for (const std::string& interface : interfaceNames)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001734 {
Patrick Williams59d494e2022-07-22 19:26:55 -05001735 sdbusplus::message_t m =
Ed Tanous002d39b2022-05-31 08:59:27 -07001736 crow::connections::systemBus->new_method_call(
1737 connection.first.c_str(), path->c_str(),
1738 "org.freedesktop.DBus.Properties", "GetAll");
1739 m.append(interface);
1740 crow::connections::systemBus->async_send(
1741 m, [asyncResp, response,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001742 propertyName](const boost::system::error_code& ec2,
Patrick Williams59d494e2022-07-22 19:26:55 -05001743 sdbusplus::message_t& msg) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001744 if (ec2)
1745 {
Ed Tanous62598e32023-07-17 17:06:25 -07001746 BMCWEB_LOG_ERROR("Bad dbus request error: {}", ec2);
Ed Tanous002d39b2022-05-31 08:59:27 -07001747 }
1748 else
1749 {
1750 nlohmann::json properties;
1751 int r = convertDBusToJSON("a{sv}", msg, properties);
1752 if (r < 0)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001753 {
Ed Tanous62598e32023-07-17 17:06:25 -07001754 BMCWEB_LOG_ERROR("convertDBusToJSON failed");
Ed Tanous1abe55e2018-09-05 08:30:59 -07001755 }
1756 else
1757 {
Patrick Williams62bafc02022-09-08 17:35:35 -05001758 for (const auto& prop : properties.items())
Ed Tanous1abe55e2018-09-05 08:30:59 -07001759 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001760 // if property name is empty, or
1761 // matches our search query, add it
1762 // to the response json
Ed Tanous1abe55e2018-09-05 08:30:59 -07001763
Ed Tanous002d39b2022-05-31 08:59:27 -07001764 if (propertyName->empty())
1765 {
1766 (*response)[prop.key()] =
1767 std::move(prop.value());
1768 }
1769 else if (prop.key() == *propertyName)
1770 {
1771 *response = std::move(prop.value());
Ed Tanous1abe55e2018-09-05 08:30:59 -07001772 }
1773 }
1774 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001775 }
1776 if (response.use_count() == 1)
1777 {
1778 if (!propertyName->empty() && response->empty())
Ed Tanous1abe55e2018-09-05 08:30:59 -07001779 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001780 setErrorResponse(
1781 asyncResp->res,
1782 boost::beast::http::status::not_found,
1783 propNotFoundDesc, notFoundMsg);
Ed Tanous1abe55e2018-09-05 08:30:59 -07001784 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001785 else
1786 {
1787 asyncResp->res.jsonValue["status"] = "ok";
1788 asyncResp->res.jsonValue["message"] = "200 OK";
1789 asyncResp->res.jsonValue["data"] = *response;
1790 }
1791 }
1792 });
Ed Tanous1abe55e2018-09-05 08:30:59 -07001793 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001794 }
George Liu2b731192023-01-11 16:27:13 +08001795 });
Ed Tanousd4bb9bb2018-05-16 13:36:42 -07001796}
1797
Ed Tanous1abe55e2018-09-05 08:30:59 -07001798struct AsyncPutRequest
1799{
Ed Tanous4e23a442022-06-06 09:57:26 -07001800 explicit AsyncPutRequest(const std::shared_ptr<bmcweb::AsyncResp>& resIn) :
zhanghch058d1b46d2021-04-01 11:18:24 +08001801 asyncResp(resIn)
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001802 {}
Ed Tanous1abe55e2018-09-05 08:30:59 -07001803 ~AsyncPutRequest()
1804 {
zhanghch058d1b46d2021-04-01 11:18:24 +08001805 if (asyncResp->res.jsonValue.empty())
Ed Tanous1abe55e2018-09-05 08:30:59 -07001806 {
zhanghch058d1b46d2021-04-01 11:18:24 +08001807 setErrorResponse(asyncResp->res,
1808 boost::beast::http::status::forbidden,
Matt Spinlerfbc19ea2018-12-11 14:03:42 -06001809 forbiddenMsg, forbiddenPropDesc);
Ed Tanous1abe55e2018-09-05 08:30:59 -07001810 }
Ed Tanousd4bb9bb2018-05-16 13:36:42 -07001811 }
1812
Ed Tanousecd6a3a2022-01-07 09:18:40 -08001813 AsyncPutRequest(const AsyncPutRequest&) = delete;
1814 AsyncPutRequest(AsyncPutRequest&&) = delete;
1815 AsyncPutRequest& operator=(const AsyncPutRequest&) = delete;
1816 AsyncPutRequest& operator=(AsyncPutRequest&&) = delete;
1817
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001818 void setErrorStatus(const std::string& desc)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001819 {
zhanghch058d1b46d2021-04-01 11:18:24 +08001820 setErrorResponse(asyncResp->res,
1821 boost::beast::http::status::internal_server_error,
Matt Spinlerfbc19ea2018-12-11 14:03:42 -06001822 desc, badReqMsg);
Ed Tanousd4bb9bb2018-05-16 13:36:42 -07001823 }
1824
zhanghch058d1b46d2021-04-01 11:18:24 +08001825 const std::shared_ptr<bmcweb::AsyncResp> asyncResp;
Ed Tanous1abe55e2018-09-05 08:30:59 -07001826 std::string objectPath;
1827 std::string propertyName;
1828 nlohmann::json propertyValue;
Ed Tanousd4bb9bb2018-05-16 13:36:42 -07001829};
1830
zhanghch058d1b46d2021-04-01 11:18:24 +08001831inline void handlePut(const crow::Request& req,
1832 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous23a21a12020-07-25 04:45:05 +00001833 const std::string& objectPath,
1834 const std::string& destProperty)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001835{
Matt Spinlerfbc19ea2018-12-11 14:03:42 -06001836 if (destProperty.empty())
1837 {
zhanghch058d1b46d2021-04-01 11:18:24 +08001838 setErrorResponse(asyncResp->res, boost::beast::http::status::forbidden,
Matt Spinlerfbc19ea2018-12-11 14:03:42 -06001839 forbiddenResDesc, forbiddenMsg);
Matt Spinlerfbc19ea2018-12-11 14:03:42 -06001840 return;
1841 }
Ed Tanous1aa0c2b2022-02-08 12:24:30 +01001842 nlohmann::json requestDbusData;
Matt Spinlerfbc19ea2018-12-11 14:03:42 -06001843
Ed Tanous1aa0c2b2022-02-08 12:24:30 +01001844 JsonParseResult ret = parseRequestAsJson(req, requestDbusData);
1845 if (ret == JsonParseResult::BadContentType)
1846 {
1847 setErrorResponse(asyncResp->res,
1848 boost::beast::http::status::unsupported_media_type,
1849 invalidContentType, unsupportedMediaMsg);
1850 return;
1851 }
Ed Tanousd4bb9bb2018-05-16 13:36:42 -07001852
Ed Tanous1aa0c2b2022-02-08 12:24:30 +01001853 if (ret != JsonParseResult::Success)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001854 {
zhanghch058d1b46d2021-04-01 11:18:24 +08001855 setErrorResponse(asyncResp->res,
1856 boost::beast::http::status::bad_request, noJsonDesc,
1857 badReqMsg);
Ed Tanousd4bb9bb2018-05-16 13:36:42 -07001858 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -07001859 }
Ed Tanousd4bb9bb2018-05-16 13:36:42 -07001860
Nan Zhoub2ec0ce2022-06-02 23:57:38 +00001861 auto propertyIt = requestDbusData.find("data");
Ed Tanous1abe55e2018-09-05 08:30:59 -07001862 if (propertyIt == requestDbusData.end())
1863 {
zhanghch058d1b46d2021-04-01 11:18:24 +08001864 setErrorResponse(asyncResp->res,
1865 boost::beast::http::status::bad_request, noJsonDesc,
1866 badReqMsg);
Ed Tanous1abe55e2018-09-05 08:30:59 -07001867 return;
1868 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001869 const nlohmann::json& propertySetValue = *propertyIt;
zhanghch058d1b46d2021-04-01 11:18:24 +08001870 auto transaction = std::make_shared<AsyncPutRequest>(asyncResp);
Ed Tanous1abe55e2018-09-05 08:30:59 -07001871 transaction->objectPath = objectPath;
1872 transaction->propertyName = destProperty;
1873 transaction->propertyValue = propertySetValue;
Ed Tanous911ac312017-08-15 09:37:42 -07001874
George Liu2b731192023-01-11 16:27:13 +08001875 dbus::utility::getDbusObject(
1876 transaction->objectPath, {},
1877 [transaction](const boost::system::error_code& ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001878 const dbus::utility::MapperGetObject& objectNames) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001879 if (!ec2 && objectNames.empty())
1880 {
1881 setErrorResponse(transaction->asyncResp->res,
1882 boost::beast::http::status::not_found,
1883 propNotFoundDesc, notFoundMsg);
1884 return;
1885 }
Ed Tanous911ac312017-08-15 09:37:42 -07001886
Ed Tanous002d39b2022-05-31 08:59:27 -07001887 for (const std::pair<std::string, std::vector<std::string>>&
1888 connection : objectNames)
1889 {
1890 const std::string& connectionName = connection.first;
Ed Tanous911ac312017-08-15 09:37:42 -07001891
Ed Tanous002d39b2022-05-31 08:59:27 -07001892 crow::connections::systemBus->async_method_call(
1893 [connectionName{std::string(connectionName)},
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001894 transaction](const boost::system::error_code& ec3,
Ed Tanous002d39b2022-05-31 08:59:27 -07001895 const std::string& introspectXml) {
1896 if (ec3)
1897 {
Ed Tanous62598e32023-07-17 17:06:25 -07001898 BMCWEB_LOG_ERROR(
1899 "Introspect call failed with error: {} on process: {}",
1900 ec3.message(), connectionName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001901 transaction->setErrorStatus("Unexpected Error");
1902 return;
1903 }
1904 tinyxml2::XMLDocument doc;
Ed Tanous911ac312017-08-15 09:37:42 -07001905
Ed Tanous002d39b2022-05-31 08:59:27 -07001906 doc.Parse(introspectXml.c_str());
1907 tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
1908 if (pRoot == nullptr)
1909 {
Ed Tanous62598e32023-07-17 17:06:25 -07001910 BMCWEB_LOG_ERROR("XML document failed to parse: {}",
1911 introspectXml);
Ed Tanous002d39b2022-05-31 08:59:27 -07001912 transaction->setErrorStatus("Unexpected Error");
1913 return;
1914 }
1915 tinyxml2::XMLElement* ifaceNode =
1916 pRoot->FirstChildElement("interface");
1917 while (ifaceNode != nullptr)
1918 {
1919 const char* interfaceName = ifaceNode->Attribute("name");
Ed Tanous62598e32023-07-17 17:06:25 -07001920 BMCWEB_LOG_DEBUG("found interface {}", interfaceName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001921 tinyxml2::XMLElement* propNode =
1922 ifaceNode->FirstChildElement("property");
1923 while (propNode != nullptr)
1924 {
1925 const char* propertyName = propNode->Attribute("name");
Ed Tanous62598e32023-07-17 17:06:25 -07001926 BMCWEB_LOG_DEBUG("Found property {}", propertyName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001927 if (propertyName == transaction->propertyName)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001928 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001929 const char* argType = propNode->Attribute("type");
1930 if (argType != nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001931 {
Patrick Williams59d494e2022-07-22 19:26:55 -05001932 sdbusplus::message_t m =
Ed Tanous002d39b2022-05-31 08:59:27 -07001933 crow::connections::systemBus
1934 ->new_method_call(
1935 connectionName.c_str(),
1936 transaction->objectPath.c_str(),
1937 "org.freedesktop.DBus."
1938 "Properties",
1939 "Set");
1940 m.append(interfaceName,
1941 transaction->propertyName);
1942 int r = sd_bus_message_open_container(
1943 m.get(), SD_BUS_TYPE_VARIANT, argType);
1944 if (r < 0)
Ed Tanous1abe55e2018-09-05 08:30:59 -07001945 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001946 transaction->setErrorStatus(
1947 "Unexpected Error");
1948 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -07001949 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001950 r = convertJsonToDbus(
1951 m.get(), argType,
1952 transaction->propertyValue);
1953 if (r < 0)
1954 {
1955 if (r == -ERANGE)
1956 {
1957 transaction->setErrorStatus(
1958 "Provided property value "
1959 "is out of range for the "
1960 "property type");
1961 }
1962 else
1963 {
1964 transaction->setErrorStatus(
1965 "Invalid arg type");
1966 }
1967 return;
1968 }
1969 r = sd_bus_message_close_container(m.get());
1970 if (r < 0)
1971 {
1972 transaction->setErrorStatus(
1973 "Unexpected Error");
1974 return;
1975 }
1976 crow::connections::systemBus->async_send(
1977 m,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001978 [transaction](
1979 const boost::system::error_code& ec,
1980 sdbusplus::message_t& m2) {
Ed Tanous62598e32023-07-17 17:06:25 -07001981 BMCWEB_LOG_DEBUG("sent");
Ed Tanous002d39b2022-05-31 08:59:27 -07001982 if (ec)
1983 {
1984 const sd_bus_error* e = m2.get_error();
1985 setErrorResponse(
1986 transaction->asyncResp->res,
1987 boost::beast::http::status::
1988 forbidden,
1989 (e) != nullptr
1990 ? e->name
1991 : ec.category().name(),
1992 (e) != nullptr ? e->message
1993 : ec.message());
1994 }
1995 else
1996 {
1997 transaction->asyncResp->res
1998 .jsonValue["status"] = "ok";
1999 transaction->asyncResp->res
2000 .jsonValue["message"] = "200 OK";
2001 transaction->asyncResp->res
2002 .jsonValue["data"] = nullptr;
2003 }
2004 });
Ed Tanous1abe55e2018-09-05 08:30:59 -07002005 }
Ed Tanous1abe55e2018-09-05 08:30:59 -07002006 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002007 propNode = propNode->NextSiblingElement("property");
2008 }
2009 ifaceNode = ifaceNode->NextSiblingElement("interface");
2010 }
2011 },
2012 connectionName, transaction->objectPath,
2013 "org.freedesktop.DBus.Introspectable", "Introspect");
2014 }
George Liu2b731192023-01-11 16:27:13 +08002015 });
Ed Tanousd4bb9bb2018-05-16 13:36:42 -07002016}
Ed Tanous1abe55e2018-09-05 08:30:59 -07002017
zhanghch058d1b46d2021-04-01 11:18:24 +08002018inline void handleDBusUrl(const crow::Request& req,
2019 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002020 std::string& objectPath)
Ed Tanous049a0512018-11-01 13:58:42 -07002021{
Ed Tanous049a0512018-11-01 13:58:42 -07002022 // If accessing a single attribute, fill in and update objectPath,
2023 // otherwise leave destProperty blank
Ed Tanouse05aec52022-01-25 10:28:56 -08002024 std::string destProperty;
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002025 const char* attrSeperator = "/attr/";
Ed Tanous049a0512018-11-01 13:58:42 -07002026 size_t attrPosition = objectPath.find(attrSeperator);
Ed Tanous71d5d8d2022-01-25 11:04:33 -08002027 if (attrPosition != std::string::npos)
Ed Tanous049a0512018-11-01 13:58:42 -07002028 {
2029 destProperty = objectPath.substr(attrPosition + strlen(attrSeperator),
2030 objectPath.length());
Ed Tanous7f57f192022-12-20 09:53:40 -08002031 objectPath.resize(attrPosition);
Ed Tanous049a0512018-11-01 13:58:42 -07002032 }
2033
Ed Tanousb41187f2019-10-24 16:30:02 -07002034 if (req.method() == boost::beast::http::verb::post)
Ed Tanous049a0512018-11-01 13:58:42 -07002035 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002036 constexpr const char* actionSeperator = "/action/";
Ed Tanous049a0512018-11-01 13:58:42 -07002037 size_t actionPosition = objectPath.find(actionSeperator);
Ed Tanous71d5d8d2022-01-25 11:04:33 -08002038 if (actionPosition != std::string::npos)
Ed Tanous049a0512018-11-01 13:58:42 -07002039 {
2040 std::string postProperty =
2041 objectPath.substr((actionPosition + strlen(actionSeperator)),
2042 objectPath.length());
Ed Tanous7f57f192022-12-20 09:53:40 -08002043 objectPath.resize(actionPosition);
zhanghch058d1b46d2021-04-01 11:18:24 +08002044 handleAction(req, asyncResp, objectPath, postProperty);
Ed Tanous049a0512018-11-01 13:58:42 -07002045 return;
2046 }
2047 }
Ed Tanousb41187f2019-10-24 16:30:02 -07002048 else if (req.method() == boost::beast::http::verb::get)
Ed Tanous049a0512018-11-01 13:58:42 -07002049 {
Ed Tanous11ba3972022-07-11 09:50:41 -07002050 if (objectPath.ends_with("/enumerate"))
Ed Tanous049a0512018-11-01 13:58:42 -07002051 {
2052 objectPath.erase(objectPath.end() - sizeof("enumerate"),
2053 objectPath.end());
zhanghch058d1b46d2021-04-01 11:18:24 +08002054 handleEnumerate(asyncResp, objectPath);
Ed Tanous049a0512018-11-01 13:58:42 -07002055 }
Ed Tanous11ba3972022-07-11 09:50:41 -07002056 else if (objectPath.ends_with("/list"))
Ed Tanous049a0512018-11-01 13:58:42 -07002057 {
2058 objectPath.erase(objectPath.end() - sizeof("list"),
2059 objectPath.end());
zhanghch058d1b46d2021-04-01 11:18:24 +08002060 handleList(asyncResp, objectPath);
Ed Tanous049a0512018-11-01 13:58:42 -07002061 }
2062 else
2063 {
Ed Tanousf839dfe2018-11-12 11:11:15 -08002064 // Trim any trailing "/" at the end
Ed Tanous11ba3972022-07-11 09:50:41 -07002065 if (objectPath.ends_with("/"))
Ed Tanousf839dfe2018-11-12 11:11:15 -08002066 {
2067 objectPath.pop_back();
zhanghch058d1b46d2021-04-01 11:18:24 +08002068 handleList(asyncResp, objectPath, 1);
Ed Tanousf839dfe2018-11-12 11:11:15 -08002069 }
2070 else
2071 {
zhanghch058d1b46d2021-04-01 11:18:24 +08002072 handleGet(asyncResp, objectPath, destProperty);
Ed Tanousf839dfe2018-11-12 11:11:15 -08002073 }
Ed Tanous049a0512018-11-01 13:58:42 -07002074 }
2075 return;
2076 }
Ed Tanousb41187f2019-10-24 16:30:02 -07002077 else if (req.method() == boost::beast::http::verb::put)
Ed Tanous049a0512018-11-01 13:58:42 -07002078 {
zhanghch058d1b46d2021-04-01 11:18:24 +08002079 handlePut(req, asyncResp, objectPath, destProperty);
Ed Tanous049a0512018-11-01 13:58:42 -07002080 return;
2081 }
Ed Tanousb41187f2019-10-24 16:30:02 -07002082 else if (req.method() == boost::beast::http::verb::delete_)
Matt Spinlerde818812018-12-11 16:39:20 -06002083 {
zhanghch058d1b46d2021-04-01 11:18:24 +08002084 handleDelete(asyncResp, objectPath);
Matt Spinlerde818812018-12-11 16:39:20 -06002085 return;
2086 }
Ed Tanous049a0512018-11-01 13:58:42 -07002087
zhanghch058d1b46d2021-04-01 11:18:24 +08002088 setErrorResponse(asyncResp->res,
2089 boost::beast::http::status::method_not_allowed,
Matt Spinlerc4e8d21d62018-12-11 11:47:17 -06002090 methodNotAllowedDesc, methodNotAllowedMsg);
Ed Tanous049a0512018-11-01 13:58:42 -07002091}
2092
Ed Tanous1656b292022-05-04 11:33:42 -07002093inline void
2094 handleBusSystemPost(const crow::Request& req,
2095 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2096 const std::string& processName,
2097 const std::string& requestedPath)
2098{
2099 std::vector<std::string> strs;
Ed Tanous50ebd4a2023-01-19 19:03:17 -08002100
2101 bmcweb::split(strs, requestedPath, '/');
Ed Tanous1656b292022-05-04 11:33:42 -07002102 std::string objectPath;
2103 std::string interfaceName;
2104 std::string methodName;
2105 auto it = strs.begin();
2106 if (it == strs.end())
2107 {
2108 objectPath = "/";
2109 }
2110 while (it != strs.end())
2111 {
2112 // Check if segment contains ".". If it does, it must be an
2113 // interface
2114 if (it->find(".") != std::string::npos)
2115 {
2116 break;
2117 // This check is necessary as the trailing slash gets
2118 // parsed as part of our <path> specifier above, which
2119 // causes the normal trailing backslash redirector to
2120 // fail.
2121 }
2122 if (!it->empty())
2123 {
2124 objectPath += "/" + *it;
2125 }
2126 it++;
2127 }
2128 if (it != strs.end())
2129 {
2130 interfaceName = *it;
2131 it++;
2132
2133 // after interface, we might have a method name
2134 if (it != strs.end())
2135 {
2136 methodName = *it;
2137 it++;
2138 }
2139 }
2140 if (it != strs.end())
2141 {
2142 // if there is more levels past the method name, something
2143 // went wrong, return not found
2144 asyncResp->res.result(boost::beast::http::status::not_found);
2145 return;
2146 }
2147 if (interfaceName.empty())
2148 {
2149 crow::connections::systemBus->async_method_call(
2150 [asyncResp, processName,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002151 objectPath](const boost::system::error_code& ec,
Ed Tanous1656b292022-05-04 11:33:42 -07002152 const std::string& introspectXml) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002153 if (ec)
2154 {
Ed Tanous62598e32023-07-17 17:06:25 -07002155 BMCWEB_LOG_ERROR(
2156 "Introspect call failed with error: {} on process: {} path: {}",
2157 ec.message(), processName, objectPath);
Ed Tanous002d39b2022-05-31 08:59:27 -07002158 return;
2159 }
2160 tinyxml2::XMLDocument doc;
Ed Tanous1656b292022-05-04 11:33:42 -07002161
Ed Tanous002d39b2022-05-31 08:59:27 -07002162 doc.Parse(introspectXml.c_str());
2163 tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
2164 if (pRoot == nullptr)
2165 {
Ed Tanous62598e32023-07-17 17:06:25 -07002166 BMCWEB_LOG_ERROR("XML document failed to parse {} {}",
2167 processName, objectPath);
Ed Tanous002d39b2022-05-31 08:59:27 -07002168 asyncResp->res.jsonValue["status"] = "XML parse error";
2169 asyncResp->res.result(
2170 boost::beast::http::status::internal_server_error);
2171 return;
2172 }
2173
Ed Tanous62598e32023-07-17 17:06:25 -07002174 BMCWEB_LOG_DEBUG("{}", introspectXml);
Ed Tanous002d39b2022-05-31 08:59:27 -07002175 asyncResp->res.jsonValue["status"] = "ok";
2176 asyncResp->res.jsonValue["bus_name"] = processName;
2177 asyncResp->res.jsonValue["object_path"] = objectPath;
2178
2179 nlohmann::json& interfacesArray =
2180 asyncResp->res.jsonValue["interfaces"];
2181 interfacesArray = nlohmann::json::array();
2182 tinyxml2::XMLElement* interface =
2183 pRoot->FirstChildElement("interface");
2184
2185 while (interface != nullptr)
2186 {
2187 const char* ifaceName = interface->Attribute("name");
2188 if (ifaceName != nullptr)
Ed Tanous1656b292022-05-04 11:33:42 -07002189 {
Ed Tanous8a592812022-06-04 09:06:59 -07002190 nlohmann::json::object_t interfaceObj;
2191 interfaceObj["name"] = ifaceName;
Patrick Williamsb2ba3072023-05-12 10:27:39 -05002192 interfacesArray.emplace_back(std::move(interfaceObj));
Ed Tanous1656b292022-05-04 11:33:42 -07002193 }
2194
Ed Tanous002d39b2022-05-31 08:59:27 -07002195 interface = interface->NextSiblingElement("interface");
2196 }
Ed Tanous1656b292022-05-04 11:33:42 -07002197 },
2198 processName, objectPath, "org.freedesktop.DBus.Introspectable",
2199 "Introspect");
2200 }
2201 else if (methodName.empty())
2202 {
2203 crow::connections::systemBus->async_method_call(
2204 [asyncResp, processName, objectPath,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002205 interfaceName](const boost::system::error_code& ec,
Ed Tanous1656b292022-05-04 11:33:42 -07002206 const std::string& introspectXml) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002207 if (ec)
2208 {
Ed Tanous62598e32023-07-17 17:06:25 -07002209 BMCWEB_LOG_ERROR(
2210 "Introspect call failed with error: {} on process: {} path: {}",
2211 ec.message(), processName, objectPath);
Ed Tanous002d39b2022-05-31 08:59:27 -07002212 return;
2213 }
2214 tinyxml2::XMLDocument doc;
Ed Tanous1656b292022-05-04 11:33:42 -07002215
Ed Tanous002d39b2022-05-31 08:59:27 -07002216 doc.Parse(introspectXml.data(), introspectXml.size());
2217 tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
2218 if (pRoot == nullptr)
2219 {
Ed Tanous62598e32023-07-17 17:06:25 -07002220 BMCWEB_LOG_ERROR("XML document failed to parse {} {}",
2221 processName, objectPath);
Ed Tanous002d39b2022-05-31 08:59:27 -07002222 asyncResp->res.result(
2223 boost::beast::http::status::internal_server_error);
2224 return;
2225 }
2226
2227 asyncResp->res.jsonValue["status"] = "ok";
2228 asyncResp->res.jsonValue["bus_name"] = processName;
2229 asyncResp->res.jsonValue["interface"] = interfaceName;
2230 asyncResp->res.jsonValue["object_path"] = objectPath;
2231
2232 nlohmann::json& methodsArray = asyncResp->res.jsonValue["methods"];
2233 methodsArray = nlohmann::json::array();
2234
2235 nlohmann::json& signalsArray = asyncResp->res.jsonValue["signals"];
2236 signalsArray = nlohmann::json::array();
2237
2238 nlohmann::json& propertiesObj =
2239 asyncResp->res.jsonValue["properties"];
2240 propertiesObj = nlohmann::json::object();
2241
2242 // if we know we're the only call, build the
2243 // json directly
2244 tinyxml2::XMLElement* interface =
2245 pRoot->FirstChildElement("interface");
2246 while (interface != nullptr)
2247 {
2248 const char* ifaceName = interface->Attribute("name");
2249
2250 if (ifaceName != nullptr && ifaceName == interfaceName)
Ed Tanous1656b292022-05-04 11:33:42 -07002251 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002252 break;
Ed Tanous1656b292022-05-04 11:33:42 -07002253 }
Ed Tanous14766872022-03-15 10:44:42 -07002254
Ed Tanous002d39b2022-05-31 08:59:27 -07002255 interface = interface->NextSiblingElement("interface");
2256 }
2257 if (interface == nullptr)
2258 {
2259 // if we got to the end of the list and
2260 // never found a match, throw 404
2261 asyncResp->res.result(boost::beast::http::status::not_found);
2262 return;
2263 }
Ed Tanous1656b292022-05-04 11:33:42 -07002264
Ed Tanous002d39b2022-05-31 08:59:27 -07002265 tinyxml2::XMLElement* methods =
2266 interface->FirstChildElement("method");
2267 while (methods != nullptr)
2268 {
2269 nlohmann::json argsArray = nlohmann::json::array();
2270 tinyxml2::XMLElement* arg = methods->FirstChildElement("arg");
2271 while (arg != nullptr)
Ed Tanous1656b292022-05-04 11:33:42 -07002272 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002273 nlohmann::json thisArg;
2274 for (const char* fieldName : std::array<const char*, 3>{
2275 "name", "direction", "type"})
Ed Tanous1656b292022-05-04 11:33:42 -07002276 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002277 const char* fieldValue = arg->Attribute(fieldName);
2278 if (fieldValue != nullptr)
Ed Tanous1656b292022-05-04 11:33:42 -07002279 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002280 thisArg[fieldName] = fieldValue;
2281 }
2282 }
Patrick Williamsb2ba3072023-05-12 10:27:39 -05002283 argsArray.emplace_back(std::move(thisArg));
Ed Tanous002d39b2022-05-31 08:59:27 -07002284 arg = arg->NextSiblingElement("arg");
2285 }
2286
2287 const char* name = methods->Attribute("name");
2288 if (name != nullptr)
2289 {
2290 std::string uri;
2291 uri.reserve(14 + processName.size() + objectPath.size() +
2292 interfaceName.size() + strlen(name));
2293 uri += "/bus/system/";
2294 uri += processName;
2295 uri += objectPath;
2296 uri += "/";
2297 uri += interfaceName;
2298 uri += "/";
2299 uri += name;
2300
2301 nlohmann::json::object_t object;
2302 object["name"] = name;
2303 object["uri"] = std::move(uri);
2304 object["args"] = argsArray;
2305
Patrick Williamsb2ba3072023-05-12 10:27:39 -05002306 methodsArray.emplace_back(std::move(object));
Ed Tanous002d39b2022-05-31 08:59:27 -07002307 }
2308 methods = methods->NextSiblingElement("method");
2309 }
2310 tinyxml2::XMLElement* signals =
2311 interface->FirstChildElement("signal");
2312 while (signals != nullptr)
2313 {
2314 nlohmann::json argsArray = nlohmann::json::array();
2315
2316 tinyxml2::XMLElement* arg = signals->FirstChildElement("arg");
2317 while (arg != nullptr)
2318 {
2319 const char* name = arg->Attribute("name");
2320 const char* type = arg->Attribute("type");
2321 if (name != nullptr && type != nullptr)
2322 {
2323 argsArray.push_back({
2324 {"name", name},
2325 {"type", type},
2326 });
2327 }
2328 arg = arg->NextSiblingElement("arg");
2329 }
2330 const char* name = signals->Attribute("name");
2331 if (name != nullptr)
2332 {
2333 nlohmann::json::object_t object;
2334 object["name"] = name;
2335 object["args"] = argsArray;
Patrick Williamsb2ba3072023-05-12 10:27:39 -05002336 signalsArray.emplace_back(std::move(object));
Ed Tanous002d39b2022-05-31 08:59:27 -07002337 }
2338
2339 signals = signals->NextSiblingElement("signal");
2340 }
2341
2342 tinyxml2::XMLElement* property =
2343 interface->FirstChildElement("property");
2344 while (property != nullptr)
2345 {
2346 const char* name = property->Attribute("name");
2347 const char* type = property->Attribute("type");
2348 if (type != nullptr && name != nullptr)
2349 {
Patrick Williams59d494e2022-07-22 19:26:55 -05002350 sdbusplus::message_t m =
Ed Tanous002d39b2022-05-31 08:59:27 -07002351 crow::connections::systemBus->new_method_call(
2352 processName.c_str(), objectPath.c_str(),
2353 "org.freedesktop."
2354 "DBus."
2355 "Properties",
2356 "Get");
2357 m.append(interfaceName, name);
2358 nlohmann::json& propertyItem = propertiesObj[name];
2359 crow::connections::systemBus->async_send(
2360 m, [&propertyItem,
Ed Tanous8b242752023-06-27 17:17:13 -07002361 asyncResp](const boost::system::error_code& ec2,
Patrick Williams59d494e2022-07-22 19:26:55 -05002362 sdbusplus::message_t& msg) {
Ed Tanous8b242752023-06-27 17:17:13 -07002363 if (ec2)
Ed Tanous1656b292022-05-04 11:33:42 -07002364 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002365 return;
Ed Tanous1656b292022-05-04 11:33:42 -07002366 }
Ed Tanous1656b292022-05-04 11:33:42 -07002367
Ed Tanous002d39b2022-05-31 08:59:27 -07002368 convertDBusToJSON("v", msg, propertyItem);
2369 });
Ed Tanous1656b292022-05-04 11:33:42 -07002370 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002371 property = property->NextSiblingElement("property");
2372 }
Ed Tanous1656b292022-05-04 11:33:42 -07002373 },
2374 processName, objectPath, "org.freedesktop.DBus.Introspectable",
2375 "Introspect");
2376 }
2377 else
2378 {
2379 if (req.method() != boost::beast::http::verb::post)
2380 {
2381 asyncResp->res.result(boost::beast::http::status::not_found);
2382 return;
2383 }
2384
Ed Tanous1aa0c2b2022-02-08 12:24:30 +01002385 nlohmann::json requestDbusData;
2386 JsonParseResult ret = parseRequestAsJson(req, requestDbusData);
2387 if (ret == JsonParseResult::BadContentType)
Ed Tanous1656b292022-05-04 11:33:42 -07002388 {
Ed Tanous1aa0c2b2022-02-08 12:24:30 +01002389 setErrorResponse(asyncResp->res,
2390 boost::beast::http::status::unsupported_media_type,
2391 invalidContentType, unsupportedMediaMsg);
Ed Tanous1656b292022-05-04 11:33:42 -07002392 return;
2393 }
Ed Tanous1aa0c2b2022-02-08 12:24:30 +01002394 if (ret != JsonParseResult::Success)
2395 {
2396 setErrorResponse(asyncResp->res,
2397 boost::beast::http::status::bad_request,
2398 noJsonDesc, badReqMsg);
2399 return;
2400 }
2401
Ed Tanous1656b292022-05-04 11:33:42 -07002402 if (!requestDbusData.is_array())
2403 {
2404 asyncResp->res.result(boost::beast::http::status::bad_request);
2405 return;
2406 }
Lei YU28dd5ca2023-03-17 13:17:05 +08002407 auto transaction = std::make_shared<InProgressActionData>(asyncResp);
Ed Tanous1656b292022-05-04 11:33:42 -07002408
2409 transaction->path = objectPath;
2410 transaction->methodName = methodName;
2411 transaction->arguments = std::move(requestDbusData);
2412
2413 findActionOnInterface(transaction, processName);
2414 }
2415}
2416
Ed Tanous23a21a12020-07-25 04:45:05 +00002417inline void requestRoutes(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002418{
2419 BMCWEB_ROUTE(app, "/bus/")
Ed Tanous432a8902021-06-14 15:28:56 -07002420 .privileges({{"Login"}})
Ed Tanousb41187f2019-10-24 16:30:02 -07002421 .methods(boost::beast::http::verb::get)(
zhanghch058d1b46d2021-04-01 11:18:24 +08002422 [](const crow::Request&,
2423 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002424 nlohmann::json::array_t buses;
2425 nlohmann::json& bus = buses.emplace_back();
2426 bus["name"] = "system";
2427 asyncResp->res.jsonValue["busses"] = std::move(buses);
2428 asyncResp->res.jsonValue["status"] = "ok";
2429 });
Ed Tanous1abe55e2018-09-05 08:30:59 -07002430
2431 BMCWEB_ROUTE(app, "/bus/system/")
Ed Tanous432a8902021-06-14 15:28:56 -07002432 .privileges({{"Login"}})
Ed Tanousb41187f2019-10-24 16:30:02 -07002433 .methods(boost::beast::http::verb::get)(
zhanghch058d1b46d2021-04-01 11:18:24 +08002434 [](const crow::Request&,
2435 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002436 auto myCallback = [asyncResp](const boost::system::error_code& ec,
zhanghch058d1b46d2021-04-01 11:18:24 +08002437 std::vector<std::string>& names) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002438 if (ec)
2439 {
Ed Tanous62598e32023-07-17 17:06:25 -07002440 BMCWEB_LOG_ERROR("Dbus call failed with code {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -07002441 asyncResp->res.result(
2442 boost::beast::http::status::internal_server_error);
2443 }
2444 else
2445 {
2446 std::sort(names.begin(), names.end());
2447 asyncResp->res.jsonValue["status"] = "ok";
2448 auto& objectsSub = asyncResp->res.jsonValue["objects"];
Ed Tanous02cad962022-06-30 16:50:15 -07002449 for (const auto& name : names)
Ed Tanous002d39b2022-05-31 08:59:27 -07002450 {
2451 nlohmann::json::object_t object;
2452 object["name"] = name;
Patrick Williamsb2ba3072023-05-12 10:27:39 -05002453 objectsSub.emplace_back(std::move(object));
Ed Tanous002d39b2022-05-31 08:59:27 -07002454 }
2455 }
2456 };
2457 crow::connections::systemBus->async_method_call(
2458 std::move(myCallback), "org.freedesktop.DBus", "/",
2459 "org.freedesktop.DBus", "ListNames");
2460 });
Ed Tanous1abe55e2018-09-05 08:30:59 -07002461
2462 BMCWEB_ROUTE(app, "/list/")
Ed Tanous432a8902021-06-14 15:28:56 -07002463 .privileges({{"Login"}})
Ed Tanousb41187f2019-10-24 16:30:02 -07002464 .methods(boost::beast::http::verb::get)(
zhanghch058d1b46d2021-04-01 11:18:24 +08002465 [](const crow::Request&,
2466 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002467 handleList(asyncResp, "/");
2468 });
Ed Tanous1abe55e2018-09-05 08:30:59 -07002469
2470 BMCWEB_ROUTE(app, "/xyz/<path>")
Ed Tanous432a8902021-06-14 15:28:56 -07002471 .privileges({{"Login"}})
zhanghch058d1b46d2021-04-01 11:18:24 +08002472 .methods(boost::beast::http::verb::get)(
2473 [](const crow::Request& req,
2474 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002475 const std::string& path) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002476 std::string objectPath = "/xyz/" + path;
2477 handleDBusUrl(req, asyncResp, objectPath);
2478 });
zhanghch058d1b46d2021-04-01 11:18:24 +08002479
2480 BMCWEB_ROUTE(app, "/xyz/<path>")
Ed Tanous432a8902021-06-14 15:28:56 -07002481 .privileges({{"ConfigureComponents", "ConfigureManager"}})
zhanghch058d1b46d2021-04-01 11:18:24 +08002482 .methods(boost::beast::http::verb::put, boost::beast::http::verb::post,
2483 boost::beast::http::verb::delete_)(
2484 [](const crow::Request& req,
2485 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2486 const std::string& path) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002487 std::string objectPath = "/xyz/" + path;
2488 handleDBusUrl(req, asyncResp, objectPath);
2489 });
Ed Tanous1abe55e2018-09-05 08:30:59 -07002490
Ed Tanous049a0512018-11-01 13:58:42 -07002491 BMCWEB_ROUTE(app, "/org/<path>")
Ed Tanous432a8902021-06-14 15:28:56 -07002492 .privileges({{"Login"}})
zhanghch058d1b46d2021-04-01 11:18:24 +08002493 .methods(boost::beast::http::verb::get)(
2494 [](const crow::Request& req,
2495 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2496 const std::string& path) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002497 std::string objectPath = "/org/" + path;
2498 handleDBusUrl(req, asyncResp, objectPath);
2499 });
Tanousf00032d2018-11-05 01:18:10 -03002500
2501 BMCWEB_ROUTE(app, "/org/<path>")
Ed Tanous432a8902021-06-14 15:28:56 -07002502 .privileges({{"ConfigureComponents", "ConfigureManager"}})
Ed Tanousb41187f2019-10-24 16:30:02 -07002503 .methods(boost::beast::http::verb::put, boost::beast::http::verb::post,
2504 boost::beast::http::verb::delete_)(
zhanghch058d1b46d2021-04-01 11:18:24 +08002505 [](const crow::Request& req,
2506 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002507 const std::string& path) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002508 std::string objectPath = "/org/" + path;
2509 handleDBusUrl(req, asyncResp, objectPath);
2510 });
Ed Tanous1abe55e2018-09-05 08:30:59 -07002511
Ed Tanous1abe55e2018-09-05 08:30:59 -07002512 BMCWEB_ROUTE(app, "/download/dump/<str>/")
Ed Tanous432a8902021-06-14 15:28:56 -07002513 .privileges({{"ConfigureManager"}})
zhanghch058d1b46d2021-04-01 11:18:24 +08002514 .methods(boost::beast::http::verb::get)(
2515 [](const crow::Request&,
2516 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2517 const std::string& dumpId) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002518 if (!validateFilename(dumpId))
2519 {
2520 asyncResp->res.result(boost::beast::http::status::bad_request);
2521 return;
2522 }
2523 std::filesystem::path loc("/var/lib/phosphor-debug-collector/dumps");
Ramesh Iyyard9207042019-07-05 08:04:42 -05002524
Ed Tanous002d39b2022-05-31 08:59:27 -07002525 loc /= dumpId;
Ramesh Iyyard9207042019-07-05 08:04:42 -05002526
Ed Tanous002d39b2022-05-31 08:59:27 -07002527 if (!std::filesystem::exists(loc) ||
2528 !std::filesystem::is_directory(loc))
2529 {
Ed Tanous62598e32023-07-17 17:06:25 -07002530 BMCWEB_LOG_ERROR("{}Not found", loc.string());
Ed Tanous002d39b2022-05-31 08:59:27 -07002531 asyncResp->res.result(boost::beast::http::status::not_found);
2532 return;
2533 }
2534 std::filesystem::directory_iterator files(loc);
zhanghch058d1b46d2021-04-01 11:18:24 +08002535
Ed Tanous002d39b2022-05-31 08:59:27 -07002536 for (const auto& file : files)
2537 {
2538 std::ifstream readFile(file.path());
2539 if (!readFile.good())
2540 {
2541 continue;
2542 }
zhanghch058d1b46d2021-04-01 11:18:24 +08002543
Ed Tanousd9f6c622022-03-17 09:12:17 -07002544 asyncResp->res.addHeader(boost::beast::http::field::content_type,
Ed Tanous002d39b2022-05-31 08:59:27 -07002545 "application/octet-stream");
zhanghch058d1b46d2021-04-01 11:18:24 +08002546
Ed Tanous002d39b2022-05-31 08:59:27 -07002547 // Assuming only one dump file will be present in the dump
2548 // id directory
2549 std::string dumpFileName = file.path().filename().string();
zhanghch058d1b46d2021-04-01 11:18:24 +08002550
Ed Tanous002d39b2022-05-31 08:59:27 -07002551 // Filename should be in alphanumeric, dot and underscore
2552 // Its based on phosphor-debug-collector application
2553 // dumpfile format
Ed Tanous4b242742023-05-11 09:51:51 -07002554 static std::regex dumpFileRegex("[a-zA-Z0-9\\._]+");
Ed Tanous002d39b2022-05-31 08:59:27 -07002555 if (!std::regex_match(dumpFileName, dumpFileRegex))
2556 {
Ed Tanous62598e32023-07-17 17:06:25 -07002557 BMCWEB_LOG_ERROR("Invalid dump filename {}", dumpFileName);
zhanghch058d1b46d2021-04-01 11:18:24 +08002558 asyncResp->res.result(boost::beast::http::status::not_found);
Ed Tanousad18f072018-11-14 14:07:48 -08002559 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002560 }
Patrick Williams89492a12023-05-10 07:51:34 -05002561 std::string contentDispositionParam = "attachment; filename=\"" +
2562 dumpFileName + "\"";
Ed Tanous002d39b2022-05-31 08:59:27 -07002563
Ed Tanousd9f6c622022-03-17 09:12:17 -07002564 asyncResp->res.addHeader(
2565 boost::beast::http::field::content_disposition,
2566 contentDispositionParam);
Ed Tanous002d39b2022-05-31 08:59:27 -07002567
2568 asyncResp->res.body() = {std::istreambuf_iterator<char>(readFile),
2569 std::istreambuf_iterator<char>()};
2570 return;
2571 }
2572 asyncResp->res.result(boost::beast::http::status::not_found);
2573 return;
2574 });
Ed Tanous1abe55e2018-09-05 08:30:59 -07002575
Ed Tanouse3cb5a32018-08-08 14:16:49 -07002576 BMCWEB_ROUTE(app, "/bus/system/<str>/")
Ed Tanous432a8902021-06-14 15:28:56 -07002577 .privileges({{"Login"}})
Ed Tanousb41187f2019-10-24 16:30:02 -07002578
2579 .methods(boost::beast::http::verb::get)(
zhanghch058d1b46d2021-04-01 11:18:24 +08002580 [](const crow::Request&,
2581 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous81ce6092020-12-17 16:54:55 +00002582 const std::string& connection) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002583 introspectObjects(connection, "/", asyncResp);
2584 });
Ed Tanouse3cb5a32018-08-08 14:16:49 -07002585
2586 BMCWEB_ROUTE(app, "/bus/system/<str>/<path>")
Ed Tanous432a8902021-06-14 15:28:56 -07002587 .privileges({{"ConfigureComponents", "ConfigureManager"}})
Ed Tanous1656b292022-05-04 11:33:42 -07002588 .methods(boost::beast::http::verb::get,
2589 boost::beast::http::verb::post)(handleBusSystemPost);
Ed Tanous1abe55e2018-09-05 08:30:59 -07002590}
2591} // namespace openbmc_mapper
2592} // namespace crow