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