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