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