Log physical security event of lan leash
Log event of lan link status change by processing dbus signal sent by
networkd in systemd.
Tested:
Unplug network cable of dedicate NIC
Check the below log message in
https://$bmcip/redfish/v1/Systems/system/LogServices/EventLog/Entries
"Message": "Physical Security: eth0 LAN leash lost is asserted"
Change-Id: I16cf41a93896355aa28aaeb07cb16bc788b1abf1
Signed-off-by: Qiang XU <qiang.xu@linux.intel.com>
diff --git a/src/IntrusionSensorMain.cpp b/src/IntrusionSensorMain.cpp
index 2def3c1..2c8628b 100644
--- a/src/IntrusionSensorMain.cpp
+++ b/src/IntrusionSensorMain.cpp
@@ -14,12 +14,15 @@
// limitations under the License.
*/
+#include <systemd/sd-journal.h>
+
#include <ChassisIntrusionSensor.hpp>
#include <Utils.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/asio.hpp>
#include <chrono>
#include <ctime>
+#include <fstream>
#include <iostream>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
@@ -34,6 +37,8 @@
static constexpr const char* sensorType =
"xyz.openbmc_project.Configuration.ChassisIntrusionSensor";
+namespace fs = std::filesystem;
+
static bool getIntrusionSensorConfig(
std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
IntrusionSensorType* pType, int* pBusId, int* pSlaveAddr, int* pGpioIndex,
@@ -173,6 +178,178 @@
return false;
}
+static constexpr bool debugLanLeash = false;
+boost::container::flat_map<int, bool> lanStatusMap;
+boost::container::flat_map<std::string, int> pathSuffixMap;
+
+static void processLanStatusChange(sdbusplus::message::message& message)
+{
+ const std::string& pathName = message.get_path();
+ std::string interfaceName;
+ boost::container::flat_map<std::string, BasicVariantType> properties;
+ message.read(interfaceName, properties);
+
+ auto findStateProperty = properties.find("OperationalState");
+ if (findStateProperty == properties.end())
+ {
+ return;
+ }
+ std::string* pState = sdbusplus::message::variant_ns::get_if<std::string>(
+ &(findStateProperty->second));
+ if (pState == nullptr)
+ {
+ std::cerr << "invalid OperationalState \n";
+ return;
+ }
+
+ bool newLanConnected = (*pState == "routable" || *pState == "carrier" ||
+ *pState == "degraded");
+
+ // get ethNum from path. /org/freedesktop/network1/link/_32 for eth0
+ int pos = pathName.find("/_");
+ if (pos == std::string::npos || pathName.length() <= pos + 2)
+ {
+ std::cerr << "unexpected path name " << pathName << "\n";
+ return;
+ }
+ std::string suffixStr = pathName.substr(pos + 2);
+
+ auto findEthNum = pathSuffixMap.find(suffixStr);
+ if (findEthNum == pathSuffixMap.end())
+ {
+ std::cerr << "unexpected eth for suffixStr " << suffixStr << "\n";
+ return;
+ }
+ int ethNum = findEthNum->second;
+ auto findLanStatus = lanStatusMap.find(ethNum);
+ if (findLanStatus == lanStatusMap.end())
+ {
+ std::cerr << "unexpected eth " << ethNum << " in lanStatusMap \n";
+ return;
+ }
+ bool oldLanConnected = findLanStatus->second;
+
+ if (debugLanLeash)
+ {
+ std::cout << "ethNum = " << ethNum << ", state = " << *pState
+ << ", oldLanConnected = "
+ << (oldLanConnected ? "true" : "false")
+ << ", newLanConnected = "
+ << (newLanConnected ? "true" : "false") << "\n";
+ }
+
+ if (oldLanConnected != newLanConnected)
+ {
+ std::string strEthNum = "eth" + std::to_string(ethNum);
+ std::string strEvent = strEthNum + " LAN leash lost";
+ std::string strAssert = newLanConnected ? "de-asserted" : "asserted";
+ std::string strMsg = strEthNum + " is " +
+ (newLanConnected ? "connected" : "disconnected");
+ std::string strMsgId = "OpenBMC.0.1.PhysicalSecurity";
+ sd_journal_send("MESSAGE=%s", strMsg.c_str(), "PRIORITY=%i", LOG_INFO,
+ "REDFISH_MESSAGE_ID=%s", strMsgId.c_str(),
+ "REDFISH_MESSAGE_ARGS=%s,%s", strEvent.c_str(),
+ strAssert.c_str(), NULL);
+ lanStatusMap[ethNum] = newLanConnected;
+ if (debugLanLeash)
+ {
+ std::cout << "log redfish event: " << strMsg << "\n";
+ }
+ }
+}
+
+static void
+ monitorLanStatusChange(std::shared_ptr<sdbusplus::asio::connection> conn)
+{
+ std::vector<fs::path> files;
+ if (!findFiles(fs::path("/sys/class/net/"), R"(eth\d+/ifindex)", files))
+ {
+ std::cerr << "No eth in system\n";
+ return;
+ }
+
+ // iterate through all found eth files, and save ifindex
+ for (auto& fileName : files)
+ {
+ if (debugLanLeash)
+ {
+ std::cout << "Reading " << fileName << "\n";
+ }
+ std::ifstream sysFile(fileName);
+ if (!sysFile.good())
+ {
+ std::cerr << "Failure reading " << fileName << "\n";
+ continue;
+ }
+ std::string line;
+ getline(sysFile, line);
+ const uint8_t ifindex = std::stoi(line);
+ // pathSuffix is ASCII of ifindex
+ const std::string& pathSuffix = std::to_string(ifindex + 30);
+
+ // extract ethNum
+ const std::string& fileStr = fileName.string();
+ const int pos = fileStr.find("eth");
+ const std::string& ethNumStr = fileStr.substr(pos + 3);
+ int ethNum = 0;
+ try
+ {
+ ethNum = std::stoul(ethNumStr);
+ }
+ catch (const std::invalid_argument& err)
+ {
+ std::cerr << "invalid ethNum string: " << ethNumStr << "\n";
+ continue;
+ }
+
+ // save pathSuffix
+ pathSuffixMap[pathSuffix] = ethNum;
+ if (debugLanLeash)
+ {
+ std::cout << "ethNum = " << std::to_string(ethNum)
+ << ", ifindex = " << line
+ << ", pathSuffix = " << pathSuffix << "\n";
+ }
+
+ // init lan connected status
+ conn->async_method_call(
+ [ethNum](boost::system::error_code ec,
+ const std::variant<std::string>& property) {
+ if (ec)
+ {
+ return;
+ }
+ const std::string* pState = std::get_if<std::string>(&property);
+ if (pState == nullptr)
+ {
+ std::cerr << "Unable to read lan status value\n";
+ return;
+ }
+ bool isLanConnected =
+ (*pState == "routable" || *pState == "carrier" ||
+ *pState == "degraded");
+ if (debugLanLeash)
+ {
+ std::cout << "ethNum = " << std::to_string(ethNum)
+ << ", init LAN status = "
+ << (isLanConnected ? "true" : "false") << "\n";
+ }
+ lanStatusMap[ethNum] = isLanConnected;
+ },
+ "org.freedesktop.network1",
+ "/org/freedesktop/network1/link/_" + pathSuffix,
+ "org.freedesktop.DBus.Properties", "Get",
+ "org.freedesktop.network1.Link", "OperationalState");
+ }
+
+ // add match to monitor lan status change
+ static sdbusplus::bus::match::match match(
+ static_cast<sdbusplus::bus::bus&>(*conn),
+ "type='signal', member='PropertiesChanged',"
+ "arg0namespace='org.freedesktop.network1.Link'",
+ [](sdbusplus::message::message& msg) { processLanStatusChange(msg); });
+}
+
int main()
{
int busId = -1, slaveAddr = -1, gpioIndex = -1;
@@ -225,6 +402,8 @@
std::string(inventoryPath) + "',arg0namespace='" + sensorType + "'",
eventHandler);
+ monitorLanStatusChange(systemBus);
+
io.run();
return 0;