transporthandler: Fix path check

Right now, paths for channel names can sometimes conflict if we have
an interface whose name is a subset of another interface. This makes the
match much more explicit. It also happens to remove the string search
completely.

Change-Id: Ia3a91e4a04a28d0b76eade2c5e716017c5431e71
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/transporthandler.cpp b/transporthandler.cpp
index dc602af..a9bc7c8 100644
--- a/transporthandler.cpp
+++ b/transporthandler.cpp
@@ -64,6 +64,16 @@
 static constexpr uint8_t oemCmdStart = 192;
 static constexpr uint8_t oemCmdEnd = 255;
 
+// Checks if the ifname is part of the networkd path
+// This assumes the path came from the network subtree PATH_ROOT
+bool ifnameInPath(std::string_view ifname, std::string_view path)
+{
+    constexpr auto rs = PATH_ROOT.size() + 1; // ROOT + separator
+    const auto is = rs + ifname.size();       // ROOT + sep + ifname
+    return path.size() > rs && path.substr(rs).starts_with(ifname) &&
+           (path.size() == is || path[is] == '/');
+}
+
 std::optional<ChannelParams> maybeGetChannelParams(sdbusplus::bus_t& bus,
                                                    uint8_t channel)
 {
@@ -76,7 +86,7 @@
     // Enumerate all VLAN + ETHERNET interfaces
     auto req = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
                                    "GetSubTree");
-    req.append(PATH_ROOT, 0,
+    req.append(std::string_view(PATH_ROOT), 0,
                std::vector<std::string>{INTF_VLAN, INTF_ETHERNET});
     auto reply = bus.call(req);
     ObjectTree objs;
@@ -85,7 +95,7 @@
     ChannelParams params;
     for (const auto& [path, impls] : objs)
     {
-        if (path.find(ifname) == path.npos)
+        if (!ifnameInPath(ifname, path))
         {
             continue;
         }
@@ -474,13 +484,14 @@
     // Delete all objects associated with the interface
     auto objreq = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
                                       "GetSubTree");
-    objreq.append(PATH_ROOT, 0, std::vector<std::string>{DELETE_INTERFACE});
+    objreq.append(std::string_view(PATH_ROOT), 0,
+                  std::vector<std::string>{DELETE_INTERFACE});
     auto objreply = bus.call(objreq);
     ObjectTree objs;
     objreply.read(objs);
     for (const auto& [path, impls] : objs)
     {
-        if (path.find(params.ifname) == path.npos)
+        if (!ifnameInPath(params.ifname, path))
         {
             continue;
         }
@@ -514,7 +525,7 @@
         return;
     }
 
-    auto req = bus.new_method_call(params.service.c_str(), PATH_ROOT,
+    auto req = bus.new_method_call(params.service.c_str(), PATH_ROOT.c_str(),
                                    INTF_VLAN_CREATE, "VLAN");
     req.append(params.ifname, static_cast<uint32_t>(vlan));
     auto reply = bus.call(req);
diff --git a/transporthandler.hpp b/transporthandler.hpp
index 019311b..f4a7585 100644
--- a/transporthandler.hpp
+++ b/transporthandler.hpp
@@ -17,6 +17,7 @@
 #include <stdplus/net/addr/ether.hpp>
 #include <stdplus/net/addr/ip.hpp>
 #include <stdplus/str/conv.hpp>
+#include <stdplus/zstring_view.hpp>
 #include <user_channel/channel_layer.hpp>
 #include <xyz/openbmc_project/Common/error.hpp>
 #include <xyz/openbmc_project/Network/EthernetInterface/server.hpp>
@@ -37,8 +38,10 @@
 namespace transport
 {
 
+using stdplus::operator""_zsv;
+
 // D-Bus Network Daemon definitions
-constexpr auto PATH_ROOT = "/xyz/openbmc_project/network";
+constexpr auto PATH_ROOT = "/xyz/openbmc_project/network"_zsv;
 constexpr auto INTF_ETHERNET = "xyz.openbmc_project.Network.EthernetInterface";
 constexpr auto INTF_IP = "xyz.openbmc_project.Network.IP";
 constexpr auto INTF_IP_CREATE = "xyz.openbmc_project.Network.IP.Create";