1 /*
2 // Copyright (c) 2018 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 
17 #pragma once
18 #include "channel_layer.hpp"
19 
20 #include <boost/interprocess/sync/file_lock.hpp>
21 #include <boost/interprocess/sync/named_recursive_mutex.hpp>
22 #include <cstdint>
23 #include <ctime>
24 #include <nlohmann/json.hpp>
25 #include <sdbusplus/bus.hpp>
26 #include <variant>
27 
28 namespace ipmi
29 {
30 
31 using Json = nlohmann::json;
32 
33 using DbusVariant = std::variant<std::vector<std::string>, std::string, bool>;
34 
35 using DbusChObjProperties = std::vector<std::pair<std::string, DbusVariant>>;
36 
37 static constexpr const char* ipmiChannelMutex = "ipmi_channel_mutex";
38 static constexpr const char* ipmiChMutexCleanupLockFile =
39     "/var/lib/ipmi/ipmi_channel_mutex_cleanup";
40 
41 /** @struct ChannelAccessData
42  *
43  *  Structure to store both non-volatile and volatile channel access information
44  *  as used by IPMI specification (refer spec sec 22.22 to 22.24)
45  */
46 struct ChannelAccessData
47 {
48     ChannelAccess chNonVolatileData;
49     ChannelAccess chVolatileData;
50 };
51 
52 /** @struct ChannelProperties
53  *
54  *  Structure for channel information - base structure to get all information
55  * about the channel.(refer spec sec 22.22 to 22.24)
56  */
57 struct ChannelProperties
58 {
59     std::string chName;
60     uint8_t chID;
61     bool isChValid;
62     uint8_t activeSessCount;
63     ChannelInfo chInfo;
64     ChannelAccessData chAccess;
65     size_t maxTransferSize;
66 };
67 
68 class ChannelConfig;
69 
70 ChannelConfig& getChannelConfigObject();
71 
72 class ChannelConfig
73 {
74   public:
75     ChannelConfig(const ChannelConfig&) = delete;
76     ChannelConfig& operator=(const ChannelConfig&) = delete;
77     ChannelConfig(ChannelConfig&&) = delete;
78     ChannelConfig& operator=(ChannelConfig&&) = delete;
79 
80     ~ChannelConfig();
81     ChannelConfig();
82 
83     /** @brief determines valid channel
84      *
85      *  @param[in] chNum - channel number
86      *
87      *  @return true if valid, false otherwise
88      */
89     bool isValidChannel(const uint8_t chNum);
90 
91     /** @brief determines valid authentication type
92      *
93      *  @param[in] chNum - channel number
94      *  @param[in] authType - authentication type
95      *
96      *  @return true if valid, false otherwise
97      */
98     bool isValidAuthType(const uint8_t chNum, const EAuthType& authType);
99 
100     /** @brief function to get channel name from channel number
101      *
102      *  @param[in] chNum - channel number index
103      *
104      *  @return network channel interface name
105      */
106     std::string getChannelName(const uint8_t chNum);
107 
108     /** @brief function to get channel number from channel name
109      *
110      *  @param[in] chName - channel name
111      *
112      *  @return network channel interface number
113      */
114 
115     uint8_t getChannelByName(const std::string& chName)
116     {
117         return convertToChannelNumberFromChannelName(chName);
118     }
119 
120     /** @brief determines supported session type of a channel
121      *
122      *  @param[in] chNum - channel number
123      *
124      *  @return EChannelSessSupported - supported session type
125      */
126     EChannelSessSupported getChannelSessionSupport(const uint8_t chNum);
127 
128     /** @brief determines number of active sessions on a channel
129      *
130      *  @param[in] chNum - channel number
131      *
132      *  @return numer of active sessions
133      */
134     int getChannelActiveSessions(const uint8_t chNum);
135 
136     /** @brief determines maximum transfer size for a channel
137      *
138      *  @param[in] chNum - channel number
139      *
140      *  @return maximum bytes that can be transferred on this channel
141      */
142     size_t getChannelMaxTransferSize(uint8_t chNum);
143 
144     /** @brief provides channel info details
145      *
146      *  @param[in] chNum - channel number
147      *  @param[out] chInfo - channel info details
148      *
149      *  @return IPMI_CC_OK for success, others for failure.
150      */
151     ipmi_ret_t getChannelInfo(const uint8_t chNum, ChannelInfo& chInfo);
152 
153     /** @brief provides channel access data
154      *
155      *  @param[in] chNum - channel number
156      *  @param[out] chAccessData - channel access data
157      *
158      *  @return IPMI_CC_OK for success, others for failure.
159      */
160     ipmi_ret_t getChannelAccessData(const uint8_t chNum,
161                                     ChannelAccess& chAccessData);
162 
163     /** @brief to set channel access data
164      *
165      *  @param[in] chNum - channel number
166      *  @param[in] chAccessData - channel access data
167      *  @param[in] setFlag - flag to indicate updatable fields
168      *
169      *  @return IPMI_CC_OK for success, others for failure.
170      */
171     ipmi_ret_t setChannelAccessData(const uint8_t chNum,
172                                     const ChannelAccess& chAccessData,
173                                     const uint8_t setFlag);
174 
175     /** @brief to get channel access data persistent data
176      *
177      *  @param[in] chNum - channel number
178      *  @param[out] chAccessData - channel access data
179      *
180      *  @return IPMI_CC_OK for success, others for failure.
181      */
182     ipmi_ret_t getChannelAccessPersistData(const uint8_t chNum,
183                                            ChannelAccess& chAccessData);
184 
185     /** @brief to set channel access data persistent data
186      *
187      *  @param[in] chNum - channel number
188      *  @param[in] chAccessData - channel access data
189      *  @param[in] setFlag - flag to indicate updatable fields
190      *
191      *  @return IPMI_CC_OK for success, others for failure.
192      */
193     ipmi_ret_t setChannelAccessPersistData(const uint8_t chNum,
194                                            const ChannelAccess& chAccessData,
195                                            const uint8_t setFlag);
196 
197     /** @brief provides supported authentication type for the channel
198      *
199      *  @param[in] chNum - channel number
200      *  @param[out] authTypeSupported - supported authentication type
201      *
202      *  @return IPMI_CC_OK for success, others for failure.
203      */
204     ipmi_ret_t getChannelAuthTypeSupported(const uint8_t chNum,
205                                            uint8_t& authTypeSupported);
206 
207     /** @brief provides enabled authentication type for the channel
208      *
209      *  @param[in] chNum - channel number
210      *  @param[in] priv - privilege
211      *  @param[out] authType - enabled authentication type
212      *
213      *  @return IPMI_CC_OK for success, others for failure.
214      */
215     ipmi_ret_t getChannelEnabledAuthType(const uint8_t chNum,
216                                          const uint8_t priv,
217                                          EAuthType& authType);
218 
219     /** @brief conver to channel privilege from system privilege
220      *
221      *  @param[in] value - privilege value
222      *
223      *  @return Channel privilege
224      */
225     CommandPrivilege convertToPrivLimitIndex(const std::string& value);
226 
227     /** @brief function to write persistent channel configuration to config file
228      *
229      *  @return 0 for success, -errno for failure.
230      */
231     int writeChannelPersistData();
232 
233     /** @brief function to write volatile channel configuration to config file
234      *
235      *  @return 0 for success, -errno for failure.
236      */
237     int writeChannelVolatileData();
238 
239   private:
240     uint32_t signalFlag = 0;
241     std::unique_ptr<boost::interprocess::named_recursive_mutex> channelMutex{
242         nullptr};
243     std::array<ChannelProperties, maxIpmiChannels> channelData;
244     std::time_t nvFileLastUpdatedTime;
245     std::time_t voltFileLastUpdatedTime;
246     boost::interprocess::file_lock mutexCleanupLock;
247     sdbusplus::bus::bus bus;
248     bool signalHndlrObjectState = false;
249     boost::interprocess::file_lock sigHndlrLock;
250 
251     /** @brief function to initialize persistent channel configuration
252      *
253      */
254     void initChannelPersistData();
255 
256     /** @brief function to set default channel configuration based on channel
257      * number
258      *
259      *  @param[in] chNum - channel number
260      *  @param[in] chName - channel name
261      */
262     void setDefaultChannelConfig(const uint8_t chNum,
263                                  const std::string& chName);
264 
265     /** @brief function to load all channel configuration
266      *
267      *  @return 0 for success, -errno for failure.
268      */
269     int loadChannelConfig();
270 
271     /** @brief function to read persistent channel data
272      *
273      *  @return 0 for success, -errno for failure.
274      */
275     int readChannelPersistData();
276 
277     /** @brief function to read volatile channel data
278      *
279      *  @return 0 for success, -errno for failure.
280      */
281     int readChannelVolatileData();
282 
283     /** @brief function to check and reload persistent channel data
284      *
285      *  @return 0 for success, -errno for failure.
286      */
287     int checkAndReloadNVData();
288 
289     /** @brief function to check and reload volatile channel data
290      *
291      *  @return 0 for success, -errno for failure.
292      */
293     int checkAndReloadVolatileData();
294 
295     /** @brief function to sync channel privilege with system network channel
296      * privilege
297      *
298      *  @return 0 for success, -errno for failure.
299      */
300     int syncNetworkChannelConfig();
301 
302     /** @brief function to set D-Bus property value
303      *
304      *  @param[in] service - service name
305      *  @param[in] objPath - object path
306      *  @param[in] interface - interface
307      *  @param[in] property - property name
308      *  @param[in] value - property value
309      *
310      *  @return 0 for success, -errno for failure.
311      */
312     int setDbusProperty(const std::string& service, const std::string& objPath,
313                         const std::string& interface,
314                         const std::string& property, const DbusVariant& value);
315 
316     /** @brief function to get D-Bus property value
317      *
318      *  @param[in] service - service name
319      *  @param[in] objPath - object path
320      *  @param[in] interface - interface
321      *  @param[in] property - property name
322      *  @param[out] value - property value
323      *
324      *  @return 0 for success, -errno for failure.
325      */
326     int getDbusProperty(const std::string& service, const std::string& objPath,
327                         const std::string& interface,
328                         const std::string& property, DbusVariant& value);
329 
330     /** @brief function to read json config file
331      *
332      *  @param[in] configFile - configuration file name
333      *
334      *  @return Json object
335      */
336     Json readJsonFile(const std::string& configFile);
337 
338     /** @brief function to write json config file
339      *
340      *  @param[in] configFile - configuration file name
341      *  @param[in] jsonData - json object
342      *
343      *  @return 0 for success, -errno for failure.
344      */
345     int writeJsonFile(const std::string& configFile, const Json& jsonData);
346 
347     /** @brief function to convert system access mode to Channel access mode
348      * type
349      *
350      *  @param[in] mode - access mode in string
351      *
352      *  @return Channel access mode.
353      */
354     EChannelAccessMode convertToAccessModeIndex(const std::string& mode);
355 
356     /** @brief function to convert access mode value to string
357      *
358      *  @param[in] value - acess mode value
359      *
360      *  @return access mode in string
361      */
362     std::string convertToAccessModeString(const uint8_t value);
363 
364     /** @brief function to convert privilege value to string
365      *
366      *  @param[in] value - privilege value
367      *
368      *  @return privilege in string
369      */
370     std::string convertToPrivLimitString(const uint8_t value);
371 
372     /** @brief function to convert session support string to value type
373      *
374      *  @param[in] value - session support type in string
375      *
376      *  @return support session type
377      */
378     EChannelSessSupported
379         convertToSessionSupportIndex(const std::string& value);
380 
381     /** @brief function to convert medium type string to value type
382      *
383      *  @param[in] value - medium type in string
384      *
385      *  @return channel medium type
386      */
387     EChannelMediumType convertToMediumTypeIndex(const std::string& value);
388 
389     /** @brief function to convert protocol type string to value type
390      *
391      *  @param[in] value - protocol type in string
392      *
393      *  @return channel protocol  type
394      */
395     EChannelProtocolType convertToProtocolTypeIndex(const std::string& value);
396 
397     /** @brief function to convert channel name to the IPMI channel number.
398      *
399      *  @param[in] chName - the channel name defined in the JSON input file
400      *  (i.e. LAN1)
401      *
402      *  @return IPMI channel number
403      */
404     int convertToChannelNumberFromChannelName(const std::string& chName);
405 
406     /** @brief function to handle Channel access property update through the
407      * D-Bus handler.
408      *
409      *  @param[in] path - D-Bus path to the network element (i.e. eth0)
410      *  @param[in] chProperties - D-Bus channel properties
411      */
412     void processChAccessPropChange(const std::string& path,
413                                    const DbusChObjProperties& chProperties);
414 
415     /** @brief function to retrieve last modification time for the named file
416      *
417      *  @param[in] fileName - the name of the file for which to acquire
418      *  timestamp data
419      *
420      *  @return time the file was last modified
421      */
422     std::time_t getUpdatedFileTime(const std::string& fileName);
423 
424     /** @brief function to convert the DBus path to a network channel name
425      *
426      *  @param[in] path - The DBus path to the device
427      *
428      *  @return network channel name (i.e. eth0)
429      */
430     std::string getChannelNameFromPath(const std::string& path);
431 };
432 
433 } // namespace ipmi
434