blob: b682ccb50c5830b471a4516c2d793e9c464ce88a [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"
Johnathan Manteyfd61fc32021-04-08 11:05:38 -070020#include "user_layer.hpp"
AppaRao Puli071f3f22018-05-24 16:45:30 +053021
22#include <sys/stat.h>
23#include <unistd.h>
24
25#include <boost/interprocess/sync/scoped_lock.hpp>
26#include <cerrno>
AppaRao Puli9613ed72018-09-01 23:46:44 +053027#include <exception>
AppaRao Puli071f3f22018-05-24 16:45:30 +053028#include <experimental/filesystem>
29#include <fstream>
30#include <phosphor-logging/log.hpp>
AppaRao Puli9613ed72018-09-01 23:46:44 +053031#include <sdbusplus/bus/match.hpp>
32#include <sdbusplus/server/object.hpp>
AppaRao Puli071f3f22018-05-24 16:45:30 +053033#include <unordered_map>
34
35namespace ipmi
36{
37
38using 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";
Johnathan Manteyfd61fc32021-04-08 11:05:38 -070071static constexpr const char* isManagementNIC = "is_management_nic";
AppaRao Puli071f3f22018-05-24 16:45:30 +053072static constexpr const char* authTypeSupportedString = "auth_type_supported";
73static constexpr const char* accessModeString = "access_mode";
74static constexpr const char* userAuthDisabledString = "user_auth_disabled";
75static constexpr const char* perMsgAuthDisabledString = "per_msg_auth_disabled";
76static constexpr const char* alertingDisabledString = "alerting_disabled";
77static constexpr const char* privLimitString = "priv_limit";
78static constexpr const char* authTypeEnabledString = "auth_type_enabled";
79
80// Default values
81static constexpr const char* defaultChannelName = "RESERVED";
82static constexpr const uint8_t defaultMediumType =
83 static_cast<uint8_t>(EChannelMediumType::reserved);
84static constexpr const uint8_t defaultProtocolType =
85 static_cast<uint8_t>(EChannelProtocolType::reserved);
86static constexpr const uint8_t defaultSessionSupported =
87 static_cast<uint8_t>(EChannelSessSupported::none);
88static constexpr const uint8_t defaultAuthType =
89 static_cast<uint8_t>(EAuthType::none);
90static constexpr const bool defaultIsIpmiState = false;
Vernon Mauery58317122018-11-28 11:02:43 -080091static constexpr size_t smallChannelSize = 64;
AppaRao Puli071f3f22018-05-24 16:45:30 +053092
Lei YU4b0ddb62019-01-25 16:43:50 +080093std::unique_ptr<sdbusplus::bus::match_t> chPropertiesSignal
94 __attribute__((init_priority(101)));
AppaRao Puli9613ed72018-09-01 23:46:44 +053095
AppaRao Puli071f3f22018-05-24 16:45:30 +053096// String mappings use in JSON config file
97static std::unordered_map<std::string, EChannelMediumType> mediumTypeMap = {
98 {"reserved", EChannelMediumType::reserved},
99 {"ipmb", EChannelMediumType::ipmb},
100 {"icmb-v1.0", EChannelMediumType::icmbV10},
101 {"icmb-v0.9", EChannelMediumType::icmbV09},
102 {"lan-802.3", EChannelMediumType::lan8032},
103 {"serial", EChannelMediumType::serial},
104 {"other-lan", EChannelMediumType::otherLan},
105 {"pci-smbus", EChannelMediumType::pciSmbus},
106 {"smbus-v1.0", EChannelMediumType::smbusV11},
107 {"smbus-v2.0", EChannelMediumType::smbusV20},
108 {"usb-1x", EChannelMediumType::usbV1x},
109 {"usb-2x", EChannelMediumType::usbV2x},
110 {"system-interface", EChannelMediumType::systemInterface},
111 {"oem", EChannelMediumType::oem},
112 {"unknown", EChannelMediumType::unknown}};
113
ssekarf4b2b092018-07-25 18:49:08 +0530114static std::unordered_map<EInterfaceIndex, std::string> interfaceMap = {
Richard Marian Thomaiyar43cb1282018-12-08 17:22:53 +0530115 {interfaceKCS, "SMS"},
Richard Marian Thomaiyar73906b92019-01-04 23:48:02 +0530116 {interfaceLAN1, "eth0"},
ssekarf4b2b092018-07-25 18:49:08 +0530117 {interfaceUnknown, "unknown"}};
118
AppaRao Puli071f3f22018-05-24 16:45:30 +0530119static std::unordered_map<std::string, EChannelProtocolType> protocolTypeMap = {
120 {"na", EChannelProtocolType::na},
121 {"ipmb-1.0", EChannelProtocolType::ipmbV10},
122 {"icmb-2.0", EChannelProtocolType::icmbV11},
123 {"reserved", EChannelProtocolType::reserved},
124 {"ipmi-smbus", EChannelProtocolType::ipmiSmbus},
125 {"kcs", EChannelProtocolType::kcs},
126 {"smic", EChannelProtocolType::smic},
127 {"bt-10", EChannelProtocolType::bt10},
128 {"bt-15", EChannelProtocolType::bt15},
129 {"tmode", EChannelProtocolType::tMode},
130 {"oem", EChannelProtocolType::oem}};
131
132static std::array<std::string, 4> accessModeList = {
133 "disabled", "pre-boot", "always_available", "shared"};
134
135static std::array<std::string, 4> sessionSupportList = {
136 "session-less", "single-session", "multi-session", "session-based"};
137
Sumanth Bhate4e633e2019-05-14 12:13:57 +0000138const std::array<std::string, PRIVILEGE_OEM + 1> privList = {
AppaRao Puli071f3f22018-05-24 16:45:30 +0530139 "priv-reserved", "priv-callback", "priv-user",
140 "priv-operator", "priv-admin", "priv-oem"};
141
Richard Marian Thomaiyar55768e32019-03-02 22:54:37 +0530142std::string ChannelConfig::getChannelName(const uint8_t chNum)
Johnathan Mantey74a21022018-12-13 13:17:56 -0800143{
144 if (!isValidChannel(chNum))
145 {
146 log<level::ERR>("Invalid channel number.",
Richard Marian Thomaiyar619ed5f2020-01-17 12:17:47 +0530147 entry("CHANNEL_ID=%d", chNum));
Johnathan Mantey74a21022018-12-13 13:17:56 -0800148 throw std::invalid_argument("Invalid channel number");
149 }
150
151 return channelData[chNum].chName;
152}
153
154int ChannelConfig::convertToChannelNumberFromChannelName(
155 const std::string& chName)
156{
157 for (const auto& it : channelData)
158 {
159 if (it.chName == chName)
160 {
161 return it.chID;
162 }
163 }
164 log<level::ERR>("Invalid channel name.",
Richard Marian Thomaiyar619ed5f2020-01-17 12:17:47 +0530165 entry("CHANNEL=%s", chName.c_str()));
Johnathan Mantey74a21022018-12-13 13:17:56 -0800166 throw std::invalid_argument("Invalid channel name");
167
168 return -1;
169}
170
171std::string ChannelConfig::getChannelNameFromPath(const std::string& path)
AppaRao Puli9613ed72018-09-01 23:46:44 +0530172{
Richard Marian Thomaiyarbbbc3952020-01-17 12:13:28 +0530173
174 constexpr size_t length = strlen(networkIntfObjectBasePath);
175 if (((length + 1) >= path.size()) ||
176 path.compare(0, length, networkIntfObjectBasePath))
AppaRao Puli9613ed72018-09-01 23:46:44 +0530177 {
Richard Marian Thomaiyarbbbc3952020-01-17 12:13:28 +0530178 log<level::ERR>("Invalid object path.", entry("PATH=%s", path.c_str()));
179 throw std::invalid_argument("Invalid object path");
AppaRao Puli9613ed72018-09-01 23:46:44 +0530180 }
Richard Marian Thomaiyarbbbc3952020-01-17 12:13:28 +0530181 std::string chName(path, length + 1);
Johnathan Mantey74a21022018-12-13 13:17:56 -0800182 return chName;
AppaRao Puli9613ed72018-09-01 23:46:44 +0530183}
184
Johnathan Manteye5c4f1d2018-12-10 16:24:26 -0800185void ChannelConfig::processChAccessPropChange(
186 const std::string& path, const DbusChObjProperties& chProperties)
AppaRao Puli9613ed72018-09-01 23:46:44 +0530187{
188 // Get interface name from path. ex: '/xyz/openbmc_project/network/eth0'
Johnathan Mantey74a21022018-12-13 13:17:56 -0800189 std::string chName;
AppaRao Puli9613ed72018-09-01 23:46:44 +0530190 try
191 {
Johnathan Mantey74a21022018-12-13 13:17:56 -0800192 chName = getChannelNameFromPath(path);
AppaRao Puli9613ed72018-09-01 23:46:44 +0530193 }
194 catch (const std::invalid_argument& e)
195 {
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530196 log<level::ERR>("Exception: ", entry("MSG=%s", e.what()));
AppaRao Puli9613ed72018-09-01 23:46:44 +0530197 return;
198 }
199
200 // Get the MaxPrivilege property value from the signal
201 std::string intfPrivStr;
202 std::string propName;
203 for (const auto& prop : chProperties)
204 {
205 if (prop.first == privilegePropertyString)
206 {
207 propName = privilegePropertyString;
Vernon Maueryf442e112019-04-09 11:44:36 -0700208 intfPrivStr = std::get<std::string>(prop.second);
AppaRao Puli9613ed72018-09-01 23:46:44 +0530209 break;
210 }
211 }
212
213 if (propName != privilegePropertyString)
214 {
215 log<level::ERR>("Unknown signal caught.");
216 return;
217 }
218
219 if (intfPrivStr.empty())
220 {
221 log<level::ERR>("Invalid privilege string.",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530222 entry("INTF=%s", chName.c_str()));
AppaRao Puli9613ed72018-09-01 23:46:44 +0530223 return;
224 }
225
226 uint8_t intfPriv = 0;
Johnathan Mantey74a21022018-12-13 13:17:56 -0800227 int chNum;
AppaRao Puli9613ed72018-09-01 23:46:44 +0530228 try
229 {
Johnathan Manteye5c4f1d2018-12-10 16:24:26 -0800230 intfPriv = static_cast<uint8_t>(convertToPrivLimitIndex(intfPrivStr));
Johnathan Mantey74a21022018-12-13 13:17:56 -0800231 chNum = convertToChannelNumberFromChannelName(chName);
AppaRao Puli9613ed72018-09-01 23:46:44 +0530232 }
233 catch (const std::invalid_argument& e)
234 {
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530235 log<level::ERR>("Exception: ", entry("MSG=%s", e.what()));
AppaRao Puli9613ed72018-09-01 23:46:44 +0530236 return;
237 }
238
239 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
Johnathan Manteye5c4f1d2018-12-10 16:24:26 -0800240 channelLock{*channelMutex};
AppaRao Puli9613ed72018-09-01 23:46:44 +0530241 // skip updating the values, if this property change originated from IPMI.
Johnathan Manteye5c4f1d2018-12-10 16:24:26 -0800242 if (signalFlag & (1 << chNum))
AppaRao Puli9613ed72018-09-01 23:46:44 +0530243 {
Johnathan Manteye5c4f1d2018-12-10 16:24:26 -0800244 signalFlag &= ~(1 << chNum);
AppaRao Puli9613ed72018-09-01 23:46:44 +0530245 log<level::DEBUG>("Request originated from IPMI so ignoring signal");
246 return;
247 }
248
249 // Update both volatile & Non-volatile, if there is mismatch.
250 // as property change other than IPMI, has to update both volatile &
251 // non-volatile data.
Johnathan Manteye5c4f1d2018-12-10 16:24:26 -0800252 checkAndReloadVolatileData();
253 checkAndReloadNVData();
254 if (channelData[chNum].chAccess.chNonVolatileData.privLimit != intfPriv)
AppaRao Puli9613ed72018-09-01 23:46:44 +0530255 {
256 // Update NV data
Johnathan Manteye5c4f1d2018-12-10 16:24:26 -0800257 channelData[chNum].chAccess.chNonVolatileData.privLimit = intfPriv;
258 if (writeChannelPersistData() != 0)
AppaRao Puli9613ed72018-09-01 23:46:44 +0530259 {
260 log<level::ERR>("Failed to update the persist data file");
261 return;
262 }
263
264 // Update Volatile data
Johnathan Manteye5c4f1d2018-12-10 16:24:26 -0800265 if (channelData[chNum].chAccess.chVolatileData.privLimit != intfPriv)
AppaRao Puli9613ed72018-09-01 23:46:44 +0530266 {
Johnathan Manteye5c4f1d2018-12-10 16:24:26 -0800267 channelData[chNum].chAccess.chVolatileData.privLimit = intfPriv;
268 if (writeChannelVolatileData() != 0)
AppaRao Puli9613ed72018-09-01 23:46:44 +0530269 {
270 log<level::ERR>("Failed to update the volatile data file");
271 return;
272 }
273 }
274 }
275
276 return;
277}
278
AppaRao Puli071f3f22018-05-24 16:45:30 +0530279ChannelConfig& getChannelConfigObject()
280{
281 static ChannelConfig channelConfig;
282 return channelConfig;
283}
284
AppaRao Puli9613ed72018-09-01 23:46:44 +0530285ChannelConfig::~ChannelConfig()
286{
287 if (signalHndlrObjectState)
288 {
289 chPropertiesSignal.reset();
290 sigHndlrLock.unlock();
291 }
292}
293
AppaRao Puli071f3f22018-05-24 16:45:30 +0530294ChannelConfig::ChannelConfig() : bus(ipmid_get_sd_bus_connection())
295{
296 std::ofstream mutexCleanUpFile;
297 mutexCleanUpFile.open(ipmiChMutexCleanupLockFile,
298 std::ofstream::out | std::ofstream::app);
299 if (!mutexCleanUpFile.good())
300 {
301 log<level::DEBUG>("Unable to open mutex cleanup file");
302 return;
303 }
304 mutexCleanUpFile.close();
305 mutexCleanupLock =
306 boost::interprocess::file_lock(ipmiChMutexCleanupLockFile);
307 if (mutexCleanupLock.try_lock())
308 {
309 boost::interprocess::named_recursive_mutex::remove(ipmiChannelMutex);
310 channelMutex =
311 std::make_unique<boost::interprocess::named_recursive_mutex>(
312 boost::interprocess::open_or_create, ipmiChannelMutex);
313 mutexCleanupLock.lock_sharable();
314 }
315 else
316 {
317 mutexCleanupLock.lock_sharable();
318 channelMutex =
319 std::make_unique<boost::interprocess::named_recursive_mutex>(
320 boost::interprocess::open_or_create, ipmiChannelMutex);
321 }
322
323 initChannelPersistData();
AppaRao Puli9613ed72018-09-01 23:46:44 +0530324
325 sigHndlrLock = boost::interprocess::file_lock(channelNvDataFilename);
326 // Register it for single object and single process either netipimd /
327 // host-ipmid
328 if (chPropertiesSignal == nullptr && sigHndlrLock.try_lock())
329 {
330 log<level::DEBUG>("Registering channel signal handler.");
331 chPropertiesSignal = std::make_unique<sdbusplus::bus::match_t>(
332 bus,
333 sdbusplus::bus::match::rules::path_namespace(
334 networkIntfObjectBasePath) +
335 sdbusplus::bus::match::rules::type::signal() +
336 sdbusplus::bus::match::rules::member(propertiesChangedSignal) +
337 sdbusplus::bus::match::rules::interface(
338 dBusPropertiesInterface) +
339 sdbusplus::bus::match::rules::argN(0, networkChConfigIntfName),
340 [&](sdbusplus::message::message& msg) {
341 DbusChObjProperties props;
342 std::string iface;
343 std::string path = msg.get_path();
344 msg.read(iface, props);
Johnathan Manteye5c4f1d2018-12-10 16:24:26 -0800345 processChAccessPropChange(path, props);
AppaRao Puli9613ed72018-09-01 23:46:44 +0530346 });
347 signalHndlrObjectState = true;
348 }
349}
350
Richard Marian Thomaiyara45cb342018-12-03 15:08:59 +0530351bool ChannelConfig::isValidChannel(const uint8_t chNum)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530352{
353 if (chNum > maxIpmiChannels)
354 {
355 log<level::DEBUG>("Invalid channel ID - Out of range");
356 return false;
357 }
358
359 if (channelData[chNum].isChValid == false)
360 {
361 log<level::DEBUG>("Channel is not valid");
AppaRao Puli071f3f22018-05-24 16:45:30 +0530362 }
363
Johnathan Manteye5c4f1d2018-12-10 16:24:26 -0800364 return channelData[chNum].isChValid;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530365}
366
367EChannelSessSupported
Richard Marian Thomaiyara45cb342018-12-03 15:08:59 +0530368 ChannelConfig::getChannelSessionSupport(const uint8_t chNum)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530369{
370 EChannelSessSupported chSessSupport =
371 (EChannelSessSupported)channelData[chNum].chInfo.sessionSupported;
372 return chSessSupport;
373}
374
Richard Marian Thomaiyara45cb342018-12-03 15:08:59 +0530375bool ChannelConfig::isValidAuthType(const uint8_t chNum,
AppaRao Puli071f3f22018-05-24 16:45:30 +0530376 const EAuthType& authType)
377{
378 if ((authType < EAuthType::md2) || (authType > EAuthType::oem))
379 {
380 log<level::DEBUG>("Invalid authentication type");
381 return false;
382 }
383
384 uint8_t authTypeSupported = channelData[chNum].chInfo.authTypeSupported;
385 if (!(authTypeSupported & (1 << static_cast<uint8_t>(authType))))
386 {
387 log<level::DEBUG>("Authentication type is not supported.");
388 return false;
389 }
390
391 return true;
392}
393
Richard Marian Thomaiyara45cb342018-12-03 15:08:59 +0530394int ChannelConfig::getChannelActiveSessions(const uint8_t chNum)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530395{
396 // TODO: TEMPORARY FIX
Johnathan Mantey4c0435a2018-12-11 13:17:55 -0800397 // Channels active session count is managed separately
AppaRao Puli071f3f22018-05-24 16:45:30 +0530398 // by monitoring channel session which includes LAN and
399 // RAKP layer changes. This will be updated, once the
400 // authentication part is implemented.
401 return channelData[chNum].activeSessCount;
402}
403
Vernon Mauery58317122018-11-28 11:02:43 -0800404size_t ChannelConfig::getChannelMaxTransferSize(uint8_t chNum)
405{
406 return channelData[chNum].maxTransferSize;
407}
408
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000409Cc ChannelConfig::getChannelInfo(const uint8_t chNum, ChannelInfo& chInfo)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530410{
411 if (!isValidChannel(chNum))
412 {
413 log<level::DEBUG>("Invalid channel");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000414 return ccInvalidFieldRequest;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530415 }
416
417 std::copy_n(reinterpret_cast<uint8_t*>(&channelData[chNum].chInfo),
418 sizeof(channelData[chNum].chInfo),
419 reinterpret_cast<uint8_t*>(&chInfo));
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000420 return ccSuccess;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530421}
422
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000423Cc ChannelConfig::getChannelAccessData(const uint8_t chNum,
424 ChannelAccess& chAccessData)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530425{
426 if (!isValidChannel(chNum))
427 {
428 log<level::DEBUG>("Invalid channel");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000429 return ccInvalidFieldRequest;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530430 }
431
432 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
433 {
434 log<level::DEBUG>("Session-less channel doesn't have access data.");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000435 return ccActionNotSupportedForChannel;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530436 }
437
438 if (checkAndReloadVolatileData() != 0)
439 {
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000440 return ccUnspecifiedError;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530441 }
442
443 std::copy_n(
444 reinterpret_cast<uint8_t*>(&channelData[chNum].chAccess.chVolatileData),
445 sizeof(channelData[chNum].chAccess.chVolatileData),
446 reinterpret_cast<uint8_t*>(&chAccessData));
447
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000448 return ccSuccess;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530449}
450
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000451Cc ChannelConfig::setChannelAccessData(const uint8_t chNum,
452 const ChannelAccess& chAccessData,
453 const uint8_t setFlag)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530454{
455 if (!isValidChannel(chNum))
456 {
457 log<level::DEBUG>("Invalid channel");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000458 return ccInvalidFieldRequest;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530459 }
460
461 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
462 {
463 log<level::DEBUG>("Session-less channel doesn't have access data.");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000464 return ccActionNotSupportedForChannel;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530465 }
466
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000467 if ((setFlag & setAccessMode) &&
468 (!isValidAccessMode(chAccessData.accessMode)))
AppaRao Puli071f3f22018-05-24 16:45:30 +0530469 {
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000470 log<level::DEBUG>("Invalid access mode specified");
471 return ccAccessModeNotSupportedForChannel;
472 }
473 if ((setFlag & setPrivLimit) && (!isValidPrivLimit(chAccessData.privLimit)))
474 {
475 log<level::DEBUG>("Invalid privilege limit specified");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000476 return ccInvalidFieldRequest;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530477 }
478
479 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
480 channelLock{*channelMutex};
481
482 if (checkAndReloadVolatileData() != 0)
483 {
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000484 return ccUnspecifiedError;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530485 }
486
487 if (setFlag & setAccessMode)
488 {
489 channelData[chNum].chAccess.chVolatileData.accessMode =
490 chAccessData.accessMode;
491 }
492 if (setFlag & setUserAuthEnabled)
493 {
494 channelData[chNum].chAccess.chVolatileData.userAuthDisabled =
495 chAccessData.userAuthDisabled;
496 }
497 if (setFlag & setMsgAuthEnabled)
498 {
499 channelData[chNum].chAccess.chVolatileData.perMsgAuthDisabled =
500 chAccessData.perMsgAuthDisabled;
501 }
502 if (setFlag & setAlertingEnabled)
503 {
504 channelData[chNum].chAccess.chVolatileData.alertingDisabled =
505 chAccessData.alertingDisabled;
506 }
507 if (setFlag & setPrivLimit)
508 {
509 channelData[chNum].chAccess.chVolatileData.privLimit =
510 chAccessData.privLimit;
511 }
512
513 // Write Volatile data to file
514 if (writeChannelVolatileData() != 0)
515 {
516 log<level::DEBUG>("Failed to update the channel volatile data");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000517 return ccUnspecifiedError;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530518 }
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000519 return ccSuccess;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530520}
521
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000522Cc ChannelConfig::getChannelAccessPersistData(const uint8_t chNum,
523 ChannelAccess& chAccessData)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530524{
525 if (!isValidChannel(chNum))
526 {
527 log<level::DEBUG>("Invalid channel");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000528 return ccInvalidFieldRequest;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530529 }
530
531 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
532 {
533 log<level::DEBUG>("Session-less channel doesn't have access data.");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000534 return ccActionNotSupportedForChannel;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530535 }
536
537 if (checkAndReloadNVData() != 0)
538 {
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000539 return ccUnspecifiedError;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530540 }
541
542 std::copy_n(reinterpret_cast<uint8_t*>(
543 &channelData[chNum].chAccess.chNonVolatileData),
544 sizeof(channelData[chNum].chAccess.chNonVolatileData),
545 reinterpret_cast<uint8_t*>(&chAccessData));
546
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000547 return ccSuccess;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530548}
549
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000550Cc ChannelConfig::setChannelAccessPersistData(const uint8_t chNum,
551 const ChannelAccess& chAccessData,
552 const uint8_t setFlag)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530553{
554 if (!isValidChannel(chNum))
555 {
556 log<level::DEBUG>("Invalid channel");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000557 return ccInvalidFieldRequest;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530558 }
559
560 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
561 {
562 log<level::DEBUG>("Session-less channel doesn't have access data.");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000563 return ccActionNotSupportedForChannel;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530564 }
565
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000566 if ((setFlag & setAccessMode) &&
567 (!isValidAccessMode(chAccessData.accessMode)))
AppaRao Puli071f3f22018-05-24 16:45:30 +0530568 {
jayaprakash Mutyala0e2dbee2019-12-26 13:03:04 +0000569 log<level::DEBUG>("Invalid access mode specified");
570 return ccAccessModeNotSupportedForChannel;
571 }
572 if ((setFlag & setPrivLimit) && (!isValidPrivLimit(chAccessData.privLimit)))
573 {
574 log<level::DEBUG>("Invalid privilege limit specified");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000575 return ccInvalidFieldRequest;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530576 }
577
578 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
579 channelLock{*channelMutex};
580
581 if (checkAndReloadNVData() != 0)
582 {
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000583 return ccUnspecifiedError;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530584 }
585
586 if (setFlag & setAccessMode)
587 {
588 channelData[chNum].chAccess.chNonVolatileData.accessMode =
589 chAccessData.accessMode;
590 }
591 if (setFlag & setUserAuthEnabled)
592 {
593 channelData[chNum].chAccess.chNonVolatileData.userAuthDisabled =
594 chAccessData.userAuthDisabled;
595 }
596 if (setFlag & setMsgAuthEnabled)
597 {
598 channelData[chNum].chAccess.chNonVolatileData.perMsgAuthDisabled =
599 chAccessData.perMsgAuthDisabled;
600 }
601 if (setFlag & setAlertingEnabled)
602 {
603 channelData[chNum].chAccess.chNonVolatileData.alertingDisabled =
604 chAccessData.alertingDisabled;
605 }
606 if (setFlag & setPrivLimit)
607 {
AppaRao Puli9613ed72018-09-01 23:46:44 +0530608 // Send Update to network channel config interfaces over dbus
AppaRao Puli9613ed72018-09-01 23:46:44 +0530609 std::string privStr = convertToPrivLimitString(chAccessData.privLimit);
Richard Marian Thomaiyar73906b92019-01-04 23:48:02 +0530610 std::string networkIntfObj = std::string(networkIntfObjectBasePath) +
611 "/" + channelData[chNum].chName;
AppaRao Puli9613ed72018-09-01 23:46:44 +0530612 try
613 {
Johnathan Manteyf92261d2018-12-10 15:49:34 -0800614 if (0 != setDbusProperty(networkIntfServiceName, networkIntfObj,
615 networkChConfigIntfName,
AppaRao Puli9613ed72018-09-01 23:46:44 +0530616 privilegePropertyString, privStr))
617 {
Richard Marian Thomaiyar73906b92019-01-04 23:48:02 +0530618 log<level::DEBUG>(
619 "Network interface does not exist",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530620 entry("INTERFACE=%s", channelData[chNum].chName.c_str()));
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000621 return ccUnspecifiedError;
AppaRao Puli9613ed72018-09-01 23:46:44 +0530622 }
623 }
624 catch (const sdbusplus::exception::SdBusError& e)
625 {
626 log<level::ERR>("Exception: Network interface does not exist");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000627 return ccInvalidFieldRequest;
AppaRao Puli9613ed72018-09-01 23:46:44 +0530628 }
629 signalFlag |= (1 << chNum);
AppaRao Puli071f3f22018-05-24 16:45:30 +0530630 channelData[chNum].chAccess.chNonVolatileData.privLimit =
631 chAccessData.privLimit;
632 }
633
634 // Write persistent data to file
635 if (writeChannelPersistData() != 0)
636 {
637 log<level::DEBUG>("Failed to update the presist data file");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000638 return ccUnspecifiedError;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530639 }
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000640 return ccSuccess;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530641}
642
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000643Cc ChannelConfig::getChannelAuthTypeSupported(const uint8_t chNum,
644 uint8_t& authTypeSupported)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530645{
646 if (!isValidChannel(chNum))
647 {
648 log<level::DEBUG>("Invalid channel");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000649 return ccInvalidFieldRequest;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530650 }
651
652 authTypeSupported = channelData[chNum].chInfo.authTypeSupported;
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000653 return ccSuccess;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530654}
655
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000656Cc ChannelConfig::getChannelEnabledAuthType(const uint8_t chNum,
657 const uint8_t priv,
658 EAuthType& authType)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530659{
660 if (!isValidChannel(chNum))
661 {
662 log<level::DEBUG>("Invalid channel");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000663 return ccInvalidFieldRequest;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530664 }
665
666 if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
667 {
668 log<level::DEBUG>("Sessionless channel doesn't have access data.");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000669 return ccInvalidFieldRequest;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530670 }
671
672 if (!isValidPrivLimit(priv))
673 {
674 log<level::DEBUG>("Invalid privilege specified.");
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000675 return ccInvalidFieldRequest;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530676 }
677
678 // TODO: Hardcoded for now. Need to implement.
679 authType = EAuthType::none;
680
NITIN SHARMAb541a5a2019-07-18 12:46:59 +0000681 return ccSuccess;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530682}
683
684std::time_t ChannelConfig::getUpdatedFileTime(const std::string& fileName)
685{
686 struct stat fileStat;
687 if (stat(fileName.c_str(), &fileStat) != 0)
688 {
689 log<level::DEBUG>("Error in getting last updated time stamp");
690 return -EIO;
691 }
692 return fileStat.st_mtime;
693}
694
695EChannelAccessMode
696 ChannelConfig::convertToAccessModeIndex(const std::string& mode)
697{
698 auto iter = std::find(accessModeList.begin(), accessModeList.end(), mode);
699 if (iter == accessModeList.end())
700 {
701 log<level::ERR>("Invalid access mode.",
702 entry("MODE_STR=%s", mode.c_str()));
703 throw std::invalid_argument("Invalid access mode.");
704 }
705
706 return static_cast<EChannelAccessMode>(
707 std::distance(accessModeList.begin(), iter));
708}
709
Richard Marian Thomaiyara45cb342018-12-03 15:08:59 +0530710std::string ChannelConfig::convertToAccessModeString(const uint8_t value)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530711{
712 if (accessModeList.size() <= value)
713 {
714 log<level::ERR>("Invalid access mode.", entry("MODE_IDX=%d", value));
715 throw std::invalid_argument("Invalid access mode.");
716 }
717
718 return accessModeList.at(value);
719}
720
721CommandPrivilege
722 ChannelConfig::convertToPrivLimitIndex(const std::string& value)
723{
724 auto iter = std::find(privList.begin(), privList.end(), value);
725 if (iter == privList.end())
726 {
727 log<level::ERR>("Invalid privilege.",
728 entry("PRIV_STR=%s", value.c_str()));
729 throw std::invalid_argument("Invalid privilege.");
730 }
731
732 return static_cast<CommandPrivilege>(std::distance(privList.begin(), iter));
733}
734
Richard Marian Thomaiyara45cb342018-12-03 15:08:59 +0530735std::string ChannelConfig::convertToPrivLimitString(const uint8_t value)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530736{
737 if (privList.size() <= value)
738 {
739 log<level::ERR>("Invalid privilege.", entry("PRIV_IDX=%d", value));
740 throw std::invalid_argument("Invalid privilege.");
741 }
742
743 return privList.at(value);
744}
745
746EChannelSessSupported
747 ChannelConfig::convertToSessionSupportIndex(const std::string& value)
748{
749 auto iter =
750 std::find(sessionSupportList.begin(), sessionSupportList.end(), value);
751 if (iter == sessionSupportList.end())
752 {
753 log<level::ERR>("Invalid session supported.",
754 entry("SESS_STR=%s", value.c_str()));
755 throw std::invalid_argument("Invalid session supported.");
756 }
757
758 return static_cast<EChannelSessSupported>(
759 std::distance(sessionSupportList.begin(), iter));
760}
761
762EChannelMediumType
763 ChannelConfig::convertToMediumTypeIndex(const std::string& value)
764{
765 std::unordered_map<std::string, EChannelMediumType>::iterator it =
766 mediumTypeMap.find(value);
767 if (it == mediumTypeMap.end())
768 {
769 log<level::ERR>("Invalid medium type.",
770 entry("MEDIUM_STR=%s", value.c_str()));
771 throw std::invalid_argument("Invalid medium type.");
772 }
773
774 return static_cast<EChannelMediumType>(it->second);
775}
776
777EChannelProtocolType
778 ChannelConfig::convertToProtocolTypeIndex(const std::string& value)
779{
780 std::unordered_map<std::string, EChannelProtocolType>::iterator it =
781 protocolTypeMap.find(value);
782 if (it == protocolTypeMap.end())
783 {
784 log<level::ERR>("Invalid protocol type.",
785 entry("PROTO_STR=%s", value.c_str()));
786 throw std::invalid_argument("Invalid protocol type.");
787 }
788
789 return static_cast<EChannelProtocolType>(it->second);
790}
791
792Json ChannelConfig::readJsonFile(const std::string& configFile)
793{
794 std::ifstream jsonFile(configFile);
795 if (!jsonFile.good())
796 {
Richard Marian Thomaiyarc4196802019-06-03 19:27:48 +0530797 log<level::INFO>("JSON file not found",
798 entry("FILE_NAME=%s", configFile.c_str()));
AppaRao Puli071f3f22018-05-24 16:45:30 +0530799 return nullptr;
800 }
801
802 Json data = nullptr;
803 try
804 {
805 data = Json::parse(jsonFile, nullptr, false);
806 }
807 catch (Json::parse_error& e)
808 {
809 log<level::DEBUG>("Corrupted channel config.",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530810 entry("MSG=%s", e.what()));
AppaRao Puli071f3f22018-05-24 16:45:30 +0530811 throw std::runtime_error("Corrupted channel config file");
812 }
813
814 return data;
815}
816
817int ChannelConfig::writeJsonFile(const std::string& configFile,
818 const Json& jsonData)
819{
Richard Marian Thomaiyar687df402019-05-09 00:16:53 +0530820 const std::string tmpFile = configFile + "_tmp";
821 int fd = open(tmpFile.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_SYNC,
822 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
823 if (fd < 0)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530824 {
Richard Marian Thomaiyar687df402019-05-09 00:16:53 +0530825 log<level::ERR>("Error in creating json file",
826 entry("FILE_NAME = %s", tmpFile.c_str()));
827 return -EIO;
828 }
829 const auto& writeData = jsonData.dump();
830 if (write(fd, writeData.c_str(), writeData.size()) !=
831 static_cast<ssize_t>(writeData.size()))
832 {
833 close(fd);
834 log<level::ERR>("Error in writing configuration file",
835 entry("FILE_NAME = %s", tmpFile.c_str()));
836 return -EIO;
837 }
838 close(fd);
839
840 if (std::rename(tmpFile.c_str(), configFile.c_str()) != 0)
841 {
842 log<level::ERR>("Error in renaming temporary data file",
843 entry("FILE_NAME = %s", tmpFile.c_str()));
AppaRao Puli071f3f22018-05-24 16:45:30 +0530844 return -EIO;
845 }
846
AppaRao Puli071f3f22018-05-24 16:45:30 +0530847 return 0;
848}
849
Richard Marian Thomaiyara45cb342018-12-03 15:08:59 +0530850void ChannelConfig::setDefaultChannelConfig(const uint8_t chNum,
AppaRao Puli071f3f22018-05-24 16:45:30 +0530851 const std::string& chName)
852{
853 channelData[chNum].chName = chName;
854 channelData[chNum].chID = chNum;
855 channelData[chNum].isChValid = false;
856 channelData[chNum].activeSessCount = 0;
Johnathan Manteyfd61fc32021-04-08 11:05:38 -0700857 channelData[chNum].isManagementNIC = false;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530858
859 channelData[chNum].chInfo.mediumType = defaultMediumType;
860 channelData[chNum].chInfo.protocolType = defaultProtocolType;
861 channelData[chNum].chInfo.sessionSupported = defaultSessionSupported;
862 channelData[chNum].chInfo.isIpmi = defaultIsIpmiState;
863 channelData[chNum].chInfo.authTypeSupported = defaultAuthType;
864}
865
Johnathan Manteyfd61fc32021-04-08 11:05:38 -0700866uint8_t ChannelConfig::getManagementNICID()
867{
868 static bool idFound = false;
869 static uint8_t id = 0;
870
871 if (idFound)
872 {
873 return id;
874 }
875
876 for (uint8_t chIdx = 0; chIdx < maxIpmiChannels; chIdx++)
877 {
878 if (channelData[chIdx].isManagementNIC)
879 {
880 id = chIdx;
881 idFound = true;
882 break;
883 }
884 }
885
886 if (!idFound)
887 {
888 id = static_cast<uint8_t>(EChannelID::chanLan1);
889 idFound = true;
890 }
891 return id;
892}
893
AppaRao Puli071f3f22018-05-24 16:45:30 +0530894int ChannelConfig::loadChannelConfig()
895{
896 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
897 channelLock{*channelMutex};
898
899 Json data = readJsonFile(channelConfigDefaultFilename);
Johnathan Manteye5c4f1d2018-12-10 16:24:26 -0800900 if (data.empty())
AppaRao Puli071f3f22018-05-24 16:45:30 +0530901 {
902 log<level::DEBUG>("Error in opening IPMI Channel data file");
903 return -EIO;
904 }
905
Johnathan Mantey4c0435a2018-12-11 13:17:55 -0800906 channelData.fill(ChannelProperties{});
907
908 for (int chNum = 0; chNum < maxIpmiChannels; chNum++)
AppaRao Puli071f3f22018-05-24 16:45:30 +0530909 {
Johnathan Mantey4c0435a2018-12-11 13:17:55 -0800910 try
AppaRao Puli071f3f22018-05-24 16:45:30 +0530911 {
AppaRao Puli071f3f22018-05-24 16:45:30 +0530912 std::string chKey = std::to_string(chNum);
913 Json jsonChData = data[chKey].get<Json>();
914 if (jsonChData.is_null())
915 {
916 log<level::WARNING>(
917 "Channel not configured so loading default.",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530918 entry("CHANNEL_NUM=%d", chNum));
AppaRao Puli071f3f22018-05-24 16:45:30 +0530919 // If user didn't want to configure specific channel (say
920 // reserved channel), then load that index with default values.
Johnathan Mantey4c0435a2018-12-11 13:17:55 -0800921 setDefaultChannelConfig(chNum, defaultChannelName);
922 continue;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530923 }
Johnathan Mantey4c0435a2018-12-11 13:17:55 -0800924 Json jsonChInfo = jsonChData[channelInfoString].get<Json>();
925 if (jsonChInfo.is_null())
AppaRao Puli071f3f22018-05-24 16:45:30 +0530926 {
Johnathan Mantey4c0435a2018-12-11 13:17:55 -0800927 log<level::ERR>("Invalid/corrupted channel config file");
928 return -EBADMSG;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530929 }
Johnathan Mantey4c0435a2018-12-11 13:17:55 -0800930
931 ChannelProperties& chData = channelData[chNum];
932 chData.chName = jsonChData[nameString].get<std::string>();
933 chData.chID = chNum;
934 chData.isChValid = jsonChData[isValidString].get<bool>();
935 chData.activeSessCount = jsonChData.value(activeSessionsString, 0);
936 chData.maxTransferSize =
937 jsonChData.value(maxTransferSizeString, smallChannelSize);
Johnathan Manteyfd61fc32021-04-08 11:05:38 -0700938 if (jsonChData.count(isManagementNIC) != 0)
939 {
940 chData.isManagementNIC =
941 jsonChData[isManagementNIC].get<bool>();
942 }
943
Johnathan Mantey4c0435a2018-12-11 13:17:55 -0800944 std::string medTypeStr =
945 jsonChInfo[mediumTypeString].get<std::string>();
946 chData.chInfo.mediumType =
947 static_cast<uint8_t>(convertToMediumTypeIndex(medTypeStr));
948 std::string protoTypeStr =
949 jsonChInfo[protocolTypeString].get<std::string>();
950 chData.chInfo.protocolType =
951 static_cast<uint8_t>(convertToProtocolTypeIndex(protoTypeStr));
952 std::string sessStr =
953 jsonChInfo[sessionSupportedString].get<std::string>();
954 chData.chInfo.sessionSupported =
955 static_cast<uint8_t>(convertToSessionSupportIndex(sessStr));
956 chData.chInfo.isIpmi = jsonChInfo[isIpmiString].get<bool>();
957 chData.chInfo.authTypeSupported = defaultAuthType;
AppaRao Puli071f3f22018-05-24 16:45:30 +0530958 }
Johnathan Mantey4c0435a2018-12-11 13:17:55 -0800959 catch (const Json::exception& e)
960 {
961 log<level::DEBUG>("Json Exception caught.",
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530962 entry("MSG=%s", e.what()));
Johnathan Mantey4c0435a2018-12-11 13:17:55 -0800963 return -EBADMSG;
964 }
965 catch (const std::invalid_argument& e)
966 {
Ayushi Smriti05ad3412019-10-16 16:10:18 +0530967 log<level::ERR>("Corrupted config.", entry("MSG=%s", e.what()));
Johnathan Mantey4c0435a2018-12-11 13:17:55 -0800968 return -EBADMSG;
969 }
AppaRao Puli071f3f22018-05-24 16:45:30 +0530970 }
971
972 return 0;
973}
974
975int ChannelConfig::readChannelVolatileData()
976{
977 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
978 channelLock{*channelMutex};
979
980 Json data = readJsonFile(channelVolatileDataFilename);
981 if (data == nullptr)
982 {
983 log<level::DEBUG>("Error in opening IPMI Channel data file");
984 return -EIO;
985 }
AppaRao Puli071f3f22018-05-24 16:45:30 +0530986 try
987 {
988 // Fill in global structure
989 for (auto it = data.begin(); it != data.end(); ++it)
990 {
991 std::string chKey = it.key();
992 uint8_t chNum = std::stoi(chKey, nullptr, 10);
993 if ((chNum < 0) || (chNum > maxIpmiChannels))
994 {
995 log<level::DEBUG>(
996 "Invalid channel access entry in config file");
997 throw std::out_of_range("Out of range - channel number");
998 }
999 Json jsonChData = it.value();
1000 if (!jsonChData.is_null())
1001 {
1002 std::string accModeStr =
1003 jsonChData[accessModeString].get<std::string>();
1004 channelData[chNum].chAccess.chVolatileData.accessMode =
1005 static_cast<uint8_t>(convertToAccessModeIndex(accModeStr));
1006 channelData[chNum].chAccess.chVolatileData.userAuthDisabled =
1007 jsonChData[userAuthDisabledString].get<bool>();
1008 channelData[chNum].chAccess.chVolatileData.perMsgAuthDisabled =
1009 jsonChData[perMsgAuthDisabledString].get<bool>();
1010 channelData[chNum].chAccess.chVolatileData.alertingDisabled =
1011 jsonChData[alertingDisabledString].get<bool>();
1012 std::string privStr =
1013 jsonChData[privLimitString].get<std::string>();
1014 channelData[chNum].chAccess.chVolatileData.privLimit =
1015 static_cast<uint8_t>(convertToPrivLimitIndex(privStr));
1016 }
1017 else
1018 {
1019 log<level::ERR>(
1020 "Invalid/corrupted volatile channel access file",
Ayushi Smriti05ad3412019-10-16 16:10:18 +05301021 entry("FILE=%s", channelVolatileDataFilename));
AppaRao Puli071f3f22018-05-24 16:45:30 +05301022 throw std::runtime_error(
1023 "Corrupted volatile channel access file");
1024 }
1025 }
1026 }
1027 catch (const Json::exception& e)
1028 {
Ayushi Smriti05ad3412019-10-16 16:10:18 +05301029 log<level::DEBUG>("Json Exception caught.", entry("MSG=%s", e.what()));
AppaRao Puli071f3f22018-05-24 16:45:30 +05301030 throw std::runtime_error("Corrupted volatile channel access file");
1031 }
1032 catch (const std::invalid_argument& e)
1033 {
Ayushi Smriti05ad3412019-10-16 16:10:18 +05301034 log<level::ERR>("Corrupted config.", entry("MSG=%s", e.what()));
AppaRao Puli071f3f22018-05-24 16:45:30 +05301035 throw std::runtime_error("Corrupted volatile channel access file");
1036 }
1037
1038 // Update the timestamp
1039 voltFileLastUpdatedTime = getUpdatedFileTime(channelVolatileDataFilename);
1040 return 0;
1041}
1042
1043int ChannelConfig::readChannelPersistData()
1044{
1045 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
1046 channelLock{*channelMutex};
1047
1048 Json data = readJsonFile(channelNvDataFilename);
1049 if (data == nullptr)
1050 {
1051 log<level::DEBUG>("Error in opening IPMI Channel data file");
1052 return -EIO;
1053 }
AppaRao Puli071f3f22018-05-24 16:45:30 +05301054 try
1055 {
1056 // Fill in global structure
1057 for (auto it = data.begin(); it != data.end(); ++it)
1058 {
1059 std::string chKey = it.key();
1060 uint8_t chNum = std::stoi(chKey, nullptr, 10);
1061 if ((chNum < 0) || (chNum > maxIpmiChannels))
1062 {
1063 log<level::DEBUG>(
1064 "Invalid channel access entry in config file");
1065 throw std::out_of_range("Out of range - channel number");
1066 }
1067 Json jsonChData = it.value();
1068 if (!jsonChData.is_null())
1069 {
1070 std::string accModeStr =
1071 jsonChData[accessModeString].get<std::string>();
1072 channelData[chNum].chAccess.chNonVolatileData.accessMode =
1073 static_cast<uint8_t>(convertToAccessModeIndex(accModeStr));
1074 channelData[chNum].chAccess.chNonVolatileData.userAuthDisabled =
1075 jsonChData[userAuthDisabledString].get<bool>();
1076 channelData[chNum]
1077 .chAccess.chNonVolatileData.perMsgAuthDisabled =
1078 jsonChData[perMsgAuthDisabledString].get<bool>();
1079 channelData[chNum].chAccess.chNonVolatileData.alertingDisabled =
1080 jsonChData[alertingDisabledString].get<bool>();
1081 std::string privStr =
1082 jsonChData[privLimitString].get<std::string>();
1083 channelData[chNum].chAccess.chNonVolatileData.privLimit =
1084 static_cast<uint8_t>(convertToPrivLimitIndex(privStr));
1085 }
1086 else
1087 {
1088 log<level::ERR>("Invalid/corrupted nv channel access file",
Ayushi Smriti05ad3412019-10-16 16:10:18 +05301089 entry("FILE=%s", channelNvDataFilename));
AppaRao Puli071f3f22018-05-24 16:45:30 +05301090 throw std::runtime_error("Corrupted nv channel access file");
1091 }
1092 }
1093 }
1094 catch (const Json::exception& e)
1095 {
Ayushi Smriti05ad3412019-10-16 16:10:18 +05301096 log<level::DEBUG>("Json Exception caught.", entry("MSG=%s", e.what()));
AppaRao Puli071f3f22018-05-24 16:45:30 +05301097 throw std::runtime_error("Corrupted nv channel access file");
1098 }
1099 catch (const std::invalid_argument& e)
1100 {
Ayushi Smriti05ad3412019-10-16 16:10:18 +05301101 log<level::ERR>("Corrupted config.", entry("MSG=%s", e.what()));
AppaRao Puli071f3f22018-05-24 16:45:30 +05301102 throw std::runtime_error("Corrupted nv channel access file");
1103 }
1104
1105 // Update the timestamp
1106 nvFileLastUpdatedTime = getUpdatedFileTime(channelNvDataFilename);
1107 return 0;
1108}
1109
1110int ChannelConfig::writeChannelVolatileData()
1111{
1112 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
1113 channelLock{*channelMutex};
1114 Json outData;
1115
1116 try
1117 {
1118 for (uint8_t chNum = 0; chNum < maxIpmiChannels; chNum++)
1119 {
1120 if (getChannelSessionSupport(chNum) != EChannelSessSupported::none)
1121 {
1122 Json jsonObj;
1123 std::string chKey = std::to_string(chNum);
1124 std::string accModeStr = convertToAccessModeString(
1125 channelData[chNum].chAccess.chVolatileData.accessMode);
1126 jsonObj[accessModeString] = accModeStr;
1127 jsonObj[userAuthDisabledString] =
1128 channelData[chNum].chAccess.chVolatileData.userAuthDisabled;
1129 jsonObj[perMsgAuthDisabledString] =
1130 channelData[chNum]
1131 .chAccess.chVolatileData.perMsgAuthDisabled;
1132 jsonObj[alertingDisabledString] =
1133 channelData[chNum].chAccess.chVolatileData.alertingDisabled;
1134 std::string privStr = convertToPrivLimitString(
1135 channelData[chNum].chAccess.chVolatileData.privLimit);
1136 jsonObj[privLimitString] = privStr;
1137
1138 outData[chKey] = jsonObj;
1139 }
1140 }
1141 }
1142 catch (const std::invalid_argument& e)
1143 {
Ayushi Smriti05ad3412019-10-16 16:10:18 +05301144 log<level::ERR>("Corrupted config.", entry("MSG=%s", e.what()));
AppaRao Puli071f3f22018-05-24 16:45:30 +05301145 return -EINVAL;
1146 }
1147
1148 if (writeJsonFile(channelVolatileDataFilename, outData) != 0)
1149 {
1150 log<level::DEBUG>("Error in write JSON data to file");
1151 return -EIO;
1152 }
1153
1154 // Update the timestamp
1155 voltFileLastUpdatedTime = getUpdatedFileTime(channelVolatileDataFilename);
1156 return 0;
1157}
1158
1159int ChannelConfig::writeChannelPersistData()
1160{
1161 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
1162 channelLock{*channelMutex};
1163 Json outData;
1164
1165 try
1166 {
1167 for (uint8_t chNum = 0; chNum < maxIpmiChannels; chNum++)
1168 {
1169 if (getChannelSessionSupport(chNum) != EChannelSessSupported::none)
1170 {
1171 Json jsonObj;
1172 std::string chKey = std::to_string(chNum);
1173 std::string accModeStr = convertToAccessModeString(
1174 channelData[chNum].chAccess.chNonVolatileData.accessMode);
1175 jsonObj[accessModeString] = accModeStr;
1176 jsonObj[userAuthDisabledString] =
1177 channelData[chNum]
1178 .chAccess.chNonVolatileData.userAuthDisabled;
1179 jsonObj[perMsgAuthDisabledString] =
1180 channelData[chNum]
1181 .chAccess.chNonVolatileData.perMsgAuthDisabled;
1182 jsonObj[alertingDisabledString] =
1183 channelData[chNum]
1184 .chAccess.chNonVolatileData.alertingDisabled;
1185 std::string privStr = convertToPrivLimitString(
1186 channelData[chNum].chAccess.chNonVolatileData.privLimit);
1187 jsonObj[privLimitString] = privStr;
1188
1189 outData[chKey] = jsonObj;
1190 }
1191 }
1192 }
1193 catch (const std::invalid_argument& e)
1194 {
Ayushi Smriti05ad3412019-10-16 16:10:18 +05301195 log<level::ERR>("Corrupted config.", entry("MSG=%s", e.what()));
AppaRao Puli071f3f22018-05-24 16:45:30 +05301196 return -EINVAL;
1197 }
1198
1199 if (writeJsonFile(channelNvDataFilename, outData) != 0)
1200 {
1201 log<level::DEBUG>("Error in write JSON data to file");
1202 return -EIO;
1203 }
1204
1205 // Update the timestamp
1206 nvFileLastUpdatedTime = getUpdatedFileTime(channelNvDataFilename);
1207 return 0;
1208}
1209
1210int ChannelConfig::checkAndReloadNVData()
1211{
1212 std::time_t updateTime = getUpdatedFileTime(channelNvDataFilename);
1213 int ret = 0;
1214 if (updateTime != nvFileLastUpdatedTime || updateTime == -EIO)
1215 {
1216 try
1217 {
1218 ret = readChannelPersistData();
1219 }
1220 catch (const std::exception& e)
1221 {
1222 log<level::ERR>("Exception caught in readChannelPersistData.",
1223 entry("MSG=%s", e.what()));
1224 ret = -EIO;
1225 }
1226 }
1227 return ret;
1228}
1229
1230int ChannelConfig::checkAndReloadVolatileData()
1231{
1232 std::time_t updateTime = getUpdatedFileTime(channelVolatileDataFilename);
1233 int ret = 0;
1234 if (updateTime != voltFileLastUpdatedTime || updateTime == -EIO)
1235 {
1236 try
1237 {
1238 ret = readChannelVolatileData();
1239 }
1240 catch (const std::exception& e)
1241 {
1242 log<level::ERR>("Exception caught in readChannelVolatileData.",
1243 entry("MSG=%s", e.what()));
1244 ret = -EIO;
1245 }
1246 }
1247 return ret;
1248}
1249
Johnathan Manteyf92261d2018-12-10 15:49:34 -08001250int ChannelConfig::setDbusProperty(const std::string& service,
AppaRao Puli9613ed72018-09-01 23:46:44 +05301251 const std::string& objPath,
1252 const std::string& interface,
1253 const std::string& property,
1254 const DbusVariant& value)
1255{
1256 try
1257 {
1258 auto method =
1259 bus.new_method_call(service.c_str(), objPath.c_str(),
1260 "org.freedesktop.DBus.Properties", "Set");
1261
1262 method.append(interface, property, value);
1263
1264 auto reply = bus.call(method);
1265 }
1266 catch (const sdbusplus::exception::SdBusError& e)
1267 {
1268 log<level::DEBUG>("set-property failed",
Ayushi Smriti05ad3412019-10-16 16:10:18 +05301269 entry("SERVICE=%s", service.c_str()),
1270 entry("OBJPATH=%s", objPath.c_str()),
1271 entry("INTERFACE=%s", interface.c_str()),
1272 entry("PROP=%s", property.c_str()));
AppaRao Puli9613ed72018-09-01 23:46:44 +05301273 return -EIO;
1274 }
1275
1276 return 0;
1277}
1278
Johnathan Manteyf92261d2018-12-10 15:49:34 -08001279int ChannelConfig::getDbusProperty(const std::string& service,
AppaRao Puli9613ed72018-09-01 23:46:44 +05301280 const std::string& objPath,
1281 const std::string& interface,
1282 const std::string& property,
1283 DbusVariant& value)
1284{
1285 try
1286 {
1287 auto method =
1288 bus.new_method_call(service.c_str(), objPath.c_str(),
1289 "org.freedesktop.DBus.Properties", "Get");
1290
1291 method.append(interface, property);
1292
1293 auto reply = bus.call(method);
1294 reply.read(value);
1295 }
1296 catch (const sdbusplus::exception::SdBusError& e)
1297 {
1298 log<level::DEBUG>("get-property failed",
Ayushi Smriti05ad3412019-10-16 16:10:18 +05301299 entry("SERVICE=%s", service.c_str()),
1300 entry("OBJPATH=%s", objPath.c_str()),
1301 entry("INTERFACE=%s", interface.c_str()),
1302 entry("PROP=%s", property.c_str()));
AppaRao Puli9613ed72018-09-01 23:46:44 +05301303 return -EIO;
1304 }
1305 return 0;
1306}
1307
1308int ChannelConfig::syncNetworkChannelConfig()
1309{
1310 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
1311 channelLock{*channelMutex};
1312 bool isUpdated = false;
1313 for (uint8_t chNum = 0; chNum < maxIpmiChannels; chNum++)
1314 {
1315 if (getChannelSessionSupport(chNum) != EChannelSessSupported::none)
1316 {
1317 std::string intfPrivStr;
1318 try
1319 {
AppaRao Puli9613ed72018-09-01 23:46:44 +05301320 std::string networkIntfObj =
Richard Marian Thomaiyar73906b92019-01-04 23:48:02 +05301321 std::string(networkIntfObjectBasePath) + "/" +
1322 channelData[chNum].chName;
AppaRao Puli9613ed72018-09-01 23:46:44 +05301323 DbusVariant variant;
Johnathan Manteyf92261d2018-12-10 15:49:34 -08001324 if (0 != getDbusProperty(networkIntfServiceName, networkIntfObj,
AppaRao Puli9613ed72018-09-01 23:46:44 +05301325 networkChConfigIntfName,
1326 privilegePropertyString, variant))
1327 {
1328 log<level::DEBUG>("Network interface does not exist",
Ayushi Smriti05ad3412019-10-16 16:10:18 +05301329 entry("INTERFACE=%s",
Richard Marian Thomaiyar73906b92019-01-04 23:48:02 +05301330 channelData[chNum].chName.c_str()));
AppaRao Puli9613ed72018-09-01 23:46:44 +05301331 continue;
1332 }
Vernon Maueryf442e112019-04-09 11:44:36 -07001333 intfPrivStr = std::get<std::string>(variant);
AppaRao Puli9613ed72018-09-01 23:46:44 +05301334 }
Vernon Maueryf442e112019-04-09 11:44:36 -07001335 catch (const std::bad_variant_access& e)
AppaRao Puli9613ed72018-09-01 23:46:44 +05301336 {
1337 log<level::DEBUG>(
1338 "exception: Network interface does not exist");
1339 continue;
1340 }
1341 catch (const sdbusplus::exception::SdBusError& e)
1342 {
1343 log<level::DEBUG>(
1344 "exception: Network interface does not exist");
1345 continue;
1346 }
1347
1348 uint8_t intfPriv =
1349 static_cast<uint8_t>(convertToPrivLimitIndex(intfPrivStr));
1350 if (channelData[chNum].chAccess.chNonVolatileData.privLimit !=
1351 intfPriv)
1352 {
1353 isUpdated = true;
1354 channelData[chNum].chAccess.chNonVolatileData.privLimit =
1355 intfPriv;
1356 channelData[chNum].chAccess.chVolatileData.privLimit = intfPriv;
1357 }
1358 }
1359 }
1360
1361 if (isUpdated)
1362 {
1363 // Write persistent data to file
1364 if (writeChannelPersistData() != 0)
1365 {
1366 log<level::DEBUG>("Failed to update the persistent data file");
1367 return -EIO;
1368 }
1369 // Write Volatile data to file
1370 if (writeChannelVolatileData() != 0)
1371 {
1372 log<level::DEBUG>("Failed to update the channel volatile data");
1373 return -EIO;
1374 }
1375 }
1376
1377 return 0;
1378}
1379
AppaRao Puli071f3f22018-05-24 16:45:30 +05301380void ChannelConfig::initChannelPersistData()
1381{
Richard Marian Thomaiyare91474c2019-09-01 23:02:47 +05301382 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
1383 channelLock{*channelMutex};
1384
AppaRao Puli071f3f22018-05-24 16:45:30 +05301385 /* Always read the channel config */
1386 if (loadChannelConfig() != 0)
1387 {
1388 log<level::ERR>("Failed to read channel config file");
1389 throw std::ios_base::failure("Failed to load channel configuration");
1390 }
1391
1392 /* Populate the channel persist data */
1393 if (readChannelPersistData() != 0)
1394 {
1395 // Copy default NV data to RW location
1396 std::experimental::filesystem::copy_file(channelAccessDefaultFilename,
1397 channelNvDataFilename);
1398
1399 // Load the channel access NV data
1400 if (readChannelPersistData() != 0)
1401 {
1402 log<level::ERR>("Failed to read channel access NV data");
1403 throw std::ios_base::failure(
1404 "Failed to read channel access NV configuration");
1405 }
1406 }
1407
1408 // First check the volatile data file
1409 // If not present, load the default values
1410 if (readChannelVolatileData() != 0)
1411 {
1412 // Copy default volatile data to temporary location
1413 // NV file(channelNvDataFilename) must have created by now.
1414 std::experimental::filesystem::copy_file(channelNvDataFilename,
1415 channelVolatileDataFilename);
1416
1417 // Load the channel access volatile data
1418 if (readChannelVolatileData() != 0)
1419 {
1420 log<level::ERR>("Failed to read channel access volatile data");
1421 throw std::ios_base::failure(
1422 "Failed to read channel access volatile configuration");
1423 }
1424 }
AppaRao Puli9613ed72018-09-01 23:46:44 +05301425
1426 // Synchronize the channel config(priv) with network channel
1427 // configuration(priv) over dbus
1428 if (syncNetworkChannelConfig() != 0)
1429 {
1430 log<level::ERR>(
1431 "Failed to synchronize data with network channel config over dbus");
1432 throw std::ios_base::failure(
1433 "Failed to synchronize data with network channel config over dbus");
1434 }
1435
1436 log<level::DEBUG>("Successfully completed channel data initialization.");
AppaRao Puli071f3f22018-05-24 16:45:30 +05301437 return;
1438}
1439
1440} // namespace ipmi