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