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 <exception> 27 #include <experimental/filesystem> 28 #include <fstream> 29 #include <phosphor-logging/log.hpp> 30 #include <sdbusplus/bus/match.hpp> 31 #include <sdbusplus/server/object.hpp> 32 #include <unordered_map> 33 34 namespace ipmi 35 { 36 37 using namespace phosphor::logging; 38 39 static constexpr const char* channelAccessDefaultFilename = 40 "/usr/share/ipmi-providers/channel_access.json"; 41 static constexpr const char* channelConfigDefaultFilename = 42 "/usr/share/ipmi-providers/channel_config.json"; 43 static constexpr const char* channelNvDataFilename = 44 "/var/lib/ipmi/channel_access_nv.json"; 45 static constexpr const char* channelVolatileDataFilename = 46 "/run/ipmi/channel_access_volatile.json"; 47 48 // TODO: Get the service name dynamically.. 49 static constexpr const char* networkIntfServiceName = 50 "xyz.openbmc_project.Network"; 51 static constexpr const char* networkIntfObjectBasePath = 52 "/xyz/openbmc_project/network"; 53 static constexpr const char* networkChConfigIntfName = 54 "xyz.openbmc_project.Channel.ChannelAccess"; 55 static constexpr const char* privilegePropertyString = "MaxPrivilege"; 56 static constexpr const char* dBusPropertiesInterface = 57 "org.freedesktop.DBus.Properties"; 58 static constexpr const char* propertiesChangedSignal = "PropertiesChanged"; 59 60 // STRING DEFINES: Should sync with key's in JSON 61 static constexpr const char* nameString = "name"; 62 static constexpr const char* isValidString = "is_valid"; 63 static constexpr const char* activeSessionsString = "active_sessions"; 64 static constexpr const char* maxTransferSizeString = "max_transfer_size"; 65 static constexpr const char* channelInfoString = "channel_info"; 66 static constexpr const char* mediumTypeString = "medium_type"; 67 static constexpr const char* protocolTypeString = "protocol_type"; 68 static constexpr const char* sessionSupportedString = "session_supported"; 69 static constexpr const char* isIpmiString = "is_ipmi"; 70 static constexpr const char* authTypeSupportedString = "auth_type_supported"; 71 static constexpr const char* accessModeString = "access_mode"; 72 static constexpr const char* userAuthDisabledString = "user_auth_disabled"; 73 static constexpr const char* perMsgAuthDisabledString = "per_msg_auth_disabled"; 74 static constexpr const char* alertingDisabledString = "alerting_disabled"; 75 static constexpr const char* privLimitString = "priv_limit"; 76 static constexpr const char* authTypeEnabledString = "auth_type_enabled"; 77 78 // Default values 79 static constexpr const char* defaultChannelName = "RESERVED"; 80 static constexpr const uint8_t defaultMediumType = 81 static_cast<uint8_t>(EChannelMediumType::reserved); 82 static constexpr const uint8_t defaultProtocolType = 83 static_cast<uint8_t>(EChannelProtocolType::reserved); 84 static constexpr const uint8_t defaultSessionSupported = 85 static_cast<uint8_t>(EChannelSessSupported::none); 86 static constexpr const uint8_t defaultAuthType = 87 static_cast<uint8_t>(EAuthType::none); 88 static constexpr const bool defaultIsIpmiState = false; 89 static constexpr size_t smallChannelSize = 64; 90 91 std::unique_ptr<sdbusplus::bus::match_t> chPropertiesSignal 92 __attribute__((init_priority(101))); 93 94 // String mappings use in JSON config file 95 static std::unordered_map<std::string, EChannelMediumType> mediumTypeMap = { 96 {"reserved", EChannelMediumType::reserved}, 97 {"ipmb", EChannelMediumType::ipmb}, 98 {"icmb-v1.0", EChannelMediumType::icmbV10}, 99 {"icmb-v0.9", EChannelMediumType::icmbV09}, 100 {"lan-802.3", EChannelMediumType::lan8032}, 101 {"serial", EChannelMediumType::serial}, 102 {"other-lan", EChannelMediumType::otherLan}, 103 {"pci-smbus", EChannelMediumType::pciSmbus}, 104 {"smbus-v1.0", EChannelMediumType::smbusV11}, 105 {"smbus-v2.0", EChannelMediumType::smbusV20}, 106 {"usb-1x", EChannelMediumType::usbV1x}, 107 {"usb-2x", EChannelMediumType::usbV2x}, 108 {"system-interface", EChannelMediumType::systemInterface}, 109 {"oem", EChannelMediumType::oem}, 110 {"unknown", EChannelMediumType::unknown}}; 111 112 static std::unordered_map<EInterfaceIndex, std::string> interfaceMap = { 113 {interfaceKCS, "SMS"}, 114 {interfaceLAN1, "eth0"}, 115 {interfaceUnknown, "unknown"}}; 116 117 static std::unordered_map<std::string, EChannelProtocolType> protocolTypeMap = { 118 {"na", EChannelProtocolType::na}, 119 {"ipmb-1.0", EChannelProtocolType::ipmbV10}, 120 {"icmb-2.0", EChannelProtocolType::icmbV11}, 121 {"reserved", EChannelProtocolType::reserved}, 122 {"ipmi-smbus", EChannelProtocolType::ipmiSmbus}, 123 {"kcs", EChannelProtocolType::kcs}, 124 {"smic", EChannelProtocolType::smic}, 125 {"bt-10", EChannelProtocolType::bt10}, 126 {"bt-15", EChannelProtocolType::bt15}, 127 {"tmode", EChannelProtocolType::tMode}, 128 {"oem", EChannelProtocolType::oem}}; 129 130 static std::array<std::string, 4> accessModeList = { 131 "disabled", "pre-boot", "always_available", "shared"}; 132 133 static std::array<std::string, 4> sessionSupportList = { 134 "session-less", "single-session", "multi-session", "session-based"}; 135 136 const std::array<std::string, PRIVILEGE_OEM + 1> privList = { 137 "priv-reserved", "priv-callback", "priv-user", 138 "priv-operator", "priv-admin", "priv-oem"}; 139 140 std::string ChannelConfig::getChannelName(const uint8_t chNum) 141 { 142 if (!isValidChannel(chNum)) 143 { 144 log<level::ERR>("Invalid channel number.", 145 entry("CHANNEL_ID=%d", chNum)); 146 throw std::invalid_argument("Invalid channel number"); 147 } 148 149 return channelData[chNum].chName; 150 } 151 152 int ChannelConfig::convertToChannelNumberFromChannelName( 153 const std::string& chName) 154 { 155 for (const auto& it : channelData) 156 { 157 if (it.chName == chName) 158 { 159 return it.chID; 160 } 161 } 162 log<level::ERR>("Invalid channel name.", 163 entry("CHANNEL=%s", chName.c_str())); 164 throw std::invalid_argument("Invalid channel name"); 165 166 return -1; 167 } 168 169 std::string ChannelConfig::getChannelNameFromPath(const std::string& path) 170 { 171 172 constexpr size_t length = strlen(networkIntfObjectBasePath); 173 if (((length + 1) >= path.size()) || 174 path.compare(0, length, networkIntfObjectBasePath)) 175 { 176 log<level::ERR>("Invalid object path.", entry("PATH=%s", path.c_str())); 177 throw std::invalid_argument("Invalid object path"); 178 } 179 std::string chName(path, length + 1); 180 return chName; 181 } 182 183 void ChannelConfig::processChAccessPropChange( 184 const std::string& path, const DbusChObjProperties& chProperties) 185 { 186 // Get interface name from path. ex: '/xyz/openbmc_project/network/eth0' 187 std::string chName; 188 try 189 { 190 chName = getChannelNameFromPath(path); 191 } 192 catch (const std::invalid_argument& e) 193 { 194 log<level::ERR>("Exception: ", entry("MSG=%s", e.what())); 195 return; 196 } 197 198 // Get the MaxPrivilege property value from the signal 199 std::string intfPrivStr; 200 std::string propName; 201 for (const auto& prop : chProperties) 202 { 203 if (prop.first == privilegePropertyString) 204 { 205 propName = privilegePropertyString; 206 intfPrivStr = std::get<std::string>(prop.second); 207 break; 208 } 209 } 210 211 if (propName != privilegePropertyString) 212 { 213 log<level::ERR>("Unknown signal caught."); 214 return; 215 } 216 217 if (intfPrivStr.empty()) 218 { 219 log<level::ERR>("Invalid privilege string.", 220 entry("INTF=%s", chName.c_str())); 221 return; 222 } 223 224 uint8_t intfPriv = 0; 225 int chNum; 226 try 227 { 228 intfPriv = static_cast<uint8_t>(convertToPrivLimitIndex(intfPrivStr)); 229 chNum = convertToChannelNumberFromChannelName(chName); 230 } 231 catch (const std::invalid_argument& e) 232 { 233 log<level::ERR>("Exception: ", entry("MSG=%s", e.what())); 234 return; 235 } 236 237 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> 238 channelLock{*channelMutex}; 239 // skip updating the values, if this property change originated from IPMI. 240 if (signalFlag & (1 << chNum)) 241 { 242 signalFlag &= ~(1 << chNum); 243 log<level::DEBUG>("Request originated from IPMI so ignoring signal"); 244 return; 245 } 246 247 // Update both volatile & Non-volatile, if there is mismatch. 248 // as property change other than IPMI, has to update both volatile & 249 // non-volatile data. 250 checkAndReloadVolatileData(); 251 checkAndReloadNVData(); 252 if (channelData[chNum].chAccess.chNonVolatileData.privLimit != intfPriv) 253 { 254 // Update NV data 255 channelData[chNum].chAccess.chNonVolatileData.privLimit = intfPriv; 256 if (writeChannelPersistData() != 0) 257 { 258 log<level::ERR>("Failed to update the persist data file"); 259 return; 260 } 261 262 // Update Volatile data 263 if (channelData[chNum].chAccess.chVolatileData.privLimit != intfPriv) 264 { 265 channelData[chNum].chAccess.chVolatileData.privLimit = intfPriv; 266 if (writeChannelVolatileData() != 0) 267 { 268 log<level::ERR>("Failed to update the volatile data file"); 269 return; 270 } 271 } 272 } 273 274 return; 275 } 276 277 ChannelConfig& getChannelConfigObject() 278 { 279 static ChannelConfig channelConfig; 280 return channelConfig; 281 } 282 283 ChannelConfig::~ChannelConfig() 284 { 285 if (signalHndlrObjectState) 286 { 287 chPropertiesSignal.reset(); 288 sigHndlrLock.unlock(); 289 } 290 } 291 292 ChannelConfig::ChannelConfig() : bus(ipmid_get_sd_bus_connection()) 293 { 294 std::ofstream mutexCleanUpFile; 295 mutexCleanUpFile.open(ipmiChMutexCleanupLockFile, 296 std::ofstream::out | std::ofstream::app); 297 if (!mutexCleanUpFile.good()) 298 { 299 log<level::DEBUG>("Unable to open mutex cleanup file"); 300 return; 301 } 302 mutexCleanUpFile.close(); 303 mutexCleanupLock = 304 boost::interprocess::file_lock(ipmiChMutexCleanupLockFile); 305 if (mutexCleanupLock.try_lock()) 306 { 307 boost::interprocess::named_recursive_mutex::remove(ipmiChannelMutex); 308 channelMutex = 309 std::make_unique<boost::interprocess::named_recursive_mutex>( 310 boost::interprocess::open_or_create, ipmiChannelMutex); 311 mutexCleanupLock.lock_sharable(); 312 } 313 else 314 { 315 mutexCleanupLock.lock_sharable(); 316 channelMutex = 317 std::make_unique<boost::interprocess::named_recursive_mutex>( 318 boost::interprocess::open_or_create, ipmiChannelMutex); 319 } 320 321 initChannelPersistData(); 322 323 sigHndlrLock = boost::interprocess::file_lock(channelNvDataFilename); 324 // Register it for single object and single process either netipimd / 325 // host-ipmid 326 if (chPropertiesSignal == nullptr && sigHndlrLock.try_lock()) 327 { 328 log<level::DEBUG>("Registering channel signal handler."); 329 chPropertiesSignal = std::make_unique<sdbusplus::bus::match_t>( 330 bus, 331 sdbusplus::bus::match::rules::path_namespace( 332 networkIntfObjectBasePath) + 333 sdbusplus::bus::match::rules::type::signal() + 334 sdbusplus::bus::match::rules::member(propertiesChangedSignal) + 335 sdbusplus::bus::match::rules::interface( 336 dBusPropertiesInterface) + 337 sdbusplus::bus::match::rules::argN(0, networkChConfigIntfName), 338 [&](sdbusplus::message::message& msg) { 339 DbusChObjProperties props; 340 std::string iface; 341 std::string path = msg.get_path(); 342 msg.read(iface, props); 343 processChAccessPropChange(path, props); 344 }); 345 signalHndlrObjectState = true; 346 } 347 } 348 349 bool ChannelConfig::isValidChannel(const uint8_t chNum) 350 { 351 if (chNum > maxIpmiChannels) 352 { 353 log<level::DEBUG>("Invalid channel ID - Out of range"); 354 return false; 355 } 356 357 if (channelData[chNum].isChValid == false) 358 { 359 log<level::DEBUG>("Channel is not valid"); 360 } 361 362 return channelData[chNum].isChValid; 363 } 364 365 EChannelSessSupported 366 ChannelConfig::getChannelSessionSupport(const uint8_t chNum) 367 { 368 EChannelSessSupported chSessSupport = 369 (EChannelSessSupported)channelData[chNum].chInfo.sessionSupported; 370 return chSessSupport; 371 } 372 373 bool ChannelConfig::isValidAuthType(const uint8_t chNum, 374 const EAuthType& authType) 375 { 376 if ((authType < EAuthType::md2) || (authType > EAuthType::oem)) 377 { 378 log<level::DEBUG>("Invalid authentication type"); 379 return false; 380 } 381 382 uint8_t authTypeSupported = channelData[chNum].chInfo.authTypeSupported; 383 if (!(authTypeSupported & (1 << static_cast<uint8_t>(authType)))) 384 { 385 log<level::DEBUG>("Authentication type is not supported."); 386 return false; 387 } 388 389 return true; 390 } 391 392 int ChannelConfig::getChannelActiveSessions(const uint8_t chNum) 393 { 394 // TODO: TEMPORARY FIX 395 // Channels active session count is managed separately 396 // by monitoring channel session which includes LAN and 397 // RAKP layer changes. This will be updated, once the 398 // authentication part is implemented. 399 return channelData[chNum].activeSessCount; 400 } 401 402 size_t ChannelConfig::getChannelMaxTransferSize(uint8_t chNum) 403 { 404 return channelData[chNum].maxTransferSize; 405 } 406 407 Cc ChannelConfig::getChannelInfo(const uint8_t chNum, ChannelInfo& chInfo) 408 { 409 if (!isValidChannel(chNum)) 410 { 411 log<level::DEBUG>("Invalid channel"); 412 return ccInvalidFieldRequest; 413 } 414 415 std::copy_n(reinterpret_cast<uint8_t*>(&channelData[chNum].chInfo), 416 sizeof(channelData[chNum].chInfo), 417 reinterpret_cast<uint8_t*>(&chInfo)); 418 return ccSuccess; 419 } 420 421 Cc ChannelConfig::getChannelAccessData(const uint8_t chNum, 422 ChannelAccess& chAccessData) 423 { 424 if (!isValidChannel(chNum)) 425 { 426 log<level::DEBUG>("Invalid channel"); 427 return ccInvalidFieldRequest; 428 } 429 430 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none) 431 { 432 log<level::DEBUG>("Session-less channel doesn't have access data."); 433 return ccActionNotSupportedForChannel; 434 } 435 436 if (checkAndReloadVolatileData() != 0) 437 { 438 return ccUnspecifiedError; 439 } 440 441 std::copy_n( 442 reinterpret_cast<uint8_t*>(&channelData[chNum].chAccess.chVolatileData), 443 sizeof(channelData[chNum].chAccess.chVolatileData), 444 reinterpret_cast<uint8_t*>(&chAccessData)); 445 446 return ccSuccess; 447 } 448 449 Cc ChannelConfig::setChannelAccessData(const uint8_t chNum, 450 const ChannelAccess& chAccessData, 451 const uint8_t setFlag) 452 { 453 if (!isValidChannel(chNum)) 454 { 455 log<level::DEBUG>("Invalid channel"); 456 return ccInvalidFieldRequest; 457 } 458 459 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none) 460 { 461 log<level::DEBUG>("Session-less channel doesn't have access data."); 462 return ccActionNotSupportedForChannel; 463 } 464 465 if ((setFlag & setAccessMode) && 466 (!isValidAccessMode(chAccessData.accessMode))) 467 { 468 log<level::DEBUG>("Invalid access mode specified"); 469 return ccAccessModeNotSupportedForChannel; 470 } 471 if ((setFlag & setPrivLimit) && (!isValidPrivLimit(chAccessData.privLimit))) 472 { 473 log<level::DEBUG>("Invalid privilege limit specified"); 474 return ccInvalidFieldRequest; 475 } 476 477 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> 478 channelLock{*channelMutex}; 479 480 if (checkAndReloadVolatileData() != 0) 481 { 482 return ccUnspecifiedError; 483 } 484 485 if (setFlag & setAccessMode) 486 { 487 channelData[chNum].chAccess.chVolatileData.accessMode = 488 chAccessData.accessMode; 489 } 490 if (setFlag & setUserAuthEnabled) 491 { 492 channelData[chNum].chAccess.chVolatileData.userAuthDisabled = 493 chAccessData.userAuthDisabled; 494 } 495 if (setFlag & setMsgAuthEnabled) 496 { 497 channelData[chNum].chAccess.chVolatileData.perMsgAuthDisabled = 498 chAccessData.perMsgAuthDisabled; 499 } 500 if (setFlag & setAlertingEnabled) 501 { 502 channelData[chNum].chAccess.chVolatileData.alertingDisabled = 503 chAccessData.alertingDisabled; 504 } 505 if (setFlag & setPrivLimit) 506 { 507 channelData[chNum].chAccess.chVolatileData.privLimit = 508 chAccessData.privLimit; 509 } 510 511 // Write Volatile data to file 512 if (writeChannelVolatileData() != 0) 513 { 514 log<level::DEBUG>("Failed to update the channel volatile data"); 515 return ccUnspecifiedError; 516 } 517 return ccSuccess; 518 } 519 520 Cc ChannelConfig::getChannelAccessPersistData(const uint8_t chNum, 521 ChannelAccess& chAccessData) 522 { 523 if (!isValidChannel(chNum)) 524 { 525 log<level::DEBUG>("Invalid channel"); 526 return ccInvalidFieldRequest; 527 } 528 529 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none) 530 { 531 log<level::DEBUG>("Session-less channel doesn't have access data."); 532 return ccActionNotSupportedForChannel; 533 } 534 535 if (checkAndReloadNVData() != 0) 536 { 537 return ccUnspecifiedError; 538 } 539 540 std::copy_n(reinterpret_cast<uint8_t*>( 541 &channelData[chNum].chAccess.chNonVolatileData), 542 sizeof(channelData[chNum].chAccess.chNonVolatileData), 543 reinterpret_cast<uint8_t*>(&chAccessData)); 544 545 return ccSuccess; 546 } 547 548 Cc ChannelConfig::setChannelAccessPersistData(const uint8_t chNum, 549 const ChannelAccess& chAccessData, 550 const uint8_t setFlag) 551 { 552 if (!isValidChannel(chNum)) 553 { 554 log<level::DEBUG>("Invalid channel"); 555 return ccInvalidFieldRequest; 556 } 557 558 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none) 559 { 560 log<level::DEBUG>("Session-less channel doesn't have access data."); 561 return ccActionNotSupportedForChannel; 562 } 563 564 if ((setFlag & setAccessMode) && 565 (!isValidAccessMode(chAccessData.accessMode))) 566 { 567 log<level::DEBUG>("Invalid access mode specified"); 568 return ccAccessModeNotSupportedForChannel; 569 } 570 if ((setFlag & setPrivLimit) && (!isValidPrivLimit(chAccessData.privLimit))) 571 { 572 log<level::DEBUG>("Invalid privilege limit specified"); 573 return ccInvalidFieldRequest; 574 } 575 576 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> 577 channelLock{*channelMutex}; 578 579 if (checkAndReloadNVData() != 0) 580 { 581 return ccUnspecifiedError; 582 } 583 584 if (setFlag & setAccessMode) 585 { 586 channelData[chNum].chAccess.chNonVolatileData.accessMode = 587 chAccessData.accessMode; 588 } 589 if (setFlag & setUserAuthEnabled) 590 { 591 channelData[chNum].chAccess.chNonVolatileData.userAuthDisabled = 592 chAccessData.userAuthDisabled; 593 } 594 if (setFlag & setMsgAuthEnabled) 595 { 596 channelData[chNum].chAccess.chNonVolatileData.perMsgAuthDisabled = 597 chAccessData.perMsgAuthDisabled; 598 } 599 if (setFlag & setAlertingEnabled) 600 { 601 channelData[chNum].chAccess.chNonVolatileData.alertingDisabled = 602 chAccessData.alertingDisabled; 603 } 604 if (setFlag & setPrivLimit) 605 { 606 // Send Update to network channel config interfaces over dbus 607 std::string privStr = convertToPrivLimitString(chAccessData.privLimit); 608 std::string networkIntfObj = std::string(networkIntfObjectBasePath) + 609 "/" + channelData[chNum].chName; 610 try 611 { 612 if (0 != setDbusProperty(networkIntfServiceName, networkIntfObj, 613 networkChConfigIntfName, 614 privilegePropertyString, privStr)) 615 { 616 log<level::DEBUG>( 617 "Network interface does not exist", 618 entry("INTERFACE=%s", channelData[chNum].chName.c_str())); 619 return ccUnspecifiedError; 620 } 621 } 622 catch (const sdbusplus::exception::SdBusError& e) 623 { 624 log<level::ERR>("Exception: Network interface does not exist"); 625 return ccInvalidFieldRequest; 626 } 627 signalFlag |= (1 << chNum); 628 channelData[chNum].chAccess.chNonVolatileData.privLimit = 629 chAccessData.privLimit; 630 } 631 632 // Write persistent data to file 633 if (writeChannelPersistData() != 0) 634 { 635 log<level::DEBUG>("Failed to update the presist data file"); 636 return ccUnspecifiedError; 637 } 638 return ccSuccess; 639 } 640 641 Cc ChannelConfig::getChannelAuthTypeSupported(const uint8_t chNum, 642 uint8_t& authTypeSupported) 643 { 644 if (!isValidChannel(chNum)) 645 { 646 log<level::DEBUG>("Invalid channel"); 647 return ccInvalidFieldRequest; 648 } 649 650 authTypeSupported = channelData[chNum].chInfo.authTypeSupported; 651 return ccSuccess; 652 } 653 654 Cc ChannelConfig::getChannelEnabledAuthType(const uint8_t chNum, 655 const uint8_t priv, 656 EAuthType& authType) 657 { 658 if (!isValidChannel(chNum)) 659 { 660 log<level::DEBUG>("Invalid channel"); 661 return ccInvalidFieldRequest; 662 } 663 664 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none) 665 { 666 log<level::DEBUG>("Sessionless channel doesn't have access data."); 667 return ccInvalidFieldRequest; 668 } 669 670 if (!isValidPrivLimit(priv)) 671 { 672 log<level::DEBUG>("Invalid privilege specified."); 673 return ccInvalidFieldRequest; 674 } 675 676 // TODO: Hardcoded for now. Need to implement. 677 authType = EAuthType::none; 678 679 return ccSuccess; 680 } 681 682 std::time_t ChannelConfig::getUpdatedFileTime(const std::string& fileName) 683 { 684 struct stat fileStat; 685 if (stat(fileName.c_str(), &fileStat) != 0) 686 { 687 log<level::DEBUG>("Error in getting last updated time stamp"); 688 return -EIO; 689 } 690 return fileStat.st_mtime; 691 } 692 693 EChannelAccessMode 694 ChannelConfig::convertToAccessModeIndex(const std::string& mode) 695 { 696 auto iter = std::find(accessModeList.begin(), accessModeList.end(), mode); 697 if (iter == accessModeList.end()) 698 { 699 log<level::ERR>("Invalid access mode.", 700 entry("MODE_STR=%s", mode.c_str())); 701 throw std::invalid_argument("Invalid access mode."); 702 } 703 704 return static_cast<EChannelAccessMode>( 705 std::distance(accessModeList.begin(), iter)); 706 } 707 708 std::string ChannelConfig::convertToAccessModeString(const uint8_t value) 709 { 710 if (accessModeList.size() <= value) 711 { 712 log<level::ERR>("Invalid access mode.", entry("MODE_IDX=%d", value)); 713 throw std::invalid_argument("Invalid access mode."); 714 } 715 716 return accessModeList.at(value); 717 } 718 719 CommandPrivilege 720 ChannelConfig::convertToPrivLimitIndex(const std::string& value) 721 { 722 auto iter = std::find(privList.begin(), privList.end(), value); 723 if (iter == privList.end()) 724 { 725 log<level::ERR>("Invalid privilege.", 726 entry("PRIV_STR=%s", value.c_str())); 727 throw std::invalid_argument("Invalid privilege."); 728 } 729 730 return static_cast<CommandPrivilege>(std::distance(privList.begin(), iter)); 731 } 732 733 std::string ChannelConfig::convertToPrivLimitString(const uint8_t value) 734 { 735 if (privList.size() <= value) 736 { 737 log<level::ERR>("Invalid privilege.", entry("PRIV_IDX=%d", value)); 738 throw std::invalid_argument("Invalid privilege."); 739 } 740 741 return privList.at(value); 742 } 743 744 EChannelSessSupported 745 ChannelConfig::convertToSessionSupportIndex(const std::string& value) 746 { 747 auto iter = 748 std::find(sessionSupportList.begin(), sessionSupportList.end(), value); 749 if (iter == sessionSupportList.end()) 750 { 751 log<level::ERR>("Invalid session supported.", 752 entry("SESS_STR=%s", value.c_str())); 753 throw std::invalid_argument("Invalid session supported."); 754 } 755 756 return static_cast<EChannelSessSupported>( 757 std::distance(sessionSupportList.begin(), iter)); 758 } 759 760 EChannelMediumType 761 ChannelConfig::convertToMediumTypeIndex(const std::string& value) 762 { 763 std::unordered_map<std::string, EChannelMediumType>::iterator it = 764 mediumTypeMap.find(value); 765 if (it == mediumTypeMap.end()) 766 { 767 log<level::ERR>("Invalid medium type.", 768 entry("MEDIUM_STR=%s", value.c_str())); 769 throw std::invalid_argument("Invalid medium type."); 770 } 771 772 return static_cast<EChannelMediumType>(it->second); 773 } 774 775 EChannelProtocolType 776 ChannelConfig::convertToProtocolTypeIndex(const std::string& value) 777 { 778 std::unordered_map<std::string, EChannelProtocolType>::iterator it = 779 protocolTypeMap.find(value); 780 if (it == protocolTypeMap.end()) 781 { 782 log<level::ERR>("Invalid protocol type.", 783 entry("PROTO_STR=%s", value.c_str())); 784 throw std::invalid_argument("Invalid protocol type."); 785 } 786 787 return static_cast<EChannelProtocolType>(it->second); 788 } 789 790 Json ChannelConfig::readJsonFile(const std::string& configFile) 791 { 792 std::ifstream jsonFile(configFile); 793 if (!jsonFile.good()) 794 { 795 log<level::INFO>("JSON file not found", 796 entry("FILE_NAME=%s", configFile.c_str())); 797 return nullptr; 798 } 799 800 Json data = nullptr; 801 try 802 { 803 data = Json::parse(jsonFile, nullptr, false); 804 } 805 catch (Json::parse_error& e) 806 { 807 log<level::DEBUG>("Corrupted channel config.", 808 entry("MSG=%s", e.what())); 809 throw std::runtime_error("Corrupted channel config file"); 810 } 811 812 return data; 813 } 814 815 int ChannelConfig::writeJsonFile(const std::string& configFile, 816 const Json& jsonData) 817 { 818 const std::string tmpFile = configFile + "_tmp"; 819 int fd = open(tmpFile.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_SYNC, 820 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 821 if (fd < 0) 822 { 823 log<level::ERR>("Error in creating json file", 824 entry("FILE_NAME = %s", tmpFile.c_str())); 825 return -EIO; 826 } 827 const auto& writeData = jsonData.dump(); 828 if (write(fd, writeData.c_str(), writeData.size()) != 829 static_cast<ssize_t>(writeData.size())) 830 { 831 close(fd); 832 log<level::ERR>("Error in writing configuration file", 833 entry("FILE_NAME = %s", tmpFile.c_str())); 834 return -EIO; 835 } 836 close(fd); 837 838 if (std::rename(tmpFile.c_str(), configFile.c_str()) != 0) 839 { 840 log<level::ERR>("Error in renaming temporary data file", 841 entry("FILE_NAME = %s", tmpFile.c_str())); 842 return -EIO; 843 } 844 845 return 0; 846 } 847 848 void ChannelConfig::setDefaultChannelConfig(const uint8_t chNum, 849 const std::string& chName) 850 { 851 channelData[chNum].chName = chName; 852 channelData[chNum].chID = chNum; 853 channelData[chNum].isChValid = false; 854 channelData[chNum].activeSessCount = 0; 855 856 channelData[chNum].chInfo.mediumType = defaultMediumType; 857 channelData[chNum].chInfo.protocolType = defaultProtocolType; 858 channelData[chNum].chInfo.sessionSupported = defaultSessionSupported; 859 channelData[chNum].chInfo.isIpmi = defaultIsIpmiState; 860 channelData[chNum].chInfo.authTypeSupported = defaultAuthType; 861 } 862 863 int ChannelConfig::loadChannelConfig() 864 { 865 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> 866 channelLock{*channelMutex}; 867 868 Json data = readJsonFile(channelConfigDefaultFilename); 869 if (data.empty()) 870 { 871 log<level::DEBUG>("Error in opening IPMI Channel data file"); 872 return -EIO; 873 } 874 875 channelData.fill(ChannelProperties{}); 876 877 for (int chNum = 0; chNum < maxIpmiChannels; chNum++) 878 { 879 try 880 { 881 std::string chKey = std::to_string(chNum); 882 Json jsonChData = data[chKey].get<Json>(); 883 if (jsonChData.is_null()) 884 { 885 log<level::WARNING>( 886 "Channel not configured so loading default.", 887 entry("CHANNEL_NUM=%d", chNum)); 888 // If user didn't want to configure specific channel (say 889 // reserved channel), then load that index with default values. 890 setDefaultChannelConfig(chNum, defaultChannelName); 891 continue; 892 } 893 Json jsonChInfo = jsonChData[channelInfoString].get<Json>(); 894 if (jsonChInfo.is_null()) 895 { 896 log<level::ERR>("Invalid/corrupted channel config file"); 897 return -EBADMSG; 898 } 899 900 ChannelProperties& chData = channelData[chNum]; 901 chData.chName = jsonChData[nameString].get<std::string>(); 902 chData.chID = chNum; 903 chData.isChValid = jsonChData[isValidString].get<bool>(); 904 chData.activeSessCount = jsonChData.value(activeSessionsString, 0); 905 chData.maxTransferSize = 906 jsonChData.value(maxTransferSizeString, smallChannelSize); 907 std::string medTypeStr = 908 jsonChInfo[mediumTypeString].get<std::string>(); 909 chData.chInfo.mediumType = 910 static_cast<uint8_t>(convertToMediumTypeIndex(medTypeStr)); 911 std::string protoTypeStr = 912 jsonChInfo[protocolTypeString].get<std::string>(); 913 chData.chInfo.protocolType = 914 static_cast<uint8_t>(convertToProtocolTypeIndex(protoTypeStr)); 915 std::string sessStr = 916 jsonChInfo[sessionSupportedString].get<std::string>(); 917 chData.chInfo.sessionSupported = 918 static_cast<uint8_t>(convertToSessionSupportIndex(sessStr)); 919 chData.chInfo.isIpmi = jsonChInfo[isIpmiString].get<bool>(); 920 chData.chInfo.authTypeSupported = defaultAuthType; 921 } 922 catch (const Json::exception& e) 923 { 924 log<level::DEBUG>("Json Exception caught.", 925 entry("MSG=%s", e.what())); 926 return -EBADMSG; 927 } 928 catch (const std::invalid_argument& e) 929 { 930 log<level::ERR>("Corrupted config.", entry("MSG=%s", e.what())); 931 return -EBADMSG; 932 } 933 } 934 935 return 0; 936 } 937 938 int ChannelConfig::readChannelVolatileData() 939 { 940 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> 941 channelLock{*channelMutex}; 942 943 Json data = readJsonFile(channelVolatileDataFilename); 944 if (data == nullptr) 945 { 946 log<level::DEBUG>("Error in opening IPMI Channel data file"); 947 return -EIO; 948 } 949 try 950 { 951 // Fill in global structure 952 for (auto it = data.begin(); it != data.end(); ++it) 953 { 954 std::string chKey = it.key(); 955 uint8_t chNum = std::stoi(chKey, nullptr, 10); 956 if ((chNum < 0) || (chNum > maxIpmiChannels)) 957 { 958 log<level::DEBUG>( 959 "Invalid channel access entry in config file"); 960 throw std::out_of_range("Out of range - channel number"); 961 } 962 Json jsonChData = it.value(); 963 if (!jsonChData.is_null()) 964 { 965 std::string accModeStr = 966 jsonChData[accessModeString].get<std::string>(); 967 channelData[chNum].chAccess.chVolatileData.accessMode = 968 static_cast<uint8_t>(convertToAccessModeIndex(accModeStr)); 969 channelData[chNum].chAccess.chVolatileData.userAuthDisabled = 970 jsonChData[userAuthDisabledString].get<bool>(); 971 channelData[chNum].chAccess.chVolatileData.perMsgAuthDisabled = 972 jsonChData[perMsgAuthDisabledString].get<bool>(); 973 channelData[chNum].chAccess.chVolatileData.alertingDisabled = 974 jsonChData[alertingDisabledString].get<bool>(); 975 std::string privStr = 976 jsonChData[privLimitString].get<std::string>(); 977 channelData[chNum].chAccess.chVolatileData.privLimit = 978 static_cast<uint8_t>(convertToPrivLimitIndex(privStr)); 979 } 980 else 981 { 982 log<level::ERR>( 983 "Invalid/corrupted volatile channel access file", 984 entry("FILE=%s", channelVolatileDataFilename)); 985 throw std::runtime_error( 986 "Corrupted volatile channel access file"); 987 } 988 } 989 } 990 catch (const Json::exception& e) 991 { 992 log<level::DEBUG>("Json Exception caught.", entry("MSG=%s", e.what())); 993 throw std::runtime_error("Corrupted volatile channel access file"); 994 } 995 catch (const std::invalid_argument& e) 996 { 997 log<level::ERR>("Corrupted config.", entry("MSG=%s", e.what())); 998 throw std::runtime_error("Corrupted volatile channel access file"); 999 } 1000 1001 // Update the timestamp 1002 voltFileLastUpdatedTime = getUpdatedFileTime(channelVolatileDataFilename); 1003 return 0; 1004 } 1005 1006 int ChannelConfig::readChannelPersistData() 1007 { 1008 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> 1009 channelLock{*channelMutex}; 1010 1011 Json data = readJsonFile(channelNvDataFilename); 1012 if (data == nullptr) 1013 { 1014 log<level::DEBUG>("Error in opening IPMI Channel data file"); 1015 return -EIO; 1016 } 1017 try 1018 { 1019 // Fill in global structure 1020 for (auto it = data.begin(); it != data.end(); ++it) 1021 { 1022 std::string chKey = it.key(); 1023 uint8_t chNum = std::stoi(chKey, nullptr, 10); 1024 if ((chNum < 0) || (chNum > maxIpmiChannels)) 1025 { 1026 log<level::DEBUG>( 1027 "Invalid channel access entry in config file"); 1028 throw std::out_of_range("Out of range - channel number"); 1029 } 1030 Json jsonChData = it.value(); 1031 if (!jsonChData.is_null()) 1032 { 1033 std::string accModeStr = 1034 jsonChData[accessModeString].get<std::string>(); 1035 channelData[chNum].chAccess.chNonVolatileData.accessMode = 1036 static_cast<uint8_t>(convertToAccessModeIndex(accModeStr)); 1037 channelData[chNum].chAccess.chNonVolatileData.userAuthDisabled = 1038 jsonChData[userAuthDisabledString].get<bool>(); 1039 channelData[chNum] 1040 .chAccess.chNonVolatileData.perMsgAuthDisabled = 1041 jsonChData[perMsgAuthDisabledString].get<bool>(); 1042 channelData[chNum].chAccess.chNonVolatileData.alertingDisabled = 1043 jsonChData[alertingDisabledString].get<bool>(); 1044 std::string privStr = 1045 jsonChData[privLimitString].get<std::string>(); 1046 channelData[chNum].chAccess.chNonVolatileData.privLimit = 1047 static_cast<uint8_t>(convertToPrivLimitIndex(privStr)); 1048 } 1049 else 1050 { 1051 log<level::ERR>("Invalid/corrupted nv channel access file", 1052 entry("FILE=%s", channelNvDataFilename)); 1053 throw std::runtime_error("Corrupted nv channel access file"); 1054 } 1055 } 1056 } 1057 catch (const Json::exception& e) 1058 { 1059 log<level::DEBUG>("Json Exception caught.", entry("MSG=%s", e.what())); 1060 throw std::runtime_error("Corrupted nv channel access file"); 1061 } 1062 catch (const std::invalid_argument& e) 1063 { 1064 log<level::ERR>("Corrupted config.", entry("MSG=%s", e.what())); 1065 throw std::runtime_error("Corrupted nv channel access file"); 1066 } 1067 1068 // Update the timestamp 1069 nvFileLastUpdatedTime = getUpdatedFileTime(channelNvDataFilename); 1070 return 0; 1071 } 1072 1073 int ChannelConfig::writeChannelVolatileData() 1074 { 1075 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> 1076 channelLock{*channelMutex}; 1077 Json outData; 1078 1079 try 1080 { 1081 for (uint8_t chNum = 0; chNum < maxIpmiChannels; chNum++) 1082 { 1083 if (getChannelSessionSupport(chNum) != EChannelSessSupported::none) 1084 { 1085 Json jsonObj; 1086 std::string chKey = std::to_string(chNum); 1087 std::string accModeStr = convertToAccessModeString( 1088 channelData[chNum].chAccess.chVolatileData.accessMode); 1089 jsonObj[accessModeString] = accModeStr; 1090 jsonObj[userAuthDisabledString] = 1091 channelData[chNum].chAccess.chVolatileData.userAuthDisabled; 1092 jsonObj[perMsgAuthDisabledString] = 1093 channelData[chNum] 1094 .chAccess.chVolatileData.perMsgAuthDisabled; 1095 jsonObj[alertingDisabledString] = 1096 channelData[chNum].chAccess.chVolatileData.alertingDisabled; 1097 std::string privStr = convertToPrivLimitString( 1098 channelData[chNum].chAccess.chVolatileData.privLimit); 1099 jsonObj[privLimitString] = privStr; 1100 1101 outData[chKey] = jsonObj; 1102 } 1103 } 1104 } 1105 catch (const std::invalid_argument& e) 1106 { 1107 log<level::ERR>("Corrupted config.", entry("MSG=%s", e.what())); 1108 return -EINVAL; 1109 } 1110 1111 if (writeJsonFile(channelVolatileDataFilename, outData) != 0) 1112 { 1113 log<level::DEBUG>("Error in write JSON data to file"); 1114 return -EIO; 1115 } 1116 1117 // Update the timestamp 1118 voltFileLastUpdatedTime = getUpdatedFileTime(channelVolatileDataFilename); 1119 return 0; 1120 } 1121 1122 int ChannelConfig::writeChannelPersistData() 1123 { 1124 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> 1125 channelLock{*channelMutex}; 1126 Json outData; 1127 1128 try 1129 { 1130 for (uint8_t chNum = 0; chNum < maxIpmiChannels; chNum++) 1131 { 1132 if (getChannelSessionSupport(chNum) != EChannelSessSupported::none) 1133 { 1134 Json jsonObj; 1135 std::string chKey = std::to_string(chNum); 1136 std::string accModeStr = convertToAccessModeString( 1137 channelData[chNum].chAccess.chNonVolatileData.accessMode); 1138 jsonObj[accessModeString] = accModeStr; 1139 jsonObj[userAuthDisabledString] = 1140 channelData[chNum] 1141 .chAccess.chNonVolatileData.userAuthDisabled; 1142 jsonObj[perMsgAuthDisabledString] = 1143 channelData[chNum] 1144 .chAccess.chNonVolatileData.perMsgAuthDisabled; 1145 jsonObj[alertingDisabledString] = 1146 channelData[chNum] 1147 .chAccess.chNonVolatileData.alertingDisabled; 1148 std::string privStr = convertToPrivLimitString( 1149 channelData[chNum].chAccess.chNonVolatileData.privLimit); 1150 jsonObj[privLimitString] = privStr; 1151 1152 outData[chKey] = jsonObj; 1153 } 1154 } 1155 } 1156 catch (const std::invalid_argument& e) 1157 { 1158 log<level::ERR>("Corrupted config.", entry("MSG=%s", e.what())); 1159 return -EINVAL; 1160 } 1161 1162 if (writeJsonFile(channelNvDataFilename, outData) != 0) 1163 { 1164 log<level::DEBUG>("Error in write JSON data to file"); 1165 return -EIO; 1166 } 1167 1168 // Update the timestamp 1169 nvFileLastUpdatedTime = getUpdatedFileTime(channelNvDataFilename); 1170 return 0; 1171 } 1172 1173 int ChannelConfig::checkAndReloadNVData() 1174 { 1175 std::time_t updateTime = getUpdatedFileTime(channelNvDataFilename); 1176 int ret = 0; 1177 if (updateTime != nvFileLastUpdatedTime || updateTime == -EIO) 1178 { 1179 try 1180 { 1181 ret = readChannelPersistData(); 1182 } 1183 catch (const std::exception& e) 1184 { 1185 log<level::ERR>("Exception caught in readChannelPersistData.", 1186 entry("MSG=%s", e.what())); 1187 ret = -EIO; 1188 } 1189 } 1190 return ret; 1191 } 1192 1193 int ChannelConfig::checkAndReloadVolatileData() 1194 { 1195 std::time_t updateTime = getUpdatedFileTime(channelVolatileDataFilename); 1196 int ret = 0; 1197 if (updateTime != voltFileLastUpdatedTime || updateTime == -EIO) 1198 { 1199 try 1200 { 1201 ret = readChannelVolatileData(); 1202 } 1203 catch (const std::exception& e) 1204 { 1205 log<level::ERR>("Exception caught in readChannelVolatileData.", 1206 entry("MSG=%s", e.what())); 1207 ret = -EIO; 1208 } 1209 } 1210 return ret; 1211 } 1212 1213 int ChannelConfig::setDbusProperty(const std::string& service, 1214 const std::string& objPath, 1215 const std::string& interface, 1216 const std::string& property, 1217 const DbusVariant& value) 1218 { 1219 try 1220 { 1221 auto method = 1222 bus.new_method_call(service.c_str(), objPath.c_str(), 1223 "org.freedesktop.DBus.Properties", "Set"); 1224 1225 method.append(interface, property, value); 1226 1227 auto reply = bus.call(method); 1228 } 1229 catch (const sdbusplus::exception::SdBusError& e) 1230 { 1231 log<level::DEBUG>("set-property failed", 1232 entry("SERVICE=%s", service.c_str()), 1233 entry("OBJPATH=%s", objPath.c_str()), 1234 entry("INTERFACE=%s", interface.c_str()), 1235 entry("PROP=%s", property.c_str())); 1236 return -EIO; 1237 } 1238 1239 return 0; 1240 } 1241 1242 int ChannelConfig::getDbusProperty(const std::string& service, 1243 const std::string& objPath, 1244 const std::string& interface, 1245 const std::string& property, 1246 DbusVariant& value) 1247 { 1248 try 1249 { 1250 auto method = 1251 bus.new_method_call(service.c_str(), objPath.c_str(), 1252 "org.freedesktop.DBus.Properties", "Get"); 1253 1254 method.append(interface, property); 1255 1256 auto reply = bus.call(method); 1257 reply.read(value); 1258 } 1259 catch (const sdbusplus::exception::SdBusError& e) 1260 { 1261 log<level::DEBUG>("get-property failed", 1262 entry("SERVICE=%s", service.c_str()), 1263 entry("OBJPATH=%s", objPath.c_str()), 1264 entry("INTERFACE=%s", interface.c_str()), 1265 entry("PROP=%s", property.c_str())); 1266 return -EIO; 1267 } 1268 return 0; 1269 } 1270 1271 int ChannelConfig::syncNetworkChannelConfig() 1272 { 1273 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> 1274 channelLock{*channelMutex}; 1275 bool isUpdated = false; 1276 for (uint8_t chNum = 0; chNum < maxIpmiChannels; chNum++) 1277 { 1278 if (getChannelSessionSupport(chNum) != EChannelSessSupported::none) 1279 { 1280 std::string intfPrivStr; 1281 try 1282 { 1283 std::string networkIntfObj = 1284 std::string(networkIntfObjectBasePath) + "/" + 1285 channelData[chNum].chName; 1286 DbusVariant variant; 1287 if (0 != getDbusProperty(networkIntfServiceName, networkIntfObj, 1288 networkChConfigIntfName, 1289 privilegePropertyString, variant)) 1290 { 1291 log<level::DEBUG>("Network interface does not exist", 1292 entry("INTERFACE=%s", 1293 channelData[chNum].chName.c_str())); 1294 continue; 1295 } 1296 intfPrivStr = std::get<std::string>(variant); 1297 } 1298 catch (const std::bad_variant_access& e) 1299 { 1300 log<level::DEBUG>( 1301 "exception: Network interface does not exist"); 1302 continue; 1303 } 1304 catch (const sdbusplus::exception::SdBusError& e) 1305 { 1306 log<level::DEBUG>( 1307 "exception: Network interface does not exist"); 1308 continue; 1309 } 1310 1311 uint8_t intfPriv = 1312 static_cast<uint8_t>(convertToPrivLimitIndex(intfPrivStr)); 1313 if (channelData[chNum].chAccess.chNonVolatileData.privLimit != 1314 intfPriv) 1315 { 1316 isUpdated = true; 1317 channelData[chNum].chAccess.chNonVolatileData.privLimit = 1318 intfPriv; 1319 channelData[chNum].chAccess.chVolatileData.privLimit = intfPriv; 1320 } 1321 } 1322 } 1323 1324 if (isUpdated) 1325 { 1326 // Write persistent data to file 1327 if (writeChannelPersistData() != 0) 1328 { 1329 log<level::DEBUG>("Failed to update the persistent data file"); 1330 return -EIO; 1331 } 1332 // Write Volatile data to file 1333 if (writeChannelVolatileData() != 0) 1334 { 1335 log<level::DEBUG>("Failed to update the channel volatile data"); 1336 return -EIO; 1337 } 1338 } 1339 1340 return 0; 1341 } 1342 1343 void ChannelConfig::initChannelPersistData() 1344 { 1345 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> 1346 channelLock{*channelMutex}; 1347 1348 /* Always read the channel config */ 1349 if (loadChannelConfig() != 0) 1350 { 1351 log<level::ERR>("Failed to read channel config file"); 1352 throw std::ios_base::failure("Failed to load channel configuration"); 1353 } 1354 1355 /* Populate the channel persist data */ 1356 if (readChannelPersistData() != 0) 1357 { 1358 // Copy default NV data to RW location 1359 std::experimental::filesystem::copy_file(channelAccessDefaultFilename, 1360 channelNvDataFilename); 1361 1362 // Load the channel access NV data 1363 if (readChannelPersistData() != 0) 1364 { 1365 log<level::ERR>("Failed to read channel access NV data"); 1366 throw std::ios_base::failure( 1367 "Failed to read channel access NV configuration"); 1368 } 1369 } 1370 1371 // First check the volatile data file 1372 // If not present, load the default values 1373 if (readChannelVolatileData() != 0) 1374 { 1375 // Copy default volatile data to temporary location 1376 // NV file(channelNvDataFilename) must have created by now. 1377 std::experimental::filesystem::copy_file(channelNvDataFilename, 1378 channelVolatileDataFilename); 1379 1380 // Load the channel access volatile data 1381 if (readChannelVolatileData() != 0) 1382 { 1383 log<level::ERR>("Failed to read channel access volatile data"); 1384 throw std::ios_base::failure( 1385 "Failed to read channel access volatile configuration"); 1386 } 1387 } 1388 1389 // Synchronize the channel config(priv) with network channel 1390 // configuration(priv) over dbus 1391 if (syncNetworkChannelConfig() != 0) 1392 { 1393 log<level::ERR>( 1394 "Failed to synchronize data with network channel config over dbus"); 1395 throw std::ios_base::failure( 1396 "Failed to synchronize data with network channel config over dbus"); 1397 } 1398 1399 log<level::DEBUG>("Successfully completed channel data initialization."); 1400 return; 1401 } 1402 1403 } // namespace ipmi 1404