1 #include "processing.hpp" 2 3 #include <iostream> 4 #include <string> 5 6 bool getWellKnown( 7 const boost::container::flat_map<std::string, std::string>& owners, 8 const std::string& request, std::string& wellKnown) 9 { 10 // If it's already a well known name, just return 11 if (!request.starts_with(":")) 12 { 13 wellKnown = request; 14 return true; 15 } 16 17 auto it = owners.find(request); 18 if (it == owners.end()) 19 { 20 return false; 21 } 22 wellKnown = it->second; 23 return true; 24 } 25 26 bool needToIntrospect(const std::string& processName, 27 const AllowDenyList& allowList) 28 { 29 auto inAllowList = std::find_if(allowList.begin(), allowList.end(), 30 [&processName](const auto& prefix) { 31 return processName.starts_with(prefix); 32 }) != allowList.end(); 33 34 return inAllowList; 35 } 36 37 void processNameChangeDelete( 38 boost::container::flat_map<std::string, std::string>& nameOwners, 39 const std::string& wellKnown, const std::string& oldOwner, 40 InterfaceMapType& interfaceMap, AssociationMaps& assocMaps, 41 sdbusplus::asio::object_server& server) 42 { 43 if (oldOwner.starts_with(":")) 44 { 45 auto it = nameOwners.find(oldOwner); 46 if (it != nameOwners.end()) 47 { 48 nameOwners.erase(it); 49 } 50 } 51 // Connection removed 52 InterfaceMapType::iterator pathIt = interfaceMap.begin(); 53 while (pathIt != interfaceMap.end()) 54 { 55 // If an associations interface is being removed, 56 // also need to remove the corresponding associations 57 // objects and properties. 58 auto ifaces = pathIt->second.find(wellKnown); 59 if (ifaces != pathIt->second.end()) 60 { 61 auto assoc = std::find(ifaces->second.begin(), ifaces->second.end(), 62 assocDefsInterface); 63 if (assoc != ifaces->second.end()) 64 { 65 removeAssociation(pathIt->first, wellKnown, server, assocMaps); 66 } 67 68 // Instead of checking if every single path is the endpoint of an 69 // association that needs to be moved to pending, only check when 70 // we own this path as well, which would be because of an 71 // association. 72 if ((pathIt->second.size() == 2) && 73 (pathIt->second.find("xyz.openbmc_project.ObjectMapper") != 74 pathIt->second.end())) 75 { 76 // Remove the 2 association D-Bus paths and move the 77 // association to pending. 78 moveAssociationToPending(pathIt->first, assocMaps, server); 79 } 80 } 81 pathIt->second.erase(wellKnown); 82 if (pathIt->second.empty()) 83 { 84 // If the last connection to the object is gone, 85 // delete the top level object 86 pathIt = interfaceMap.erase(pathIt); 87 continue; 88 } 89 pathIt++; 90 } 91 } 92 93 void processInterfaceAdded(InterfaceMapType& interfaceMap, 94 const sdbusplus::message::object_path& objPath, 95 const InterfacesAdded& intfAdded, 96 const std::string& wellKnown, 97 AssociationMaps& assocMaps, 98 sdbusplus::asio::object_server& server) 99 { 100 auto& ifaceList = interfaceMap[objPath.str]; 101 102 for (const auto& interfacePair : intfAdded) 103 { 104 ifaceList[wellKnown].emplace(interfacePair.first); 105 106 if (interfacePair.first == assocDefsInterface) 107 { 108 const std::variant<std::vector<Association>>* variantAssociations = 109 nullptr; 110 for (const auto& interface : interfacePair.second) 111 { 112 if (interface.first == assocDefsProperty) 113 { 114 variantAssociations = &(interface.second); 115 } 116 } 117 if (variantAssociations == nullptr) 118 { 119 std::cerr << "Illegal association found on " << wellKnown 120 << "\n"; 121 continue; 122 } 123 std::vector<Association> associations = 124 std::get<std::vector<Association>>(*variantAssociations); 125 associationChanged(server, associations, objPath.str, wellKnown, 126 interfaceMap, assocMaps); 127 } 128 } 129 130 // To handle the case where an object path is being created 131 // with 2 or more new path segments, check if the parent paths 132 // of this path are already in the interface map, and add them 133 // if they aren't with just the default freedesktop interfaces. 134 // This would be done via introspection if they would have 135 // already existed at startup. While we could also introspect 136 // them now to do the work, we know there aren't any other 137 // interfaces or we would have gotten signals for them as well, 138 // so take a shortcut to speed things up. 139 // 140 // This is all needed so that mapper operations can be done 141 // on the new parent paths. 142 using iface_map_iterator = InterfaceMapType::iterator; 143 using name_map_iterator = InterfaceMapType::mapped_type::iterator; 144 145 static const InterfaceNames defaultIfaces{ 146 "org.freedesktop.DBus.Introspectable", "org.freedesktop.DBus.Peer", 147 "org.freedesktop.DBus.Properties"}; 148 149 std::string parent = objPath.str; 150 auto pos = parent.find_last_of('/'); 151 152 while (pos != std::string::npos) 153 { 154 parent = parent.substr(0, pos); 155 156 std::pair<iface_map_iterator, bool> parentEntry = 157 interfaceMap.try_emplace(parent); 158 159 std::pair<name_map_iterator, bool> ifaceEntry = 160 parentEntry.first->second.try_emplace(wellKnown, defaultIfaces); 161 162 if (!ifaceEntry.second) 163 { 164 // Entry was already there for this name so done. 165 break; 166 } 167 168 pos = parent.find_last_of('/'); 169 } 170 171 // The new interface might have an association pending 172 checkIfPendingAssociation(objPath.str, interfaceMap, assocMaps, server); 173 } 174