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