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     bool isManagementNIC;
68 };
69 
70 class ChannelConfig;
71 
72 ChannelConfig& getChannelConfigObject();
73 
74 class ChannelConfig
75 {
76   public:
77     ChannelConfig(const ChannelConfig&) = delete;
78     ChannelConfig& operator=(const ChannelConfig&) = delete;
79     ChannelConfig(ChannelConfig&&) = delete;
80     ChannelConfig& operator=(ChannelConfig&&) = delete;
81 
82     ~ChannelConfig();
83     ChannelConfig();
84 
85     /** @brief determines valid channel
86      *
87      *  @param[in] chNum - channel number
88      *
89      *  @return true if valid, false otherwise
90      */
91     bool isValidChannel(const uint8_t chNum);
92 
93     /** @brief determines valid authentication type
94      *
95      *  @param[in] chNum - channel number
96      *  @param[in] authType - authentication type
97      *
98      *  @return true if valid, false otherwise
99      */
100     bool isValidAuthType(const uint8_t chNum, const EAuthType& authType);
101 
102     /** @brief function to get channel name from channel number
103      *
104      *  @param[in] chNum - channel number index
105      *
106      *  @return network channel interface name
107      */
108     std::string getChannelName(const uint8_t chNum);
109 
110     /** @brief function to get channel number from channel name
111      *
112      *  @param[in] chName - channel name
113      *
114      *  @return network channel interface number
115      */
116 
117     uint8_t getChannelByName(const std::string& chName)
118     {
119         return convertToChannelNumberFromChannelName(chName);
120     }
121 
122     /** @brief determines supported session type of a channel
123      *
124      *  @param[in] chNum - channel number
125      *
126      *  @return EChannelSessSupported - supported session type
127      */
128     EChannelSessSupported getChannelSessionSupport(const uint8_t chNum);
129 
130     /** @brief determines number of active sessions on a channel
131      *
132      *  @param[in] chNum - channel number
133      *
134      *  @return numer of active sessions
135      */
136     int getChannelActiveSessions(const uint8_t chNum);
137 
138     /** @brief determines maximum transfer size for a channel
139      *
140      *  @param[in] chNum - channel number
141      *
142      *  @return maximum bytes that can be transferred on this channel
143      */
144     size_t getChannelMaxTransferSize(uint8_t chNum);
145 
146     /** @brief provides channel info details
147      *
148      *  @param[in] chNum - channel number
149      *  @param[out] chInfo - channel info details
150      *
151      *  @return ccSuccess for success, others for failure.
152      */
153     Cc getChannelInfo(const uint8_t chNum, ChannelInfo& chInfo);
154 
155     /** @brief provides channel access data
156      *
157      *  @param[in] chNum - channel number
158      *  @param[out] chAccessData - channel access data
159      *
160      *  @return ccSuccess for success, others for failure.
161      */
162     Cc getChannelAccessData(const uint8_t chNum, ChannelAccess& chAccessData);
163 
164     /** @brief to set channel access data
165      *
166      *  @param[in] chNum - channel number
167      *  @param[in] chAccessData - channel access data
168      *  @param[in] setFlag - flag to indicate updatable fields
169      *
170      *  @return ccSuccess for success, others for failure.
171      */
172     Cc setChannelAccessData(const uint8_t chNum,
173                             const ChannelAccess& chAccessData,
174                             const uint8_t setFlag);
175 
176     /** @brief to get channel access data persistent data
177      *
178      *  @param[in] chNum - channel number
179      *  @param[out] chAccessData - channel access data
180      *
181      *  @return ccSuccess for success, others for failure.
182      */
183     Cc getChannelAccessPersistData(const uint8_t chNum,
184                                    ChannelAccess& chAccessData);
185 
186     /** @brief to set channel access data persistent data
187      *
188      *  @param[in] chNum - channel number
189      *  @param[in] chAccessData - channel access data
190      *  @param[in] setFlag - flag to indicate updatable fields
191      *
192      *  @return ccSuccess for success, others for failure.
193      */
194     Cc setChannelAccessPersistData(const uint8_t chNum,
195                                    const ChannelAccess& chAccessData,
196                                    const uint8_t setFlag);
197 
198     /** @brief provides supported authentication type for the channel
199      *
200      *  @param[in] chNum - channel number
201      *  @param[out] authTypeSupported - supported authentication type
202      *
203      *  @return ccSuccess for success, others for failure.
204      */
205     Cc getChannelAuthTypeSupported(const uint8_t chNum,
206                                    uint8_t& authTypeSupported);
207 
208     /** @brief provides enabled authentication type for the channel
209      *
210      *  @param[in] chNum - channel number
211      *  @param[in] priv - privilege
212      *  @param[out] authType - enabled authentication type
213      *
214      *  @return ccSuccess for success, others for failure.
215      */
216     Cc getChannelEnabledAuthType(const uint8_t chNum, 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     /** @brief Returns the IPMI channel ID authorized to push IPMI privilege
240      * changes to phosphor-user-manager. Any channel access changes made on
241      * any other channel are ignored.
242      *
243      *  @return IPMI channel ID as defined in channel_config.json
244      */
245     uint8_t getManagementNICID();
246 
247   private:
248     uint32_t signalFlag = 0;
249     std::unique_ptr<boost::interprocess::named_recursive_mutex> channelMutex{
250         nullptr};
251     std::array<ChannelProperties, maxIpmiChannels> channelData;
252     std::time_t nvFileLastUpdatedTime;
253     std::time_t voltFileLastUpdatedTime;
254     boost::interprocess::file_lock mutexCleanupLock;
255     sdbusplus::bus_t bus;
256     bool signalHndlrObjectState = false;
257     boost::interprocess::file_lock sigHndlrLock;
258 
259     /** @brief function to initialize persistent channel configuration
260      *
261      */
262     void initChannelPersistData();
263 
264     /** @brief function to set default channel configuration based on channel
265      * number
266      *
267      *  @param[in] chNum - channel number
268      *  @param[in] chName - channel name
269      */
270     void setDefaultChannelConfig(const uint8_t chNum,
271                                  const std::string& chName);
272 
273     /** @brief function to load all channel configuration
274      *
275      *  @return 0 for success, -errno for failure.
276      */
277     int loadChannelConfig();
278 
279     /** @brief function to read persistent channel data
280      *
281      *  @return 0 for success, -errno for failure.
282      */
283     int readChannelPersistData();
284 
285     /** @brief function to read volatile channel data
286      *
287      *  @return 0 for success, -errno for failure.
288      */
289     int readChannelVolatileData();
290 
291     /** @brief function to check and reload persistent channel data
292      *
293      *  @return 0 for success, -errno for failure.
294      */
295     int checkAndReloadNVData();
296 
297     /** @brief function to check and reload volatile channel data
298      *
299      *  @return 0 for success, -errno for failure.
300      */
301     int checkAndReloadVolatileData();
302 
303     /** @brief function to sync channel privilege with system network channel
304      * privilege
305      *
306      *  @return 0 for success, -errno for failure.
307      */
308     int syncNetworkChannelConfig();
309 
310     /** @brief function to set D-Bus property value
311      *
312      *  @param[in] service - service name
313      *  @param[in] objPath - object path
314      *  @param[in] interface - interface
315      *  @param[in] property - property name
316      *  @param[in] value - property value
317      *
318      *  @return 0 for success, -errno for failure.
319      */
320     int setDbusProperty(const std::string& service, const std::string& objPath,
321                         const std::string& interface,
322                         const std::string& property, const DbusVariant& value);
323 
324     /** @brief function to get D-Bus property value
325      *
326      *  @param[in] service - service name
327      *  @param[in] objPath - object path
328      *  @param[in] interface - interface
329      *  @param[in] property - property name
330      *  @param[out] value - property value
331      *
332      *  @return 0 for success, -errno for failure.
333      */
334     int getDbusProperty(const std::string& service, const std::string& objPath,
335                         const std::string& interface,
336                         const std::string& property, DbusVariant& value);
337 
338     /** @brief function to read json config file
339      *
340      *  @param[in] configFile - configuration file name
341      *
342      *  @return Json object
343      */
344     Json readJsonFile(const std::string& configFile);
345 
346     /** @brief function to write json config file
347      *
348      *  @param[in] configFile - configuration file name
349      *  @param[in] jsonData - json object
350      *
351      *  @return 0 for success, -errno for failure.
352      */
353     int writeJsonFile(const std::string& configFile, const Json& jsonData);
354 
355     /** @brief function to convert system access mode to Channel access mode
356      * type
357      *
358      *  @param[in] mode - access mode in string
359      *
360      *  @return Channel access mode.
361      */
362     EChannelAccessMode convertToAccessModeIndex(const std::string& mode);
363 
364     /** @brief function to convert access mode value to string
365      *
366      *  @param[in] value - acess mode value
367      *
368      *  @return access mode in string
369      */
370     std::string convertToAccessModeString(const uint8_t value);
371 
372     /** @brief function to convert privilege value to string
373      *
374      *  @param[in] value - privilege value
375      *
376      *  @return privilege in string
377      */
378     std::string convertToPrivLimitString(const uint8_t value);
379 
380     /** @brief function to convert session support string to value type
381      *
382      *  @param[in] value - session support type in string
383      *
384      *  @return support session type
385      */
386     EChannelSessSupported
387         convertToSessionSupportIndex(const std::string& value);
388 
389     /** @brief function to convert medium type string to value type
390      *
391      *  @param[in] value - medium type in string
392      *
393      *  @return channel medium type
394      */
395     EChannelMediumType convertToMediumTypeIndex(const std::string& value);
396 
397     /** @brief function to convert protocol type string to value type
398      *
399      *  @param[in] value - protocol type in string
400      *
401      *  @return channel protocol  type
402      */
403     EChannelProtocolType convertToProtocolTypeIndex(const std::string& value);
404 
405     /** @brief function to convert channel name to the IPMI channel number.
406      *
407      *  @param[in] chName - the channel name defined in the JSON input file
408      *  (i.e. LAN1)
409      *
410      *  @return IPMI channel number
411      */
412     int convertToChannelNumberFromChannelName(const std::string& chName);
413 
414     /** @brief function to handle Channel access property update through the
415      * D-Bus handler.
416      *
417      *  @param[in] path - D-Bus path to the network element (i.e. eth0)
418      *  @param[in] chProperties - D-Bus channel properties
419      */
420     void processChAccessPropChange(const std::string& path,
421                                    const DbusChObjProperties& chProperties);
422 
423     /** @brief function to retrieve last modification time for the named file
424      *
425      *  @param[in] fileName - the name of the file for which to acquire
426      *  timestamp data
427      *
428      *  @return time the file was last modified
429      */
430     std::time_t getUpdatedFileTime(const std::string& fileName);
431 
432     /** @brief function to convert the DBus path to a network channel name
433      *
434      *  @param[in] path - The DBus path to the device
435      *
436      *  @return network channel name (i.e. eth0)
437      */
438     std::string getChannelNameFromPath(const std::string& path);
439 };
440 
441 } // namespace ipmi
442