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