blob: 4432ed5734b4a2da4ca63b2830a5df8dc772186b [file] [log] [blame]
Qiang XUe28d1fa2019-02-27 13:50:56 +08001/*
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
Andrew Jefferye73bd0a2023-01-25 10:39:57 +103017#include "ChassisIntrusionSensor.hpp"
18#include "Utils.hpp"
19
Ed Tanouseacbfdd2024-04-04 12:00:24 -070020#include <boost/asio/error.hpp>
Ed Tanous1f978632023-02-28 18:16:39 -080021#include <boost/asio/io_context.hpp>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070022#include <boost/asio/steady_timer.hpp>
Patrick Venture96e97db2019-10-31 13:44:38 -070023#include <boost/container/flat_map.hpp>
Patrick Williams0c42f402021-08-27 16:05:45 -050024#include <phosphor-logging/lg2.hpp>
Qiang XUe28d1fa2019-02-27 13:50:56 +080025#include <sdbusplus/asio/connection.hpp>
26#include <sdbusplus/asio/object_server.hpp>
Qiang XUe28d1fa2019-02-27 13:50:56 +080027#include <sdbusplus/bus.hpp>
Patrick Venture96e97db2019-10-31 13:44:38 -070028#include <sdbusplus/bus/match.hpp>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070029#include <sdbusplus/message.hpp>
James Feist38fb5982020-05-28 10:09:54 -070030
31#include <array>
Ed Tanous8a57ec02020-10-09 12:46:52 -070032#include <charconv>
James Feist38fb5982020-05-28 10:09:54 -070033#include <chrono>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070034#include <cstdint>
James Feist38fb5982020-05-28 10:09:54 -070035#include <ctime>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070036#include <exception>
37#include <filesystem>
James Feist38fb5982020-05-28 10:09:54 -070038#include <fstream>
39#include <functional>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070040#include <map>
James Feist38fb5982020-05-28 10:09:54 -070041#include <memory>
Patrick Venture96e97db2019-10-31 13:44:38 -070042#include <string>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070043#include <system_error>
Patrick Venture96e97db2019-10-31 13:44:38 -070044#include <utility>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070045#include <variant>
Patrick Venture96e97db2019-10-31 13:44:38 -070046#include <vector>
Qiang XUe28d1fa2019-02-27 13:50:56 +080047
Ed Tanous8a57ec02020-10-09 12:46:52 -070048static constexpr bool debug = false;
Qiang XUe28d1fa2019-02-27 13:50:56 +080049
Zev Weiss054aad82022-08-18 01:37:34 -070050static constexpr const char* sensorType = "ChassisIntrusionSensor";
51static constexpr const char* nicType = "NIC";
Brandon Kim66558232021-11-09 16:53:08 -080052static constexpr auto nicTypes{std::to_array<const char*>({nicType})};
Qiang XUe28d1fa2019-02-27 13:50:56 +080053
Chau Ly95f49932023-04-19 09:44:55 +000054static const std::map<std::string, std::string> compatibleHwmonNames = {
55 {"Aspeed2600_Hwmon", "intrusion0_alarm"}
56 // Add compatible strings here for new hwmon intrusion detection
57 // drivers that have different hwmon names but would also like to
58 // use the available Hwmon class.
59};
60
Chau Lycebb28c2022-10-21 10:01:52 +000061static void createSensorsFromConfig(
62 boost::asio::io_context& io, sdbusplus::asio::object_server& objServer,
Lei YUba637932021-03-17 10:35:00 +080063 const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
Chau Lycebb28c2022-10-21 10:01:52 +000064 std::shared_ptr<ChassisIntrusionSensor>& pSensor)
Qiang XUe28d1fa2019-02-27 13:50:56 +080065{
66 // find matched configuration according to sensor type
67 ManagedObjectType sensorConfigurations;
68 bool useCache = false;
69
70 if (!getSensorConfiguration(sensorType, dbusConnection,
71 sensorConfigurations, useCache))
72 {
George Liue9a1c9c2025-02-20 15:02:35 +080073 lg2::error("error communicating to entity manager");
Chau Lycebb28c2022-10-21 10:01:52 +000074 return;
Qiang XUe28d1fa2019-02-27 13:50:56 +080075 }
76
77 const SensorData* sensorData = nullptr;
Zev Weissafd15042022-07-18 12:28:40 -070078 const std::pair<std::string, SensorBaseConfigMap>* baseConfiguration =
79 nullptr;
Qiang XUe28d1fa2019-02-27 13:50:56 +080080
Zev Weissf343b8a2022-08-12 18:21:01 -070081 for (const auto& [path, cfgData] : sensorConfigurations)
Qiang XUe28d1fa2019-02-27 13:50:56 +080082 {
83 baseConfiguration = nullptr;
Zev Weissf343b8a2022-08-12 18:21:01 -070084 sensorData = &cfgData;
Qiang XUe28d1fa2019-02-27 13:50:56 +080085
86 // match sensor type
Zev Weiss054aad82022-08-18 01:37:34 -070087 auto sensorBase = sensorData->find(configInterfaceName(sensorType));
Qiang XUe28d1fa2019-02-27 13:50:56 +080088 if (sensorBase == sensorData->end())
89 {
George Liue9a1c9c2025-02-20 15:02:35 +080090 lg2::error("error finding base configuration");
Qiang XUe28d1fa2019-02-27 13:50:56 +080091 continue;
92 }
93
94 baseConfiguration = &(*sensorBase);
95
Chau Lyb318dca2022-10-26 04:12:52 +000096 // Rearm defaults to "Automatic" mode
97 bool autoRearm = true;
98 auto findRearm = baseConfiguration->second.find("Rearm");
99 if (findRearm != baseConfiguration->second.end())
100 {
101 std::string rearmStr = std::get<std::string>(findRearm->second);
102 if (rearmStr != "Automatic" && rearmStr != "Manual")
103 {
George Liue9a1c9c2025-02-20 15:02:35 +0800104 lg2::error("Wrong input for Rearm parameter");
Chau Lyb318dca2022-10-26 04:12:52 +0000105 continue;
106 }
107 autoRearm = (rearmStr == "Automatic");
108 }
109
Chau Ly95f49932023-04-19 09:44:55 +0000110 // judge class, "Gpio", "Hwmon" or "I2C"
Qiang XUe28d1fa2019-02-27 13:50:56 +0800111 auto findClass = baseConfiguration->second.find("Class");
Chau Ly95f49932023-04-19 09:44:55 +0000112 if (findClass != baseConfiguration->second.end())
Qiang XUe28d1fa2019-02-27 13:50:56 +0800113 {
Chau Ly95f49932023-04-19 09:44:55 +0000114 auto classString = std::get<std::string>(findClass->second);
115 if (classString == "Gpio")
116 {
117 auto findGpioPolarity =
118 baseConfiguration->second.find("GpioPolarity");
Qiang XUe28d1fa2019-02-27 13:50:56 +0800119
Chau Ly95f49932023-04-19 09:44:55 +0000120 if (findGpioPolarity == baseConfiguration->second.end())
121 {
George Liue9a1c9c2025-02-20 15:02:35 +0800122 lg2::error("error finding gpio polarity in configuration");
Chau Ly95f49932023-04-19 09:44:55 +0000123 continue;
124 }
Qiang XUe28d1fa2019-02-27 13:50:56 +0800125
Chau Ly95f49932023-04-19 09:44:55 +0000126 try
Chau Lycebb28c2022-10-21 10:01:52 +0000127 {
Chau Ly95f49932023-04-19 09:44:55 +0000128 bool gpioInverted =
129 (std::get<std::string>(findGpioPolarity->second) ==
130 "Low");
131 pSensor = std::make_shared<ChassisIntrusionGpioSensor>(
Chau Lyb318dca2022-10-26 04:12:52 +0000132 autoRearm, io, objServer, gpioInverted);
Chau Ly95f49932023-04-19 09:44:55 +0000133 pSensor->start();
134 if (debug)
135 {
George Liue9a1c9c2025-02-20 15:02:35 +0800136 lg2::info(
137 "find chassis intrusion sensor polarity inverted flag is '{GPIO_INVERTED}'",
138 "GPIO_INVERTED", gpioInverted);
Chau Ly95f49932023-04-19 09:44:55 +0000139 }
140 return;
Chau Lycebb28c2022-10-21 10:01:52 +0000141 }
Chau Ly95f49932023-04-19 09:44:55 +0000142 catch (const std::bad_variant_access& e)
Chau Lycebb28c2022-10-21 10:01:52 +0000143 {
George Liue9a1c9c2025-02-20 15:02:35 +0800144 lg2::error("invalid value for gpio info in config.");
Chau Ly95f49932023-04-19 09:44:55 +0000145 continue;
Chau Lycebb28c2022-10-21 10:01:52 +0000146 }
Chau Ly95f49932023-04-19 09:44:55 +0000147 catch (const std::exception& e)
148 {
George Liue9a1c9c2025-02-20 15:02:35 +0800149 lg2::error(
150 "error creating chassis intrusion gpio sensor: '{ERROR}'",
151 "ERROR", e);
Chau Ly95f49932023-04-19 09:44:55 +0000152 continue;
153 }
Qiang XUe28d1fa2019-02-27 13:50:56 +0800154 }
Chau Ly95f49932023-04-19 09:44:55 +0000155 // If class string contains Hwmon string
156 else if (classString.find("Hwmon") != std::string::npos)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800157 {
Chau Ly95f49932023-04-19 09:44:55 +0000158 std::string hwmonName;
159 std::map<std::string, std::string>::const_iterator
160 compatIterator = compatibleHwmonNames.find(classString);
161
162 if (compatIterator == compatibleHwmonNames.end())
163 {
George Liue9a1c9c2025-02-20 15:02:35 +0800164 lg2::error("Hwmon Class string is not supported");
Chau Ly95f49932023-04-19 09:44:55 +0000165 continue;
166 }
167
168 hwmonName = compatIterator->second;
169
170 try
171 {
172 pSensor = std::make_shared<ChassisIntrusionHwmonSensor>(
Chau Lyb318dca2022-10-26 04:12:52 +0000173 autoRearm, io, objServer, hwmonName);
Chau Ly95f49932023-04-19 09:44:55 +0000174 pSensor->start();
175 return;
176 }
177 catch (const std::exception& e)
178 {
George Liue9a1c9c2025-02-20 15:02:35 +0800179 lg2::error(
180 "error creating chassis intrusion hwmon sensor: '{ERROR}'",
181 "ERROR", e);
Chau Ly95f49932023-04-19 09:44:55 +0000182 continue;
183 }
Qiang XUe28d1fa2019-02-27 13:50:56 +0800184 }
Chau Ly95f49932023-04-19 09:44:55 +0000185 else
Qiang XUe28d1fa2019-02-27 13:50:56 +0800186 {
Chau Ly95f49932023-04-19 09:44:55 +0000187 auto findBus = baseConfiguration->second.find("Bus");
188 auto findAddress = baseConfiguration->second.find("Address");
189 if (findBus == baseConfiguration->second.end() ||
190 findAddress == baseConfiguration->second.end())
191 {
George Liue9a1c9c2025-02-20 15:02:35 +0800192 lg2::error("error finding bus or address in configuration");
Chau Ly95f49932023-04-19 09:44:55 +0000193 continue;
194 }
195 try
196 {
197 int busId = std::get<uint64_t>(findBus->second);
198 int slaveAddr = std::get<uint64_t>(findAddress->second);
199 pSensor = std::make_shared<ChassisIntrusionPchSensor>(
Chau Lyb318dca2022-10-26 04:12:52 +0000200 autoRearm, io, objServer, busId, slaveAddr);
Chau Ly95f49932023-04-19 09:44:55 +0000201 pSensor->start();
202 if (debug)
203 {
George Liue9a1c9c2025-02-20 15:02:35 +0800204 lg2::info(
205 "find matched bus '{BUS}', matched slave addr '{ADDR}'",
206 "BUS", busId, "ADDR", slaveAddr);
Chau Ly95f49932023-04-19 09:44:55 +0000207 }
208 return;
209 }
210 catch (const std::bad_variant_access& e)
211 {
George Liue9a1c9c2025-02-20 15:02:35 +0800212 lg2::error("invalid value for bus or address in config.");
Chau Ly95f49932023-04-19 09:44:55 +0000213 continue;
214 }
215 catch (const std::exception& e)
216 {
George Liue9a1c9c2025-02-20 15:02:35 +0800217 lg2::error(
218 "error creating chassis intrusion pch sensor: '{ERROR}'",
219 "ERROR", e);
Chau Ly95f49932023-04-19 09:44:55 +0000220 continue;
221 }
Qiang XUe28d1fa2019-02-27 13:50:56 +0800222 }
Qiang XUe28d1fa2019-02-27 13:50:56 +0800223 }
224 }
225
George Liue9a1c9c2025-02-20 15:02:35 +0800226 lg2::error("Can't find matched I2C, GPIO or Hwmon configuration");
Chau Lycebb28c2022-10-21 10:01:52 +0000227
228 // Make sure nothing runs when there's failure in configuration for the
229 // sensor after rescan
230 if (pSensor)
231 {
George Liue9a1c9c2025-02-20 15:02:35 +0800232 lg2::error("Reset the occupied sensor pointer");
Chau Lycebb28c2022-10-21 10:01:52 +0000233 pSensor = nullptr;
234 }
Qiang XUe28d1fa2019-02-27 13:50:56 +0800235}
236
Qiang XU88b7f282019-08-14 22:51:43 +0800237static constexpr bool debugLanLeash = false;
238boost::container::flat_map<int, bool> lanStatusMap;
Qiang XU74ddf862019-09-12 17:12:13 +0800239boost::container::flat_map<int, std::string> lanInfoMap;
Qiang XU88b7f282019-08-14 22:51:43 +0800240boost::container::flat_map<std::string, int> pathSuffixMap;
241
Lei YUba637932021-03-17 10:35:00 +0800242static void getNicNameInfo(
243 const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
Qiang XU74ddf862019-09-12 17:12:13 +0800244{
245 auto getter = std::make_shared<GetSensorConfiguration>(
Patrick Williams597e8422023-10-20 11:19:01 -0500246 dbusConnection, [](const ManagedObjectType& sensorConfigurations) {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400247 // Get NIC name and save to map
248 lanInfoMap.clear();
249 for (const auto& [path, cfgData] : sensorConfigurations)
Qiang XU74ddf862019-09-12 17:12:13 +0800250 {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400251 const std::pair<std::string, SensorBaseConfigMap>*
252 baseConfiguration = nullptr;
Qiang XU74ddf862019-09-12 17:12:13 +0800253
Patrick Williams2aaf7172024-08-16 15:20:40 -0400254 // find base configuration
255 auto sensorBase = cfgData.find(configInterfaceName(nicType));
256 if (sensorBase == cfgData.end())
Qiang XU74ddf862019-09-12 17:12:13 +0800257 {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400258 continue;
259 }
260 baseConfiguration = &(*sensorBase);
261
262 auto findEthIndex = baseConfiguration->second.find("EthIndex");
263 auto findName = baseConfiguration->second.find("Name");
264
265 if (findEthIndex != baseConfiguration->second.end() &&
266 findName != baseConfiguration->second.end())
267 {
268 const auto* pEthIndex =
269 std::get_if<uint64_t>(&findEthIndex->second);
270 const auto* pName =
271 std::get_if<std::string>(&findName->second);
272 if (pEthIndex != nullptr && pName != nullptr)
Qiang XU74ddf862019-09-12 17:12:13 +0800273 {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400274 lanInfoMap[*pEthIndex] = *pName;
275 if (debugLanLeash)
276 {
George Liue9a1c9c2025-02-20 15:02:35 +0800277 lg2::info("find name of eth{ETH_INDEX} is '{NAME}'",
278 "ETH_INDEX", *pEthIndex, "NAME", *pName);
Patrick Williams2aaf7172024-08-16 15:20:40 -0400279 }
Qiang XU74ddf862019-09-12 17:12:13 +0800280 }
281 }
282 }
283
Patrick Williams2aaf7172024-08-16 15:20:40 -0400284 if (lanInfoMap.empty())
285 {
George Liue9a1c9c2025-02-20 15:02:35 +0800286 lg2::error("can't find matched NIC name.");
Patrick Williams2aaf7172024-08-16 15:20:40 -0400287 }
288 });
Qiang XU74ddf862019-09-12 17:12:13 +0800289
290 getter->getConfiguration(
291 std::vector<std::string>{nicTypes.begin(), nicTypes.end()});
292}
293
Patrick Williams92f8f512022-07-22 19:26:55 -0500294static void processLanStatusChange(sdbusplus::message_t& message)
Qiang XU88b7f282019-08-14 22:51:43 +0800295{
296 const std::string& pathName = message.get_path();
297 std::string interfaceName;
Zev Weissafd15042022-07-18 12:28:40 -0700298 SensorBaseConfigMap properties;
Qiang XU88b7f282019-08-14 22:51:43 +0800299 message.read(interfaceName, properties);
300
301 auto findStateProperty = properties.find("OperationalState");
302 if (findStateProperty == properties.end())
303 {
304 return;
305 }
Qiang XU74ddf862019-09-12 17:12:13 +0800306 std::string* pState =
307 std::get_if<std::string>(&(findStateProperty->second));
Qiang XU88b7f282019-08-14 22:51:43 +0800308 if (pState == nullptr)
309 {
George Liue9a1c9c2025-02-20 15:02:35 +0800310 lg2::error("invalid OperationalState");
Qiang XU88b7f282019-08-14 22:51:43 +0800311 return;
312 }
313
314 bool newLanConnected = (*pState == "routable" || *pState == "carrier" ||
315 *pState == "degraded");
316
317 // get ethNum from path. /org/freedesktop/network1/link/_32 for eth0
Brad Bishopfbb44ad2019-11-08 09:42:37 -0500318 size_t pos = pathName.find("/_");
Qiang XU88b7f282019-08-14 22:51:43 +0800319 if (pos == std::string::npos || pathName.length() <= pos + 2)
320 {
George Liue9a1c9c2025-02-20 15:02:35 +0800321 lg2::error("unexpected path name '{NAME}'", "NAME", pathName);
Qiang XU88b7f282019-08-14 22:51:43 +0800322 return;
323 }
324 std::string suffixStr = pathName.substr(pos + 2);
325
326 auto findEthNum = pathSuffixMap.find(suffixStr);
327 if (findEthNum == pathSuffixMap.end())
328 {
George Liue9a1c9c2025-02-20 15:02:35 +0800329 lg2::error("unexpected eth for suffixStr '{SUFFIX}'", "SUFFIX",
330 suffixStr);
Qiang XU88b7f282019-08-14 22:51:43 +0800331 return;
332 }
333 int ethNum = findEthNum->second;
Qiang XU74ddf862019-09-12 17:12:13 +0800334
335 // get lan status from map
Qiang XU88b7f282019-08-14 22:51:43 +0800336 auto findLanStatus = lanStatusMap.find(ethNum);
337 if (findLanStatus == lanStatusMap.end())
338 {
George Liue9a1c9c2025-02-20 15:02:35 +0800339 lg2::error("unexpected eth{ETH_INDEX} is lanStatusMap", "ETH_INDEX",
340 ethNum);
Qiang XU88b7f282019-08-14 22:51:43 +0800341 return;
342 }
343 bool oldLanConnected = findLanStatus->second;
344
Qiang XU74ddf862019-09-12 17:12:13 +0800345 // get lan info from map
Ed Tanous2049bd22022-07-09 07:20:26 -0700346 std::string lanInfo;
347 if (!lanInfoMap.empty())
Qiang XU74ddf862019-09-12 17:12:13 +0800348 {
349 auto findLanInfo = lanInfoMap.find(ethNum);
350 if (findLanInfo == lanInfoMap.end())
351 {
George Liue9a1c9c2025-02-20 15:02:35 +0800352 lg2::error("unexpected eth{ETH_INDEX} is lanInfoMap", "ETH_INDEX",
353 ethNum);
Qiang XU74ddf862019-09-12 17:12:13 +0800354 }
355 else
356 {
357 lanInfo = "(" + findLanInfo->second + ")";
358 }
359 }
360
Qiang XU88b7f282019-08-14 22:51:43 +0800361 if (debugLanLeash)
362 {
George Liue9a1c9c2025-02-20 15:02:35 +0800363 lg2::info(
364 "ethNum = {ETH_INDEX}, state = {LAN_STATUS}, oldLanConnected = {OLD_LAN_CONNECTED}, "
365 "newLanConnected = {NEW_LAN_CONNECTED}",
366 "ETH_INDEX", ethNum, "LAN_STATUS", *pState, "OLD_LAN_CONNECTED",
367 (oldLanConnected ? "true" : "false"), "NEW_LAN_CONNECTED",
368 (newLanConnected ? "true" : "false"));
Qiang XU88b7f282019-08-14 22:51:43 +0800369 }
370
371 if (oldLanConnected != newLanConnected)
372 {
Qiang XU74ddf862019-09-12 17:12:13 +0800373 std::string strEthNum = "eth" + std::to_string(ethNum) + lanInfo;
Ed Tanous2049bd22022-07-09 07:20:26 -0700374 const auto* strState = newLanConnected ? "connected" : "lost";
Patrick Williams2aaf7172024-08-16 15:20:40 -0400375 const auto* strMsgId =
376 newLanConnected ? "OpenBMC.0.1.LanRegained" : "OpenBMC.0.1.LanLost";
Patrick Williams0c42f402021-08-27 16:05:45 -0500377
George Liue9a1c9c2025-02-20 15:02:35 +0800378 lg2::info("'{ETH_INFO}' LAN leash '{LAN_STATUS}'", "ETH_INFO",
379 strEthNum, "LAN_STATUS", strState, "REDFISH_MESSAGE_ID",
380 strMsgId, "REDFISH_MESSAGE_ARGS", strEthNum);
Patrick Williams0c42f402021-08-27 16:05:45 -0500381
Qiang XU88b7f282019-08-14 22:51:43 +0800382 lanStatusMap[ethNum] = newLanConnected;
Qiang XU88b7f282019-08-14 22:51:43 +0800383 }
384}
385
Lei YUdd68d4a2021-03-16 22:17:23 +0800386/** @brief Initialize the lan status.
387 *
388 * @return true on success and false on failure
389 */
Lei YUba637932021-03-17 10:35:00 +0800390static bool initializeLanStatus(
391 const std::shared_ptr<sdbusplus::asio::connection>& conn)
Qiang XU88b7f282019-08-14 22:51:43 +0800392{
Qiang XU74ddf862019-09-12 17:12:13 +0800393 // init lan port name from configuration
394 getNicNameInfo(conn);
395
396 // get eth info from sysfs
Ed Tanous2e466962025-01-30 10:59:49 -0800397 std::vector<std::filesystem::path> files;
398 if (!findFiles(std::filesystem::path("/sys/class/net/"),
399 R"(eth\d+/ifindex)", files))
Qiang XU88b7f282019-08-14 22:51:43 +0800400 {
George Liue9a1c9c2025-02-20 15:02:35 +0800401 lg2::error("No eth in system");
Lei YUdd68d4a2021-03-16 22:17:23 +0800402 return false;
Qiang XU88b7f282019-08-14 22:51:43 +0800403 }
404
405 // iterate through all found eth files, and save ifindex
Ed Tanous2e466962025-01-30 10:59:49 -0800406 for (const std::filesystem::path& fileName : files)
Qiang XU88b7f282019-08-14 22:51:43 +0800407 {
408 if (debugLanLeash)
409 {
George Liue9a1c9c2025-02-20 15:02:35 +0800410 lg2::info("Reading '{NAME}'", "NAME", fileName);
Qiang XU88b7f282019-08-14 22:51:43 +0800411 }
412 std::ifstream sysFile(fileName);
413 if (!sysFile.good())
414 {
George Liue9a1c9c2025-02-20 15:02:35 +0800415 lg2::error("Failure reading '{NAME}'", "NAME", fileName);
Qiang XU88b7f282019-08-14 22:51:43 +0800416 continue;
417 }
418 std::string line;
419 getline(sysFile, line);
420 const uint8_t ifindex = std::stoi(line);
421 // pathSuffix is ASCII of ifindex
422 const std::string& pathSuffix = std::to_string(ifindex + 30);
423
424 // extract ethNum
425 const std::string& fileStr = fileName.string();
426 const int pos = fileStr.find("eth");
427 const std::string& ethNumStr = fileStr.substr(pos + 3);
428 int ethNum = 0;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700429 std::from_chars_result r = std::from_chars(
430 ethNumStr.data(), ethNumStr.data() + ethNumStr.size(), ethNum);
431 if (r.ec != std::errc())
Qiang XU88b7f282019-08-14 22:51:43 +0800432 {
George Liue9a1c9c2025-02-20 15:02:35 +0800433 lg2::error("invalid ethNum string: '{ETH_INDEX}'", "ETH_INDEX",
434 ethNumStr);
Qiang XU88b7f282019-08-14 22:51:43 +0800435 continue;
436 }
437
438 // save pathSuffix
439 pathSuffixMap[pathSuffix] = ethNum;
440 if (debugLanLeash)
441 {
George Liue9a1c9c2025-02-20 15:02:35 +0800442 lg2::info(
443 "ethNum = {ETH_INDEX}, ifindex = {LINE}, pathSuffix = {PATH}",
444 "ETH_INDEX", ethNum, "LINE", line, "PATH", pathSuffix);
Qiang XU88b7f282019-08-14 22:51:43 +0800445 }
446
Qiang XU74ddf862019-09-12 17:12:13 +0800447 // init lan connected status from networkd
Qiang XU88b7f282019-08-14 22:51:43 +0800448 conn->async_method_call(
449 [ethNum](boost::system::error_code ec,
450 const std::variant<std::string>& property) {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400451 lanStatusMap[ethNum] = false;
452 if (ec)
453 {
George Liue9a1c9c2025-02-20 15:02:35 +0800454 lg2::error("Error reading init status of eth{ETH_INDEX}",
455 "ETH_INDEX", ethNum);
Patrick Williams2aaf7172024-08-16 15:20:40 -0400456 return;
457 }
458 const std::string* pState = std::get_if<std::string>(&property);
459 if (pState == nullptr)
460 {
George Liue9a1c9c2025-02-20 15:02:35 +0800461 lg2::error("Unable to read lan status value");
Patrick Williams2aaf7172024-08-16 15:20:40 -0400462 return;
463 }
464 bool isLanConnected =
465 (*pState == "routable" || *pState == "carrier" ||
466 *pState == "degraded");
467 if (debugLanLeash)
468 {
George Liue9a1c9c2025-02-20 15:02:35 +0800469 lg2::info(
470 "ethNum = {ETH_INDEX}, init LAN status = {STATUS}",
471 "ETH_INDEX", ethNum, "STATUS",
472 (isLanConnected ? "true" : "false"));
Patrick Williams2aaf7172024-08-16 15:20:40 -0400473 }
474 lanStatusMap[ethNum] = isLanConnected;
475 },
Qiang XU88b7f282019-08-14 22:51:43 +0800476 "org.freedesktop.network1",
477 "/org/freedesktop/network1/link/_" + pathSuffix,
478 "org.freedesktop.DBus.Properties", "Get",
479 "org.freedesktop.network1.Link", "OperationalState");
480 }
Lei YUdd68d4a2021-03-16 22:17:23 +0800481 return true;
Qiang XU88b7f282019-08-14 22:51:43 +0800482}
483
Qiang XUe28d1fa2019-02-27 13:50:56 +0800484int main()
485{
Chau Lycebb28c2022-10-21 10:01:52 +0000486 std::shared_ptr<ChassisIntrusionSensor> intrusionSensor;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800487
488 // setup connection to dbus
Ed Tanous1f978632023-02-28 18:16:39 -0800489 boost::asio::io_context io;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800490 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
Qiang XUe28d1fa2019-02-27 13:50:56 +0800491
492 // setup object server, define interface
493 systemBus->request_name("xyz.openbmc_project.IntrusionSensor");
494
Ed Tanous14ed5e92022-07-12 15:50:23 -0700495 sdbusplus::asio::object_server objServer(systemBus, true);
496
Chau Ly889af822023-02-20 07:13:52 +0000497 objServer.add_manager("/xyz/openbmc_project/Chassis");
Ed Tanous14ed5e92022-07-12 15:50:23 -0700498
Chau Lycebb28c2022-10-21 10:01:52 +0000499 createSensorsFromConfig(io, objServer, systemBus, intrusionSensor);
Qiang XUe28d1fa2019-02-27 13:50:56 +0800500
501 // callback to handle configuration change
Ian Woloschin0df80a12023-11-06 14:27:44 +0000502 boost::asio::steady_timer filterTimer(io);
Patrick Williams92f8f512022-07-22 19:26:55 -0500503 std::function<void(sdbusplus::message_t&)> eventHandler =
504 [&](sdbusplus::message_t& message) {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400505 if (message.is_method_error())
Ian Woloschin0df80a12023-11-06 14:27:44 +0000506 {
George Liue9a1c9c2025-02-20 15:02:35 +0800507 lg2::error("callback method error");
Ian Woloschin0df80a12023-11-06 14:27:44 +0000508 return;
509 }
Patrick Williams2aaf7172024-08-16 15:20:40 -0400510 // this implicitly cancels the timer
511 filterTimer.expires_after(std::chrono::seconds(1));
512 filterTimer.async_wait([&](const boost::system::error_code& ec) {
513 if (ec == boost::asio::error::operation_aborted)
514 {
515 // timer was cancelled
516 return;
517 }
George Liue9a1c9c2025-02-20 15:02:35 +0800518 lg2::info("rescan due to configuration change");
Patrick Williams2aaf7172024-08-16 15:20:40 -0400519 createSensorsFromConfig(io, objServer, systemBus,
520 intrusionSensor);
521 });
522 };
Qiang XUe28d1fa2019-02-27 13:50:56 +0800523
Zev Weiss214d9712022-08-12 12:54:31 -0700524 std::vector<std::unique_ptr<sdbusplus::bus::match_t>> matches =
525 setupPropertiesChangedMatches(
526 *systemBus, std::to_array<const char*>({sensorType}), eventHandler);
Qiang XUe28d1fa2019-02-27 13:50:56 +0800527
Lei YUdd68d4a2021-03-16 22:17:23 +0800528 if (initializeLanStatus(systemBus))
529 {
530 // add match to monitor lan status change
Patrick Williams92f8f512022-07-22 19:26:55 -0500531 sdbusplus::bus::match_t lanStatusMatch(
532 static_cast<sdbusplus::bus_t&>(*systemBus),
Lei YUdd68d4a2021-03-16 22:17:23 +0800533 "type='signal', member='PropertiesChanged',"
534 "arg0namespace='org.freedesktop.network1.Link'",
Patrick Williams92f8f512022-07-22 19:26:55 -0500535 [](sdbusplus::message_t& msg) { processLanStatusChange(msg); });
Lei YUdd68d4a2021-03-16 22:17:23 +0800536
537 // add match to monitor entity manager signal about nic name config
538 // change
Patrick Williams92f8f512022-07-22 19:26:55 -0500539 sdbusplus::bus::match_t lanConfigMatch(
540 static_cast<sdbusplus::bus_t&>(*systemBus),
Lei YUdd68d4a2021-03-16 22:17:23 +0800541 "type='signal', member='PropertiesChanged',path_namespace='" +
Zev Weiss054aad82022-08-18 01:37:34 -0700542 std::string(inventoryPath) + "',arg0namespace='" +
543 configInterfaceName(nicType) + "'",
Patrick Williams92f8f512022-07-22 19:26:55 -0500544 [&systemBus](sdbusplus::message_t& msg) {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400545 if (msg.is_method_error())
546 {
George Liue9a1c9c2025-02-20 15:02:35 +0800547 lg2::error("callback method error");
Patrick Williams2aaf7172024-08-16 15:20:40 -0400548 return;
549 }
550 getNicNameInfo(systemBus);
551 });
Lei YUdd68d4a2021-03-16 22:17:23 +0800552 }
Qiang XU88b7f282019-08-14 22:51:43 +0800553
Qiang XUe28d1fa2019-02-27 13:50:56 +0800554 io.run();
555
556 return 0;
557}