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