| AppaRao Puli | 071f3f2 | 2018-05-24 16:45:30 +0530 | [diff] [blame^] | 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 | #include "channel_mgmt.hpp" | 
|  | 18 |  | 
|  | 19 | #include "apphandler.hpp" | 
|  | 20 |  | 
|  | 21 | #include <sys/stat.h> | 
|  | 22 | #include <unistd.h> | 
|  | 23 |  | 
|  | 24 | #include <boost/interprocess/sync/scoped_lock.hpp> | 
|  | 25 | #include <cerrno> | 
|  | 26 | #include <experimental/filesystem> | 
|  | 27 | #include <fstream> | 
|  | 28 | #include <phosphor-logging/log.hpp> | 
|  | 29 | #include <unordered_map> | 
|  | 30 |  | 
|  | 31 | namespace ipmi | 
|  | 32 | { | 
|  | 33 |  | 
|  | 34 | using namespace phosphor::logging; | 
|  | 35 |  | 
|  | 36 | static constexpr const char* channelAccessDefaultFilename = | 
|  | 37 | "/usr/share/ipmi-providers/channel_access.json"; | 
|  | 38 | static constexpr const char* channelConfigDefaultFilename = | 
|  | 39 | "/usr/share/ipmi-providers/channel_config.json"; | 
|  | 40 | static constexpr const char* channelNvDataFilename = | 
|  | 41 | "/var/lib/ipmi/channel_access_nv.json"; | 
|  | 42 | static constexpr const char* channelVolatileDataFilename = | 
|  | 43 | "/run/ipmi/channel_access_volatile.json"; | 
|  | 44 |  | 
|  | 45 | // STRING DEFINES: Should sync with key's in JSON | 
|  | 46 | static constexpr const char* nameString = "name"; | 
|  | 47 | static constexpr const char* isValidString = "is_valid"; | 
|  | 48 | static constexpr const char* activeSessionsString = "active_sessions"; | 
|  | 49 | static constexpr const char* channelInfoString = "channel_info"; | 
|  | 50 | static constexpr const char* mediumTypeString = "medium_type"; | 
|  | 51 | static constexpr const char* protocolTypeString = "protocol_type"; | 
|  | 52 | static constexpr const char* sessionSupportedString = "session_supported"; | 
|  | 53 | static constexpr const char* isIpmiString = "is_ipmi"; | 
|  | 54 | static constexpr const char* authTypeSupportedString = "auth_type_supported"; | 
|  | 55 | static constexpr const char* accessModeString = "access_mode"; | 
|  | 56 | static constexpr const char* userAuthDisabledString = "user_auth_disabled"; | 
|  | 57 | static constexpr const char* perMsgAuthDisabledString = "per_msg_auth_disabled"; | 
|  | 58 | static constexpr const char* alertingDisabledString = "alerting_disabled"; | 
|  | 59 | static constexpr const char* privLimitString = "priv_limit"; | 
|  | 60 | static constexpr const char* authTypeEnabledString = "auth_type_enabled"; | 
|  | 61 |  | 
|  | 62 | // Default values | 
|  | 63 | static constexpr const char* defaultChannelName = "RESERVED"; | 
|  | 64 | static constexpr const uint8_t defaultMediumType = | 
|  | 65 | static_cast<uint8_t>(EChannelMediumType::reserved); | 
|  | 66 | static constexpr const uint8_t defaultProtocolType = | 
|  | 67 | static_cast<uint8_t>(EChannelProtocolType::reserved); | 
|  | 68 | static constexpr const uint8_t defaultSessionSupported = | 
|  | 69 | static_cast<uint8_t>(EChannelSessSupported::none); | 
|  | 70 | static constexpr const uint8_t defaultAuthType = | 
|  | 71 | static_cast<uint8_t>(EAuthType::none); | 
|  | 72 | static constexpr const bool defaultIsIpmiState = false; | 
|  | 73 |  | 
|  | 74 | // String mappings use in JSON config file | 
|  | 75 | static std::unordered_map<std::string, EChannelMediumType> mediumTypeMap = { | 
|  | 76 | {"reserved", EChannelMediumType::reserved}, | 
|  | 77 | {"ipmb", EChannelMediumType::ipmb}, | 
|  | 78 | {"icmb-v1.0", EChannelMediumType::icmbV10}, | 
|  | 79 | {"icmb-v0.9", EChannelMediumType::icmbV09}, | 
|  | 80 | {"lan-802.3", EChannelMediumType::lan8032}, | 
|  | 81 | {"serial", EChannelMediumType::serial}, | 
|  | 82 | {"other-lan", EChannelMediumType::otherLan}, | 
|  | 83 | {"pci-smbus", EChannelMediumType::pciSmbus}, | 
|  | 84 | {"smbus-v1.0", EChannelMediumType::smbusV11}, | 
|  | 85 | {"smbus-v2.0", EChannelMediumType::smbusV20}, | 
|  | 86 | {"usb-1x", EChannelMediumType::usbV1x}, | 
|  | 87 | {"usb-2x", EChannelMediumType::usbV2x}, | 
|  | 88 | {"system-interface", EChannelMediumType::systemInterface}, | 
|  | 89 | {"oem", EChannelMediumType::oem}, | 
|  | 90 | {"unknown", EChannelMediumType::unknown}}; | 
|  | 91 |  | 
|  | 92 | static std::unordered_map<std::string, EChannelProtocolType> protocolTypeMap = { | 
|  | 93 | {"na", EChannelProtocolType::na}, | 
|  | 94 | {"ipmb-1.0", EChannelProtocolType::ipmbV10}, | 
|  | 95 | {"icmb-2.0", EChannelProtocolType::icmbV11}, | 
|  | 96 | {"reserved", EChannelProtocolType::reserved}, | 
|  | 97 | {"ipmi-smbus", EChannelProtocolType::ipmiSmbus}, | 
|  | 98 | {"kcs", EChannelProtocolType::kcs}, | 
|  | 99 | {"smic", EChannelProtocolType::smic}, | 
|  | 100 | {"bt-10", EChannelProtocolType::bt10}, | 
|  | 101 | {"bt-15", EChannelProtocolType::bt15}, | 
|  | 102 | {"tmode", EChannelProtocolType::tMode}, | 
|  | 103 | {"oem", EChannelProtocolType::oem}}; | 
|  | 104 |  | 
|  | 105 | static std::array<std::string, 4> accessModeList = { | 
|  | 106 | "disabled", "pre-boot", "always_available", "shared"}; | 
|  | 107 |  | 
|  | 108 | static std::array<std::string, 4> sessionSupportList = { | 
|  | 109 | "session-less", "single-session", "multi-session", "session-based"}; | 
|  | 110 |  | 
|  | 111 | static std::array<std::string, PRIVILEGE_OEM + 1> privList = { | 
|  | 112 | "priv-reserved", "priv-callback", "priv-user", | 
|  | 113 | "priv-operator", "priv-admin",    "priv-oem"}; | 
|  | 114 |  | 
|  | 115 | ChannelConfig& getChannelConfigObject() | 
|  | 116 | { | 
|  | 117 | static ChannelConfig channelConfig; | 
|  | 118 | return channelConfig; | 
|  | 119 | } | 
|  | 120 |  | 
|  | 121 | ChannelConfig::ChannelConfig() : bus(ipmid_get_sd_bus_connection()) | 
|  | 122 | { | 
|  | 123 | std::ofstream mutexCleanUpFile; | 
|  | 124 | mutexCleanUpFile.open(ipmiChMutexCleanupLockFile, | 
|  | 125 | std::ofstream::out | std::ofstream::app); | 
|  | 126 | if (!mutexCleanUpFile.good()) | 
|  | 127 | { | 
|  | 128 | log<level::DEBUG>("Unable to open mutex cleanup file"); | 
|  | 129 | return; | 
|  | 130 | } | 
|  | 131 | mutexCleanUpFile.close(); | 
|  | 132 | mutexCleanupLock = | 
|  | 133 | boost::interprocess::file_lock(ipmiChMutexCleanupLockFile); | 
|  | 134 | if (mutexCleanupLock.try_lock()) | 
|  | 135 | { | 
|  | 136 | boost::interprocess::named_recursive_mutex::remove(ipmiChannelMutex); | 
|  | 137 | channelMutex = | 
|  | 138 | std::make_unique<boost::interprocess::named_recursive_mutex>( | 
|  | 139 | boost::interprocess::open_or_create, ipmiChannelMutex); | 
|  | 140 | mutexCleanupLock.lock_sharable(); | 
|  | 141 | } | 
|  | 142 | else | 
|  | 143 | { | 
|  | 144 | mutexCleanupLock.lock_sharable(); | 
|  | 145 | channelMutex = | 
|  | 146 | std::make_unique<boost::interprocess::named_recursive_mutex>( | 
|  | 147 | boost::interprocess::open_or_create, ipmiChannelMutex); | 
|  | 148 | } | 
|  | 149 |  | 
|  | 150 | initChannelPersistData(); | 
|  | 151 | } | 
|  | 152 |  | 
|  | 153 | bool ChannelConfig::isValidChannel(const uint8_t& chNum) | 
|  | 154 | { | 
|  | 155 | if (chNum > maxIpmiChannels) | 
|  | 156 | { | 
|  | 157 | log<level::DEBUG>("Invalid channel ID - Out of range"); | 
|  | 158 | return false; | 
|  | 159 | } | 
|  | 160 |  | 
|  | 161 | if (channelData[chNum].isChValid == false) | 
|  | 162 | { | 
|  | 163 | log<level::DEBUG>("Channel is not valid"); | 
|  | 164 | return false; | 
|  | 165 | } | 
|  | 166 |  | 
|  | 167 | return true; | 
|  | 168 | } | 
|  | 169 |  | 
|  | 170 | EChannelSessSupported | 
|  | 171 | ChannelConfig::getChannelSessionSupport(const uint8_t& chNum) | 
|  | 172 | { | 
|  | 173 | EChannelSessSupported chSessSupport = | 
|  | 174 | (EChannelSessSupported)channelData[chNum].chInfo.sessionSupported; | 
|  | 175 | return chSessSupport; | 
|  | 176 | } | 
|  | 177 |  | 
|  | 178 | bool ChannelConfig::isValidAuthType(const uint8_t& chNum, | 
|  | 179 | const EAuthType& authType) | 
|  | 180 | { | 
|  | 181 | if ((authType < EAuthType::md2) || (authType > EAuthType::oem)) | 
|  | 182 | { | 
|  | 183 | log<level::DEBUG>("Invalid authentication type"); | 
|  | 184 | return false; | 
|  | 185 | } | 
|  | 186 |  | 
|  | 187 | uint8_t authTypeSupported = channelData[chNum].chInfo.authTypeSupported; | 
|  | 188 | if (!(authTypeSupported & (1 << static_cast<uint8_t>(authType)))) | 
|  | 189 | { | 
|  | 190 | log<level::DEBUG>("Authentication type is not supported."); | 
|  | 191 | return false; | 
|  | 192 | } | 
|  | 193 |  | 
|  | 194 | return true; | 
|  | 195 | } | 
|  | 196 |  | 
|  | 197 | int ChannelConfig::getChannelActiveSessions(const uint8_t& chNum) | 
|  | 198 | { | 
|  | 199 | // TODO: TEMPORARY FIX | 
|  | 200 | // Channels active session count is managed separatly | 
|  | 201 | // by monitoring channel session which includes LAN and | 
|  | 202 | // RAKP layer changes. This will be updated, once the | 
|  | 203 | // authentication part is implemented. | 
|  | 204 | return channelData[chNum].activeSessCount; | 
|  | 205 | } | 
|  | 206 |  | 
|  | 207 | ipmi_ret_t ChannelConfig::getChannelInfo(const uint8_t& chNum, | 
|  | 208 | ChannelInfo& chInfo) | 
|  | 209 | { | 
|  | 210 | if (!isValidChannel(chNum)) | 
|  | 211 | { | 
|  | 212 | log<level::DEBUG>("Invalid channel"); | 
|  | 213 | return IPMI_CC_INVALID_FIELD_REQUEST; | 
|  | 214 | } | 
|  | 215 |  | 
|  | 216 | std::copy_n(reinterpret_cast<uint8_t*>(&channelData[chNum].chInfo), | 
|  | 217 | sizeof(channelData[chNum].chInfo), | 
|  | 218 | reinterpret_cast<uint8_t*>(&chInfo)); | 
|  | 219 |  | 
|  | 220 | return IPMI_CC_OK; | 
|  | 221 | } | 
|  | 222 |  | 
|  | 223 | ipmi_ret_t ChannelConfig::getChannelAccessData(const uint8_t& chNum, | 
|  | 224 | ChannelAccess& chAccessData) | 
|  | 225 | { | 
|  | 226 | if (!isValidChannel(chNum)) | 
|  | 227 | { | 
|  | 228 | log<level::DEBUG>("Invalid channel"); | 
|  | 229 | return IPMI_CC_INVALID_FIELD_REQUEST; | 
|  | 230 | } | 
|  | 231 |  | 
|  | 232 | if (getChannelSessionSupport(chNum) == EChannelSessSupported::none) | 
|  | 233 | { | 
|  | 234 | log<level::DEBUG>("Session-less channel doesn't have access data."); | 
|  | 235 | return IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL; | 
|  | 236 | } | 
|  | 237 |  | 
|  | 238 | if (checkAndReloadVolatileData() != 0) | 
|  | 239 | { | 
|  | 240 | return IPMI_CC_UNSPECIFIED_ERROR; | 
|  | 241 | } | 
|  | 242 |  | 
|  | 243 | std::copy_n( | 
|  | 244 | reinterpret_cast<uint8_t*>(&channelData[chNum].chAccess.chVolatileData), | 
|  | 245 | sizeof(channelData[chNum].chAccess.chVolatileData), | 
|  | 246 | reinterpret_cast<uint8_t*>(&chAccessData)); | 
|  | 247 |  | 
|  | 248 | return IPMI_CC_OK; | 
|  | 249 | } | 
|  | 250 |  | 
|  | 251 | ipmi_ret_t | 
|  | 252 | ChannelConfig::setChannelAccessData(const uint8_t& chNum, | 
|  | 253 | const ChannelAccess& chAccessData, | 
|  | 254 | const uint8_t& setFlag) | 
|  | 255 | { | 
|  | 256 | if (!isValidChannel(chNum)) | 
|  | 257 | { | 
|  | 258 | log<level::DEBUG>("Invalid channel"); | 
|  | 259 | return IPMI_CC_INVALID_FIELD_REQUEST; | 
|  | 260 | } | 
|  | 261 |  | 
|  | 262 | if (getChannelSessionSupport(chNum) == EChannelSessSupported::none) | 
|  | 263 | { | 
|  | 264 | log<level::DEBUG>("Session-less channel doesn't have access data."); | 
|  | 265 | return IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL; | 
|  | 266 | } | 
|  | 267 |  | 
|  | 268 | if ((setFlag & setAccessMode) && | 
|  | 269 | (!isValidAccessMode(chAccessData.accessMode))) | 
|  | 270 | { | 
|  | 271 | log<level::DEBUG>("Invalid access mode specified"); | 
|  | 272 | return IPMI_CC_INVALID_FIELD_REQUEST; | 
|  | 273 | } | 
|  | 274 |  | 
|  | 275 | boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> | 
|  | 276 | channelLock{*channelMutex}; | 
|  | 277 |  | 
|  | 278 | if (checkAndReloadVolatileData() != 0) | 
|  | 279 | { | 
|  | 280 | return IPMI_CC_UNSPECIFIED_ERROR; | 
|  | 281 | } | 
|  | 282 |  | 
|  | 283 | if (setFlag & setAccessMode) | 
|  | 284 | { | 
|  | 285 | channelData[chNum].chAccess.chVolatileData.accessMode = | 
|  | 286 | chAccessData.accessMode; | 
|  | 287 | } | 
|  | 288 | if (setFlag & setUserAuthEnabled) | 
|  | 289 | { | 
|  | 290 | channelData[chNum].chAccess.chVolatileData.userAuthDisabled = | 
|  | 291 | chAccessData.userAuthDisabled; | 
|  | 292 | } | 
|  | 293 | if (setFlag & setMsgAuthEnabled) | 
|  | 294 | { | 
|  | 295 | channelData[chNum].chAccess.chVolatileData.perMsgAuthDisabled = | 
|  | 296 | chAccessData.perMsgAuthDisabled; | 
|  | 297 | } | 
|  | 298 | if (setFlag & setAlertingEnabled) | 
|  | 299 | { | 
|  | 300 | channelData[chNum].chAccess.chVolatileData.alertingDisabled = | 
|  | 301 | chAccessData.alertingDisabled; | 
|  | 302 | } | 
|  | 303 | if (setFlag & setPrivLimit) | 
|  | 304 | { | 
|  | 305 | channelData[chNum].chAccess.chVolatileData.privLimit = | 
|  | 306 | chAccessData.privLimit; | 
|  | 307 | } | 
|  | 308 |  | 
|  | 309 | // Write Volatile data to file | 
|  | 310 | if (writeChannelVolatileData() != 0) | 
|  | 311 | { | 
|  | 312 | log<level::DEBUG>("Failed to update the channel volatile data"); | 
|  | 313 | return IPMI_CC_UNSPECIFIED_ERROR; | 
|  | 314 | } | 
|  | 315 | return IPMI_CC_OK; | 
|  | 316 | } | 
|  | 317 |  | 
|  | 318 | ipmi_ret_t | 
|  | 319 | ChannelConfig::getChannelAccessPersistData(const uint8_t& chNum, | 
|  | 320 | ChannelAccess& chAccessData) | 
|  | 321 | { | 
|  | 322 | if (!isValidChannel(chNum)) | 
|  | 323 | { | 
|  | 324 | log<level::DEBUG>("Invalid channel"); | 
|  | 325 | return IPMI_CC_INVALID_FIELD_REQUEST; | 
|  | 326 | } | 
|  | 327 |  | 
|  | 328 | if (getChannelSessionSupport(chNum) == EChannelSessSupported::none) | 
|  | 329 | { | 
|  | 330 | log<level::DEBUG>("Session-less channel doesn't have access data."); | 
|  | 331 | return IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL; | 
|  | 332 | } | 
|  | 333 |  | 
|  | 334 | if (checkAndReloadNVData() != 0) | 
|  | 335 | { | 
|  | 336 | return IPMI_CC_UNSPECIFIED_ERROR; | 
|  | 337 | } | 
|  | 338 |  | 
|  | 339 | std::copy_n(reinterpret_cast<uint8_t*>( | 
|  | 340 | &channelData[chNum].chAccess.chNonVolatileData), | 
|  | 341 | sizeof(channelData[chNum].chAccess.chNonVolatileData), | 
|  | 342 | reinterpret_cast<uint8_t*>(&chAccessData)); | 
|  | 343 |  | 
|  | 344 | return IPMI_CC_OK; | 
|  | 345 | } | 
|  | 346 |  | 
|  | 347 | ipmi_ret_t ChannelConfig::setChannelAccessPersistData( | 
|  | 348 | const uint8_t& chNum, const ChannelAccess& chAccessData, | 
|  | 349 | const uint8_t& setFlag) | 
|  | 350 | { | 
|  | 351 | if (!isValidChannel(chNum)) | 
|  | 352 | { | 
|  | 353 | log<level::DEBUG>("Invalid channel"); | 
|  | 354 | return IPMI_CC_INVALID_FIELD_REQUEST; | 
|  | 355 | } | 
|  | 356 |  | 
|  | 357 | if (getChannelSessionSupport(chNum) == EChannelSessSupported::none) | 
|  | 358 | { | 
|  | 359 | log<level::DEBUG>("Session-less channel doesn't have access data."); | 
|  | 360 | return IPMI_CC_ACTION_NOT_SUPPORTED_FOR_CHANNEL; | 
|  | 361 | } | 
|  | 362 |  | 
|  | 363 | if ((setFlag & setAccessMode) && | 
|  | 364 | (!isValidAccessMode(chAccessData.accessMode))) | 
|  | 365 | { | 
|  | 366 | log<level::DEBUG>("Invalid access mode specified"); | 
|  | 367 | return IPMI_CC_INVALID_FIELD_REQUEST; | 
|  | 368 | } | 
|  | 369 |  | 
|  | 370 | boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> | 
|  | 371 | channelLock{*channelMutex}; | 
|  | 372 |  | 
|  | 373 | if (checkAndReloadNVData() != 0) | 
|  | 374 | { | 
|  | 375 | return IPMI_CC_UNSPECIFIED_ERROR; | 
|  | 376 | } | 
|  | 377 |  | 
|  | 378 | if (setFlag & setAccessMode) | 
|  | 379 | { | 
|  | 380 | channelData[chNum].chAccess.chNonVolatileData.accessMode = | 
|  | 381 | chAccessData.accessMode; | 
|  | 382 | } | 
|  | 383 | if (setFlag & setUserAuthEnabled) | 
|  | 384 | { | 
|  | 385 | channelData[chNum].chAccess.chNonVolatileData.userAuthDisabled = | 
|  | 386 | chAccessData.userAuthDisabled; | 
|  | 387 | } | 
|  | 388 | if (setFlag & setMsgAuthEnabled) | 
|  | 389 | { | 
|  | 390 | channelData[chNum].chAccess.chNonVolatileData.perMsgAuthDisabled = | 
|  | 391 | chAccessData.perMsgAuthDisabled; | 
|  | 392 | } | 
|  | 393 | if (setFlag & setAlertingEnabled) | 
|  | 394 | { | 
|  | 395 | channelData[chNum].chAccess.chNonVolatileData.alertingDisabled = | 
|  | 396 | chAccessData.alertingDisabled; | 
|  | 397 | } | 
|  | 398 | if (setFlag & setPrivLimit) | 
|  | 399 | { | 
|  | 400 | channelData[chNum].chAccess.chNonVolatileData.privLimit = | 
|  | 401 | chAccessData.privLimit; | 
|  | 402 | } | 
|  | 403 |  | 
|  | 404 | // Write persistent data to file | 
|  | 405 | if (writeChannelPersistData() != 0) | 
|  | 406 | { | 
|  | 407 | log<level::DEBUG>("Failed to update the presist data file"); | 
|  | 408 | return IPMI_CC_UNSPECIFIED_ERROR; | 
|  | 409 | } | 
|  | 410 | return IPMI_CC_OK; | 
|  | 411 | } | 
|  | 412 |  | 
|  | 413 | ipmi_ret_t | 
|  | 414 | ChannelConfig::getChannelAuthTypeSupported(const uint8_t& chNum, | 
|  | 415 | uint8_t& authTypeSupported) | 
|  | 416 | { | 
|  | 417 | if (!isValidChannel(chNum)) | 
|  | 418 | { | 
|  | 419 | log<level::DEBUG>("Invalid channel"); | 
|  | 420 | return IPMI_CC_INVALID_FIELD_REQUEST; | 
|  | 421 | } | 
|  | 422 |  | 
|  | 423 | authTypeSupported = channelData[chNum].chInfo.authTypeSupported; | 
|  | 424 | return IPMI_CC_OK; | 
|  | 425 | } | 
|  | 426 |  | 
|  | 427 | ipmi_ret_t ChannelConfig::getChannelEnabledAuthType(const uint8_t& chNum, | 
|  | 428 | const uint8_t& priv, | 
|  | 429 | EAuthType& authType) | 
|  | 430 | { | 
|  | 431 | if (!isValidChannel(chNum)) | 
|  | 432 | { | 
|  | 433 | log<level::DEBUG>("Invalid channel"); | 
|  | 434 | return IPMI_CC_INVALID_FIELD_REQUEST; | 
|  | 435 | } | 
|  | 436 |  | 
|  | 437 | if (getChannelSessionSupport(chNum) == EChannelSessSupported::none) | 
|  | 438 | { | 
|  | 439 | log<level::DEBUG>("Sessionless channel doesn't have access data."); | 
|  | 440 | return IPMI_CC_INVALID_FIELD_REQUEST; | 
|  | 441 | } | 
|  | 442 |  | 
|  | 443 | if (!isValidPrivLimit(priv)) | 
|  | 444 | { | 
|  | 445 | log<level::DEBUG>("Invalid privilege specified."); | 
|  | 446 | return IPMI_CC_INVALID_FIELD_REQUEST; | 
|  | 447 | } | 
|  | 448 |  | 
|  | 449 | // TODO: Hardcoded for now. Need to implement. | 
|  | 450 | authType = EAuthType::none; | 
|  | 451 |  | 
|  | 452 | return IPMI_CC_OK; | 
|  | 453 | } | 
|  | 454 |  | 
|  | 455 | std::time_t ChannelConfig::getUpdatedFileTime(const std::string& fileName) | 
|  | 456 | { | 
|  | 457 | struct stat fileStat; | 
|  | 458 | if (stat(fileName.c_str(), &fileStat) != 0) | 
|  | 459 | { | 
|  | 460 | log<level::DEBUG>("Error in getting last updated time stamp"); | 
|  | 461 | return -EIO; | 
|  | 462 | } | 
|  | 463 | return fileStat.st_mtime; | 
|  | 464 | } | 
|  | 465 |  | 
|  | 466 | EChannelAccessMode | 
|  | 467 | ChannelConfig::convertToAccessModeIndex(const std::string& mode) | 
|  | 468 | { | 
|  | 469 | auto iter = std::find(accessModeList.begin(), accessModeList.end(), mode); | 
|  | 470 | if (iter == accessModeList.end()) | 
|  | 471 | { | 
|  | 472 | log<level::ERR>("Invalid access mode.", | 
|  | 473 | entry("MODE_STR=%s", mode.c_str())); | 
|  | 474 | throw std::invalid_argument("Invalid access mode."); | 
|  | 475 | } | 
|  | 476 |  | 
|  | 477 | return static_cast<EChannelAccessMode>( | 
|  | 478 | std::distance(accessModeList.begin(), iter)); | 
|  | 479 | } | 
|  | 480 |  | 
|  | 481 | std::string ChannelConfig::convertToAccessModeString(const uint8_t& value) | 
|  | 482 | { | 
|  | 483 | if (accessModeList.size() <= value) | 
|  | 484 | { | 
|  | 485 | log<level::ERR>("Invalid access mode.", entry("MODE_IDX=%d", value)); | 
|  | 486 | throw std::invalid_argument("Invalid access mode."); | 
|  | 487 | } | 
|  | 488 |  | 
|  | 489 | return accessModeList.at(value); | 
|  | 490 | } | 
|  | 491 |  | 
|  | 492 | CommandPrivilege | 
|  | 493 | ChannelConfig::convertToPrivLimitIndex(const std::string& value) | 
|  | 494 | { | 
|  | 495 | auto iter = std::find(privList.begin(), privList.end(), value); | 
|  | 496 | if (iter == privList.end()) | 
|  | 497 | { | 
|  | 498 | log<level::ERR>("Invalid privilege.", | 
|  | 499 | entry("PRIV_STR=%s", value.c_str())); | 
|  | 500 | throw std::invalid_argument("Invalid privilege."); | 
|  | 501 | } | 
|  | 502 |  | 
|  | 503 | return static_cast<CommandPrivilege>(std::distance(privList.begin(), iter)); | 
|  | 504 | } | 
|  | 505 |  | 
|  | 506 | std::string ChannelConfig::convertToPrivLimitString(const uint8_t& value) | 
|  | 507 | { | 
|  | 508 | if (privList.size() <= value) | 
|  | 509 | { | 
|  | 510 | log<level::ERR>("Invalid privilege.", entry("PRIV_IDX=%d", value)); | 
|  | 511 | throw std::invalid_argument("Invalid privilege."); | 
|  | 512 | } | 
|  | 513 |  | 
|  | 514 | return privList.at(value); | 
|  | 515 | } | 
|  | 516 |  | 
|  | 517 | EChannelSessSupported | 
|  | 518 | ChannelConfig::convertToSessionSupportIndex(const std::string& value) | 
|  | 519 | { | 
|  | 520 | auto iter = | 
|  | 521 | std::find(sessionSupportList.begin(), sessionSupportList.end(), value); | 
|  | 522 | if (iter == sessionSupportList.end()) | 
|  | 523 | { | 
|  | 524 | log<level::ERR>("Invalid session supported.", | 
|  | 525 | entry("SESS_STR=%s", value.c_str())); | 
|  | 526 | throw std::invalid_argument("Invalid session supported."); | 
|  | 527 | } | 
|  | 528 |  | 
|  | 529 | return static_cast<EChannelSessSupported>( | 
|  | 530 | std::distance(sessionSupportList.begin(), iter)); | 
|  | 531 | } | 
|  | 532 |  | 
|  | 533 | EChannelMediumType | 
|  | 534 | ChannelConfig::convertToMediumTypeIndex(const std::string& value) | 
|  | 535 | { | 
|  | 536 | std::unordered_map<std::string, EChannelMediumType>::iterator it = | 
|  | 537 | mediumTypeMap.find(value); | 
|  | 538 | if (it == mediumTypeMap.end()) | 
|  | 539 | { | 
|  | 540 | log<level::ERR>("Invalid medium type.", | 
|  | 541 | entry("MEDIUM_STR=%s", value.c_str())); | 
|  | 542 | throw std::invalid_argument("Invalid medium type."); | 
|  | 543 | } | 
|  | 544 |  | 
|  | 545 | return static_cast<EChannelMediumType>(it->second); | 
|  | 546 | } | 
|  | 547 |  | 
|  | 548 | EChannelProtocolType | 
|  | 549 | ChannelConfig::convertToProtocolTypeIndex(const std::string& value) | 
|  | 550 | { | 
|  | 551 | std::unordered_map<std::string, EChannelProtocolType>::iterator it = | 
|  | 552 | protocolTypeMap.find(value); | 
|  | 553 | if (it == protocolTypeMap.end()) | 
|  | 554 | { | 
|  | 555 | log<level::ERR>("Invalid protocol type.", | 
|  | 556 | entry("PROTO_STR=%s", value.c_str())); | 
|  | 557 | throw std::invalid_argument("Invalid protocol type."); | 
|  | 558 | } | 
|  | 559 |  | 
|  | 560 | return static_cast<EChannelProtocolType>(it->second); | 
|  | 561 | } | 
|  | 562 |  | 
|  | 563 | Json ChannelConfig::readJsonFile(const std::string& configFile) | 
|  | 564 | { | 
|  | 565 | std::ifstream jsonFile(configFile); | 
|  | 566 | if (!jsonFile.good()) | 
|  | 567 | { | 
|  | 568 | log<level::ERR>("JSON file not found"); | 
|  | 569 | return nullptr; | 
|  | 570 | } | 
|  | 571 |  | 
|  | 572 | Json data = nullptr; | 
|  | 573 | try | 
|  | 574 | { | 
|  | 575 | data = Json::parse(jsonFile, nullptr, false); | 
|  | 576 | } | 
|  | 577 | catch (Json::parse_error& e) | 
|  | 578 | { | 
|  | 579 | log<level::DEBUG>("Corrupted channel config.", | 
|  | 580 | entry("MSG: %s", e.what())); | 
|  | 581 | throw std::runtime_error("Corrupted channel config file"); | 
|  | 582 | } | 
|  | 583 |  | 
|  | 584 | return data; | 
|  | 585 | } | 
|  | 586 |  | 
|  | 587 | int ChannelConfig::writeJsonFile(const std::string& configFile, | 
|  | 588 | const Json& jsonData) | 
|  | 589 | { | 
|  | 590 | std::ofstream jsonFile(configFile); | 
|  | 591 | if (!jsonFile.good()) | 
|  | 592 | { | 
|  | 593 | log<level::ERR>("JSON file not found"); | 
|  | 594 | return -EIO; | 
|  | 595 | } | 
|  | 596 |  | 
|  | 597 | // Write JSON to file | 
|  | 598 | jsonFile << jsonData; | 
|  | 599 |  | 
|  | 600 | jsonFile.flush(); | 
|  | 601 | return 0; | 
|  | 602 | } | 
|  | 603 |  | 
|  | 604 | void ChannelConfig::setDefaultChannelConfig(const uint8_t& chNum, | 
|  | 605 | const std::string& chName) | 
|  | 606 | { | 
|  | 607 | channelData[chNum].chName = chName; | 
|  | 608 | channelData[chNum].chID = chNum; | 
|  | 609 | channelData[chNum].isChValid = false; | 
|  | 610 | channelData[chNum].activeSessCount = 0; | 
|  | 611 |  | 
|  | 612 | channelData[chNum].chInfo.mediumType = defaultMediumType; | 
|  | 613 | channelData[chNum].chInfo.protocolType = defaultProtocolType; | 
|  | 614 | channelData[chNum].chInfo.sessionSupported = defaultSessionSupported; | 
|  | 615 | channelData[chNum].chInfo.isIpmi = defaultIsIpmiState; | 
|  | 616 | channelData[chNum].chInfo.authTypeSupported = defaultAuthType; | 
|  | 617 | } | 
|  | 618 |  | 
|  | 619 | int ChannelConfig::loadChannelConfig() | 
|  | 620 | { | 
|  | 621 | boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> | 
|  | 622 | channelLock{*channelMutex}; | 
|  | 623 |  | 
|  | 624 | Json data = readJsonFile(channelConfigDefaultFilename); | 
|  | 625 | if (data == nullptr) | 
|  | 626 | { | 
|  | 627 | log<level::DEBUG>("Error in opening IPMI Channel data file"); | 
|  | 628 | return -EIO; | 
|  | 629 | } | 
|  | 630 |  | 
|  | 631 | try | 
|  | 632 | { | 
|  | 633 | // Fill in global structure | 
|  | 634 | for (uint8_t chNum = 0; chNum < maxIpmiChannels; chNum++) | 
|  | 635 | { | 
|  | 636 | std::fill(reinterpret_cast<uint8_t*>(&channelData[chNum]), | 
|  | 637 | reinterpret_cast<uint8_t*>(&channelData[chNum]) + | 
|  | 638 | sizeof(ChannelData), | 
|  | 639 | 0); | 
|  | 640 | std::string chKey = std::to_string(chNum); | 
|  | 641 | Json jsonChData = data[chKey].get<Json>(); | 
|  | 642 | if (jsonChData.is_null()) | 
|  | 643 | { | 
|  | 644 | log<level::WARNING>( | 
|  | 645 | "Channel not configured so loading default.", | 
|  | 646 | entry("CHANNEL_NUM:%d", chNum)); | 
|  | 647 | // If user didn't want to configure specific channel (say | 
|  | 648 | // reserved channel), then load that index with default values. | 
|  | 649 | std::string chName(defaultChannelName); | 
|  | 650 | setDefaultChannelConfig(chNum, chName); | 
|  | 651 | } | 
|  | 652 | else | 
|  | 653 | { | 
|  | 654 | std::string chName = jsonChData[nameString].get<std::string>(); | 
|  | 655 | channelData[chNum].chName = chName; | 
|  | 656 | channelData[chNum].chID = chNum; | 
|  | 657 | channelData[chNum].isChValid = | 
|  | 658 | jsonChData[isValidString].get<bool>(); | 
|  | 659 | channelData[chNum].activeSessCount = | 
|  | 660 | jsonChData.value(activeSessionsString, 0); | 
|  | 661 | Json jsonChInfo = jsonChData[channelInfoString].get<Json>(); | 
|  | 662 | if (jsonChInfo.is_null()) | 
|  | 663 | { | 
|  | 664 | log<level::ERR>("Invalid/corrupted channel config file"); | 
|  | 665 | return -EBADMSG; | 
|  | 666 | } | 
|  | 667 | else | 
|  | 668 | { | 
|  | 669 | std::string medTypeStr = | 
|  | 670 | jsonChInfo[mediumTypeString].get<std::string>(); | 
|  | 671 | channelData[chNum].chInfo.mediumType = static_cast<uint8_t>( | 
|  | 672 | convertToMediumTypeIndex(medTypeStr)); | 
|  | 673 | std::string protoTypeStr = | 
|  | 674 | jsonChInfo[protocolTypeString].get<std::string>(); | 
|  | 675 | channelData[chNum].chInfo.protocolType = | 
|  | 676 | static_cast<uint8_t>( | 
|  | 677 | convertToProtocolTypeIndex(protoTypeStr)); | 
|  | 678 | std::string sessStr = | 
|  | 679 | jsonChInfo[sessionSupportedString].get<std::string>(); | 
|  | 680 | channelData[chNum].chInfo.sessionSupported = | 
|  | 681 | static_cast<uint8_t>( | 
|  | 682 | convertToSessionSupportIndex(sessStr)); | 
|  | 683 | channelData[chNum].chInfo.isIpmi = | 
|  | 684 | jsonChInfo[isIpmiString].get<bool>(); | 
|  | 685 | channelData[chNum].chInfo.authTypeSupported = | 
|  | 686 | defaultAuthType; | 
|  | 687 | } | 
|  | 688 | } | 
|  | 689 | } | 
|  | 690 | } | 
|  | 691 | catch (const Json::exception& e) | 
|  | 692 | { | 
|  | 693 | log<level::DEBUG>("Json Exception caught.", entry("MSG:%s", e.what())); | 
|  | 694 | return -EBADMSG; | 
|  | 695 | } | 
|  | 696 | catch (const std::invalid_argument& e) | 
|  | 697 | { | 
|  | 698 | log<level::ERR>("Corrupted config.", entry("MSG:%s", e.what())); | 
|  | 699 | return -EBADMSG; | 
|  | 700 | } | 
|  | 701 |  | 
|  | 702 | return 0; | 
|  | 703 | } | 
|  | 704 |  | 
|  | 705 | int ChannelConfig::readChannelVolatileData() | 
|  | 706 | { | 
|  | 707 | boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> | 
|  | 708 | channelLock{*channelMutex}; | 
|  | 709 |  | 
|  | 710 | Json data = readJsonFile(channelVolatileDataFilename); | 
|  | 711 | if (data == nullptr) | 
|  | 712 | { | 
|  | 713 | log<level::DEBUG>("Error in opening IPMI Channel data file"); | 
|  | 714 | return -EIO; | 
|  | 715 | } | 
|  | 716 |  | 
|  | 717 | try | 
|  | 718 | { | 
|  | 719 | // Fill in global structure | 
|  | 720 | for (auto it = data.begin(); it != data.end(); ++it) | 
|  | 721 | { | 
|  | 722 | std::string chKey = it.key(); | 
|  | 723 | uint8_t chNum = std::stoi(chKey, nullptr, 10); | 
|  | 724 | if ((chNum < 0) || (chNum > maxIpmiChannels)) | 
|  | 725 | { | 
|  | 726 | log<level::DEBUG>( | 
|  | 727 | "Invalid channel access entry in config file"); | 
|  | 728 | throw std::out_of_range("Out of range - channel number"); | 
|  | 729 | } | 
|  | 730 | Json jsonChData = it.value(); | 
|  | 731 | if (!jsonChData.is_null()) | 
|  | 732 | { | 
|  | 733 | std::string accModeStr = | 
|  | 734 | jsonChData[accessModeString].get<std::string>(); | 
|  | 735 | channelData[chNum].chAccess.chVolatileData.accessMode = | 
|  | 736 | static_cast<uint8_t>(convertToAccessModeIndex(accModeStr)); | 
|  | 737 | channelData[chNum].chAccess.chVolatileData.userAuthDisabled = | 
|  | 738 | jsonChData[userAuthDisabledString].get<bool>(); | 
|  | 739 | channelData[chNum].chAccess.chVolatileData.perMsgAuthDisabled = | 
|  | 740 | jsonChData[perMsgAuthDisabledString].get<bool>(); | 
|  | 741 | channelData[chNum].chAccess.chVolatileData.alertingDisabled = | 
|  | 742 | jsonChData[alertingDisabledString].get<bool>(); | 
|  | 743 | std::string privStr = | 
|  | 744 | jsonChData[privLimitString].get<std::string>(); | 
|  | 745 | channelData[chNum].chAccess.chVolatileData.privLimit = | 
|  | 746 | static_cast<uint8_t>(convertToPrivLimitIndex(privStr)); | 
|  | 747 | } | 
|  | 748 | else | 
|  | 749 | { | 
|  | 750 | log<level::ERR>( | 
|  | 751 | "Invalid/corrupted volatile channel access file", | 
|  | 752 | entry("FILE: %s", channelVolatileDataFilename)); | 
|  | 753 | throw std::runtime_error( | 
|  | 754 | "Corrupted volatile channel access file"); | 
|  | 755 | } | 
|  | 756 | } | 
|  | 757 | } | 
|  | 758 | catch (const Json::exception& e) | 
|  | 759 | { | 
|  | 760 | log<level::DEBUG>("Json Exception caught.", entry("MSG:%s", e.what())); | 
|  | 761 | throw std::runtime_error("Corrupted volatile channel access file"); | 
|  | 762 | } | 
|  | 763 | catch (const std::invalid_argument& e) | 
|  | 764 | { | 
|  | 765 | log<level::ERR>("Corrupted config.", entry("MSG:%s", e.what())); | 
|  | 766 | throw std::runtime_error("Corrupted volatile channel access file"); | 
|  | 767 | } | 
|  | 768 |  | 
|  | 769 | // Update the timestamp | 
|  | 770 | voltFileLastUpdatedTime = getUpdatedFileTime(channelVolatileDataFilename); | 
|  | 771 | return 0; | 
|  | 772 | } | 
|  | 773 |  | 
|  | 774 | int ChannelConfig::readChannelPersistData() | 
|  | 775 | { | 
|  | 776 | boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> | 
|  | 777 | channelLock{*channelMutex}; | 
|  | 778 |  | 
|  | 779 | Json data = readJsonFile(channelNvDataFilename); | 
|  | 780 | if (data == nullptr) | 
|  | 781 | { | 
|  | 782 | log<level::DEBUG>("Error in opening IPMI Channel data file"); | 
|  | 783 | return -EIO; | 
|  | 784 | } | 
|  | 785 |  | 
|  | 786 | try | 
|  | 787 | { | 
|  | 788 | // Fill in global structure | 
|  | 789 | for (auto it = data.begin(); it != data.end(); ++it) | 
|  | 790 | { | 
|  | 791 | std::string chKey = it.key(); | 
|  | 792 | uint8_t chNum = std::stoi(chKey, nullptr, 10); | 
|  | 793 | if ((chNum < 0) || (chNum > maxIpmiChannels)) | 
|  | 794 | { | 
|  | 795 | log<level::DEBUG>( | 
|  | 796 | "Invalid channel access entry in config file"); | 
|  | 797 | throw std::out_of_range("Out of range - channel number"); | 
|  | 798 | } | 
|  | 799 | Json jsonChData = it.value(); | 
|  | 800 | if (!jsonChData.is_null()) | 
|  | 801 | { | 
|  | 802 | std::string accModeStr = | 
|  | 803 | jsonChData[accessModeString].get<std::string>(); | 
|  | 804 | channelData[chNum].chAccess.chNonVolatileData.accessMode = | 
|  | 805 | static_cast<uint8_t>(convertToAccessModeIndex(accModeStr)); | 
|  | 806 | channelData[chNum].chAccess.chNonVolatileData.userAuthDisabled = | 
|  | 807 | jsonChData[userAuthDisabledString].get<bool>(); | 
|  | 808 | channelData[chNum] | 
|  | 809 | .chAccess.chNonVolatileData.perMsgAuthDisabled = | 
|  | 810 | jsonChData[perMsgAuthDisabledString].get<bool>(); | 
|  | 811 | channelData[chNum].chAccess.chNonVolatileData.alertingDisabled = | 
|  | 812 | jsonChData[alertingDisabledString].get<bool>(); | 
|  | 813 | std::string privStr = | 
|  | 814 | jsonChData[privLimitString].get<std::string>(); | 
|  | 815 | channelData[chNum].chAccess.chNonVolatileData.privLimit = | 
|  | 816 | static_cast<uint8_t>(convertToPrivLimitIndex(privStr)); | 
|  | 817 | } | 
|  | 818 | else | 
|  | 819 | { | 
|  | 820 | log<level::ERR>("Invalid/corrupted nv channel access file", | 
|  | 821 | entry("FILE:%s", channelNvDataFilename)); | 
|  | 822 | throw std::runtime_error("Corrupted nv channel access file"); | 
|  | 823 | } | 
|  | 824 | } | 
|  | 825 | } | 
|  | 826 | catch (const Json::exception& e) | 
|  | 827 | { | 
|  | 828 | log<level::DEBUG>("Json Exception caught.", entry("MSG:%s", e.what())); | 
|  | 829 | throw std::runtime_error("Corrupted nv channel access file"); | 
|  | 830 | } | 
|  | 831 | catch (const std::invalid_argument& e) | 
|  | 832 | { | 
|  | 833 | log<level::ERR>("Corrupted config.", entry("MSG: %s", e.what())); | 
|  | 834 | throw std::runtime_error("Corrupted nv channel access file"); | 
|  | 835 | } | 
|  | 836 |  | 
|  | 837 | // Update the timestamp | 
|  | 838 | nvFileLastUpdatedTime = getUpdatedFileTime(channelNvDataFilename); | 
|  | 839 | return 0; | 
|  | 840 | } | 
|  | 841 |  | 
|  | 842 | int ChannelConfig::writeChannelVolatileData() | 
|  | 843 | { | 
|  | 844 | boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> | 
|  | 845 | channelLock{*channelMutex}; | 
|  | 846 | Json outData; | 
|  | 847 |  | 
|  | 848 | try | 
|  | 849 | { | 
|  | 850 | for (uint8_t chNum = 0; chNum < maxIpmiChannels; chNum++) | 
|  | 851 | { | 
|  | 852 | if (getChannelSessionSupport(chNum) != EChannelSessSupported::none) | 
|  | 853 | { | 
|  | 854 | Json jsonObj; | 
|  | 855 | std::string chKey = std::to_string(chNum); | 
|  | 856 | std::string accModeStr = convertToAccessModeString( | 
|  | 857 | channelData[chNum].chAccess.chVolatileData.accessMode); | 
|  | 858 | jsonObj[accessModeString] = accModeStr; | 
|  | 859 | jsonObj[userAuthDisabledString] = | 
|  | 860 | channelData[chNum].chAccess.chVolatileData.userAuthDisabled; | 
|  | 861 | jsonObj[perMsgAuthDisabledString] = | 
|  | 862 | channelData[chNum] | 
|  | 863 | .chAccess.chVolatileData.perMsgAuthDisabled; | 
|  | 864 | jsonObj[alertingDisabledString] = | 
|  | 865 | channelData[chNum].chAccess.chVolatileData.alertingDisabled; | 
|  | 866 | std::string privStr = convertToPrivLimitString( | 
|  | 867 | channelData[chNum].chAccess.chVolatileData.privLimit); | 
|  | 868 | jsonObj[privLimitString] = privStr; | 
|  | 869 |  | 
|  | 870 | outData[chKey] = jsonObj; | 
|  | 871 | } | 
|  | 872 | } | 
|  | 873 | } | 
|  | 874 | catch (const std::invalid_argument& e) | 
|  | 875 | { | 
|  | 876 | log<level::ERR>("Corrupted config.", entry("MSG: %s", e.what())); | 
|  | 877 | return -EINVAL; | 
|  | 878 | } | 
|  | 879 |  | 
|  | 880 | if (writeJsonFile(channelVolatileDataFilename, outData) != 0) | 
|  | 881 | { | 
|  | 882 | log<level::DEBUG>("Error in write JSON data to file"); | 
|  | 883 | return -EIO; | 
|  | 884 | } | 
|  | 885 |  | 
|  | 886 | // Update the timestamp | 
|  | 887 | voltFileLastUpdatedTime = getUpdatedFileTime(channelVolatileDataFilename); | 
|  | 888 | return 0; | 
|  | 889 | } | 
|  | 890 |  | 
|  | 891 | int ChannelConfig::writeChannelPersistData() | 
|  | 892 | { | 
|  | 893 | boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> | 
|  | 894 | channelLock{*channelMutex}; | 
|  | 895 | Json outData; | 
|  | 896 |  | 
|  | 897 | try | 
|  | 898 | { | 
|  | 899 | for (uint8_t chNum = 0; chNum < maxIpmiChannels; chNum++) | 
|  | 900 | { | 
|  | 901 | if (getChannelSessionSupport(chNum) != EChannelSessSupported::none) | 
|  | 902 | { | 
|  | 903 | Json jsonObj; | 
|  | 904 | std::string chKey = std::to_string(chNum); | 
|  | 905 | std::string accModeStr = convertToAccessModeString( | 
|  | 906 | channelData[chNum].chAccess.chNonVolatileData.accessMode); | 
|  | 907 | jsonObj[accessModeString] = accModeStr; | 
|  | 908 | jsonObj[userAuthDisabledString] = | 
|  | 909 | channelData[chNum] | 
|  | 910 | .chAccess.chNonVolatileData.userAuthDisabled; | 
|  | 911 | jsonObj[perMsgAuthDisabledString] = | 
|  | 912 | channelData[chNum] | 
|  | 913 | .chAccess.chNonVolatileData.perMsgAuthDisabled; | 
|  | 914 | jsonObj[alertingDisabledString] = | 
|  | 915 | channelData[chNum] | 
|  | 916 | .chAccess.chNonVolatileData.alertingDisabled; | 
|  | 917 | std::string privStr = convertToPrivLimitString( | 
|  | 918 | channelData[chNum].chAccess.chNonVolatileData.privLimit); | 
|  | 919 | jsonObj[privLimitString] = privStr; | 
|  | 920 |  | 
|  | 921 | outData[chKey] = jsonObj; | 
|  | 922 | } | 
|  | 923 | } | 
|  | 924 | } | 
|  | 925 | catch (const std::invalid_argument& e) | 
|  | 926 | { | 
|  | 927 | log<level::ERR>("Corrupted config.", entry("MSG: %s", e.what())); | 
|  | 928 | return -EINVAL; | 
|  | 929 | } | 
|  | 930 |  | 
|  | 931 | if (writeJsonFile(channelNvDataFilename, outData) != 0) | 
|  | 932 | { | 
|  | 933 | log<level::DEBUG>("Error in write JSON data to file"); | 
|  | 934 | return -EIO; | 
|  | 935 | } | 
|  | 936 |  | 
|  | 937 | // Update the timestamp | 
|  | 938 | nvFileLastUpdatedTime = getUpdatedFileTime(channelNvDataFilename); | 
|  | 939 | return 0; | 
|  | 940 | } | 
|  | 941 |  | 
|  | 942 | int ChannelConfig::checkAndReloadNVData() | 
|  | 943 | { | 
|  | 944 | std::time_t updateTime = getUpdatedFileTime(channelNvDataFilename); | 
|  | 945 | int ret = 0; | 
|  | 946 | if (updateTime != nvFileLastUpdatedTime || updateTime == -EIO) | 
|  | 947 | { | 
|  | 948 | try | 
|  | 949 | { | 
|  | 950 | ret = readChannelPersistData(); | 
|  | 951 | } | 
|  | 952 | catch (const std::exception& e) | 
|  | 953 | { | 
|  | 954 | log<level::ERR>("Exception caught in readChannelPersistData.", | 
|  | 955 | entry("MSG=%s", e.what())); | 
|  | 956 | ret = -EIO; | 
|  | 957 | } | 
|  | 958 | } | 
|  | 959 | return ret; | 
|  | 960 | } | 
|  | 961 |  | 
|  | 962 | int ChannelConfig::checkAndReloadVolatileData() | 
|  | 963 | { | 
|  | 964 | std::time_t updateTime = getUpdatedFileTime(channelVolatileDataFilename); | 
|  | 965 | int ret = 0; | 
|  | 966 | if (updateTime != voltFileLastUpdatedTime || updateTime == -EIO) | 
|  | 967 | { | 
|  | 968 | try | 
|  | 969 | { | 
|  | 970 | ret = readChannelVolatileData(); | 
|  | 971 | } | 
|  | 972 | catch (const std::exception& e) | 
|  | 973 | { | 
|  | 974 | log<level::ERR>("Exception caught in readChannelVolatileData.", | 
|  | 975 | entry("MSG=%s", e.what())); | 
|  | 976 | ret = -EIO; | 
|  | 977 | } | 
|  | 978 | } | 
|  | 979 | return ret; | 
|  | 980 | } | 
|  | 981 |  | 
|  | 982 | void ChannelConfig::initChannelPersistData() | 
|  | 983 | { | 
|  | 984 | /* Always read the channel config */ | 
|  | 985 | if (loadChannelConfig() != 0) | 
|  | 986 | { | 
|  | 987 | log<level::ERR>("Failed to read channel config file"); | 
|  | 988 | throw std::ios_base::failure("Failed to load channel configuration"); | 
|  | 989 | } | 
|  | 990 |  | 
|  | 991 | /* Populate the channel persist data */ | 
|  | 992 | if (readChannelPersistData() != 0) | 
|  | 993 | { | 
|  | 994 | // Copy default NV data to RW location | 
|  | 995 | std::experimental::filesystem::copy_file(channelAccessDefaultFilename, | 
|  | 996 | channelNvDataFilename); | 
|  | 997 |  | 
|  | 998 | // Load the channel access NV data | 
|  | 999 | if (readChannelPersistData() != 0) | 
|  | 1000 | { | 
|  | 1001 | log<level::ERR>("Failed to read channel access NV data"); | 
|  | 1002 | throw std::ios_base::failure( | 
|  | 1003 | "Failed to read channel access NV configuration"); | 
|  | 1004 | } | 
|  | 1005 | } | 
|  | 1006 |  | 
|  | 1007 | // First check the volatile data file | 
|  | 1008 | // If not present, load the default values | 
|  | 1009 | if (readChannelVolatileData() != 0) | 
|  | 1010 | { | 
|  | 1011 | // Copy default volatile data to temporary location | 
|  | 1012 | // NV file(channelNvDataFilename) must have created by now. | 
|  | 1013 | std::experimental::filesystem::copy_file(channelNvDataFilename, | 
|  | 1014 | channelVolatileDataFilename); | 
|  | 1015 |  | 
|  | 1016 | // Load the channel access volatile data | 
|  | 1017 | if (readChannelVolatileData() != 0) | 
|  | 1018 | { | 
|  | 1019 | log<level::ERR>("Failed to read channel access volatile data"); | 
|  | 1020 | throw std::ios_base::failure( | 
|  | 1021 | "Failed to read channel access volatile configuration"); | 
|  | 1022 | } | 
|  | 1023 | } | 
|  | 1024 | return; | 
|  | 1025 | } | 
|  | 1026 |  | 
|  | 1027 | } // namespace ipmi |