1 #pragma once
2 
3 #include <chrono>
4 #include <ipmid/api-types.hpp>
5 #include <ipmid/types.hpp>
6 #include <optional>
7 #include <sdbusplus/server.hpp>
8 
9 namespace ipmi
10 {
11 
12 using namespace std::literals::chrono_literals;
13 
14 constexpr auto MAPPER_BUS_NAME = "xyz.openbmc_project.ObjectMapper";
15 constexpr auto MAPPER_OBJ = "/xyz/openbmc_project/object_mapper";
16 constexpr auto MAPPER_INTF = "xyz.openbmc_project.ObjectMapper";
17 
18 constexpr auto ROOT = "/";
19 constexpr auto HOST_MATCH = "host0";
20 
21 constexpr auto PROP_INTF = "org.freedesktop.DBus.Properties";
22 constexpr auto DELETE_INTERFACE = "xyz.openbmc_project.Object.Delete";
23 
24 constexpr auto METHOD_GET = "Get";
25 constexpr auto METHOD_GET_ALL = "GetAll";
26 constexpr auto METHOD_SET = "Set";
27 
28 /* Use a value of 5s which aligns with BT/KCS bridged timeouts, rather
29  * than the default 25s D-Bus timeout. */
30 constexpr std::chrono::microseconds IPMI_DBUS_TIMEOUT = 5s;
31 
32 /** @class ServiceCache
33  *  @brief Caches lookups of service names from the object mapper.
34  *  @details Most ipmi commands need to talk to other dbus daemons to perform
35  *           their intended actions on the BMC. This usually means they will
36  *           first look up the service name providing the interface they
37  *           require. This class reduces the number of such calls by caching
38  *           the lookup for a specific service.
39  */
40 class ServiceCache
41 {
42   public:
43     /** @brief Creates a new service cache for the given interface
44      *         and path.
45      *
46      *  @param[in] intf - The interface used for each lookup
47      *  @param[in] path - The path used for each lookup
48      */
49     ServiceCache(const std::string& intf, const std::string& path);
50     ServiceCache(std::string&& intf, std::string&& path);
51 
52     /** @brief Gets the service name from the cache or does in a
53      *         lookup when invalid.
54      *
55      *  @param[in] bus - The bus associated with and used for looking
56      *                   up the service.
57      */
58     const std::string& getService(sdbusplus::bus::bus& bus);
59 
60     /** @brief Invalidates the current service name */
61     void invalidate();
62 
63     /** @brief A wrapper around sdbusplus bus.new_method_call
64      *
65      *  @param[in] bus - The bus used for calling the method
66      *  @param[in] intf - The interface containing the method
67      *  @param[in] method - The method name
68      *  @return The message containing the method call.
69      */
70     sdbusplus::message::message newMethodCall(sdbusplus::bus::bus& bus,
71                                               const char* intf,
72                                               const char* method);
73 
74     /** @brief Check to see if the current cache is valid
75      *
76      * @param[in] bus - The bus used for the service lookup
77      * @return True if the cache is valid false otherwise.
78      */
79     bool isValid(sdbusplus::bus::bus& bus) const;
80 
81   private:
82     /** @brief DBUS interface provided by the service */
83     const std::string intf;
84     /** @brief DBUS path provided by the service */
85     const std::string path;
86     /** @brief The name of the service if valid */
87     std::optional<std::string> cachedService;
88     /** @brief The name of the bus used in the service lookup */
89     std::optional<std::string> cachedBusName;
90 };
91 
92 /**
93  * @brief Get the DBUS Service name for the input dbus path
94  *
95  * @param[in] bus - DBUS Bus Object
96  * @param[in] intf - DBUS Interface
97  * @param[in] path - DBUS Object Path
98  *
99  */
100 std::string getService(sdbusplus::bus::bus& bus, const std::string& intf,
101                        const std::string& path);
102 
103 /** @brief Gets the dbus object info implementing the given interface
104  *         from the given subtree.
105  *  @param[in] bus - DBUS Bus Object.
106  *  @param[in] interface - Dbus interface.
107  *  @param[in] subtreePath - subtree from where the search should start.
108  *  @param[in] match - identifier for object.
109  *  @return On success returns the object having objectpath and servicename.
110  */
111 DbusObjectInfo getDbusObject(sdbusplus::bus::bus& bus,
112                              const std::string& interface,
113                              const std::string& subtreePath = ROOT,
114                              const std::string& match = {});
115 
116 /** @brief Get the ipObject of first dbus IP object of Non-LinkLocalIPAddress
117  *         type from the given subtree, if not available gets IP object of
118  *         LinkLocalIPAddress type.
119  *  @param[in] bus - DBUS Bus Object.
120  *  @param[in] interface - Dbus interface.
121  *  @param[in] subtreePath - subtree from where the search should start.
122  *  @param[in] match - identifier for object.
123  *  @return On success returns the object having objectpath and servicename.
124  */
125 DbusObjectInfo getIPObject(sdbusplus::bus::bus& bus,
126                            const std::string& interface,
127                            const std::string& subtreePath,
128                            const std::string& match);
129 
130 /** @brief Gets the value associated with the given object
131  *         and the interface.
132  *  @param[in] bus - DBUS Bus Object.
133  *  @param[in] service - Dbus service name.
134  *  @param[in] objPath - Dbus object path.
135  *  @param[in] interface - Dbus interface.
136  *  @param[in] property - name of the property.
137  *  @return On success returns the value of the property.
138  */
139 Value getDbusProperty(sdbusplus::bus::bus& bus, const std::string& service,
140                       const std::string& objPath, const std::string& interface,
141                       const std::string& property,
142                       std::chrono::microseconds timeout = IPMI_DBUS_TIMEOUT);
143 
144 /** @brief Gets all the properties associated with the given object
145  *         and the interface.
146  *  @param[in] bus - DBUS Bus Object.
147  *  @param[in] service - Dbus service name.
148  *  @param[in] objPath - Dbus object path.
149  *  @param[in] interface - Dbus interface.
150  *  @return On success returns the map of name value pair.
151  */
152 PropertyMap
153     getAllDbusProperties(sdbusplus::bus::bus& bus, const std::string& service,
154                          const std::string& objPath,
155                          const std::string& interface,
156                          std::chrono::microseconds timeout = IPMI_DBUS_TIMEOUT);
157 
158 /** @brief Gets all managed objects associated with the given object
159  *         path and service.
160  *  @param[in] bus - D-Bus Bus Object.
161  *  @param[in] service - D-Bus service name.
162  *  @param[in] objPath - D-Bus object path.
163  *  @return On success returns the map of name value pair.
164  */
165 ObjectValueTree getManagedObjects(sdbusplus::bus::bus& bus,
166                                   const std::string& service,
167                                   const std::string& objPath);
168 
169 /** @brief Sets the property value of the given object.
170  *  @param[in] bus - DBUS Bus Object.
171  *  @param[in] service - Dbus service name.
172  *  @param[in] objPath - Dbus object path.
173  *  @param[in] interface - Dbus interface.
174  *  @param[in] property - name of the property.
175  *  @param[in] value - value which needs to be set.
176  */
177 void setDbusProperty(sdbusplus::bus::bus& bus, const std::string& service,
178                      const std::string& objPath, const std::string& interface,
179                      const std::string& property, const Value& value,
180                      std::chrono::microseconds timeout = IPMI_DBUS_TIMEOUT);
181 
182 /** @brief  Gets all the dbus objects from the given service root
183  *          which matches the object identifier.
184  *  @param[in] bus - DBUS Bus Object.
185  *  @param[in] serviceRoot - Service root path.
186  *  @param[in] interface - Dbus interface.
187  *  @param[in] match - Identifier for a path.
188  *  @returns map of object path and service info.
189  */
190 ObjectTree getAllDbusObjects(sdbusplus::bus::bus& bus,
191                              const std::string& serviceRoot,
192                              const std::string& interface,
193                              const std::string& match = {});
194 
195 /** @brief Deletes all the dbus objects from the given service root
196            which matches the object identifier.
197  *  @param[in] bus - DBUS Bus Object.
198  *  @param[in] serviceRoot - Service root path.
199  *  @param[in] interface - Dbus interface.
200  *  @param[in] match - Identifier for object.
201  */
202 void deleteAllDbusObjects(sdbusplus::bus::bus& bus,
203                           const std::string& serviceRoot,
204                           const std::string& interface,
205                           const std::string& match = {});
206 
207 /** @brief Gets the ancestor objects of the given object
208            which implements the given interface.
209  *  @param[in] bus - Dbus bus object.
210  *  @param[in] path - Child Dbus object path.
211  *  @param[in] interfaces - Dbus interface list.
212  *  @return map of object path and service info.
213  */
214 ObjectTree getAllAncestors(sdbusplus::bus::bus& bus, const std::string& path,
215                            InterfaceList&& interfaces);
216 
217 /** @struct VariantToDoubleVisitor
218  *  @brief Visitor to convert variants to doubles
219  *  @details Performs a static cast on the underlying type
220  */
221 struct VariantToDoubleVisitor
222 {
223     template <typename T>
224     std::enable_if_t<std::is_arithmetic<T>::value, double>
225         operator()(const T& t) const
226     {
227         return static_cast<double>(t);
228     }
229 
230     template <typename T>
231     std::enable_if_t<!std::is_arithmetic<T>::value, double>
232         operator()(const T& t) const
233     {
234         throw std::invalid_argument("Cannot translate type to double");
235     }
236 };
237 
238 namespace method_no_args
239 {
240 
241 /** @brief Calls the Dbus method which waits for response.
242  *  @param[in] bus - DBUS Bus Object.
243  *  @param[in] service - Dbus service name.
244  *  @param[in] objPath - Dbus object path.
245  *  @param[in] interface - Dbus interface.
246  *  @param[in] method - Dbus method.
247  */
248 void callDbusMethod(sdbusplus::bus::bus& bus, const std::string& service,
249                     const std::string& objPath, const std::string& interface,
250                     const std::string& method);
251 
252 } // namespace method_no_args
253 
254 namespace network
255 {
256 
257 constexpr auto ROOT = "/xyz/openbmc_project/network";
258 constexpr auto SERVICE = "xyz.openbmc_project.Network";
259 constexpr auto IP_TYPE = "ipv4";
260 constexpr auto IPV4_PREFIX = "169.254";
261 constexpr auto IPV6_PREFIX = "fe80";
262 constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
263 constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
264 constexpr auto SYSTEMCONFIG_INTERFACE =
265     "xyz.openbmc_project.Network.SystemConfiguration";
266 constexpr auto ETHERNET_INTERFACE =
267     "xyz.openbmc_project.Network.EthernetInterface";
268 constexpr auto IP_CREATE_INTERFACE = "xyz.openbmc_project.Network.IP.Create";
269 constexpr auto VLAN_CREATE_INTERFACE =
270     "xyz.openbmc_project.Network.VLAN.Create";
271 constexpr auto VLAN_INTERFACE = "xyz.openbmc_project.Network.VLAN";
272 
273 /* @brief converts the given subnet into prefix notation.
274  * @param[in] addressFamily - IP address family(AF_INET/AF_INET6).
275  * @param[in] mask - Subnet Mask.
276  * @returns prefix.
277  */
278 uint8_t toPrefix(int addressFamily, const std::string& subnetMask);
279 
280 /** @brief Sets the ip on the system.
281  *  @param[in] bus - DBUS Bus Object.
282  *  @param[in] service - Dbus service name.
283  *  @param[in] objPath - Dbus object path.
284  *  @param[in] protocolType - Protocol type
285  *  @param[in] ipaddress - IPaddress.
286  *  @param[in] prefix - Prefix length.
287  */
288 void createIP(sdbusplus::bus::bus& bus, const std::string& service,
289               const std::string& objPath, const std::string& protocolType,
290               const std::string& ipaddress, uint8_t prefix);
291 
292 /** @brief Creates the VLAN on the given interface.
293  *  @param[in] bus - DBUS Bus Object.
294  *  @param[in] service - Dbus service name.
295  *  @param[in] objPath - Dbus object path.
296  *  @param[in] interface - EthernetInterface.
297  *  @param[in] vlanID - Vlan ID.
298  */
299 void createVLAN(sdbusplus::bus::bus& bus, const std::string& service,
300                 const std::string& objPath, const std::string& interface,
301                 uint32_t vlanID);
302 
303 /** @brief Gets the vlan id from the given object path.
304  *  @param[in] path - Dbus object path.
305  */
306 uint32_t getVLAN(const std::string& path);
307 
308 } // namespace network
309 
310 /** @brief Perform the low-level i2c bus write-read.
311  *  @param[in] i2cBus - i2c bus device node name, such as /dev/i2c-2.
312  *  @param[in] slaveAddr - i2c device slave address.
313  *  @param[in] writeData - The data written to i2c device.
314  *  @param[out] readBuf - Data read from the i2c device.
315  */
316 ipmi::Cc i2cWriteRead(std::string i2cBus, const uint8_t slaveAddr,
317                       std::vector<uint8_t> writeData,
318                       std::vector<uint8_t>& readBuf);
319 } // namespace ipmi
320