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