Add service and interface whitelist/blacklists

This allows service whitelists and blacklists, and
interface whitelists to be passed into the application.

The whitelists can be prefixes, like xyz.openbmc_project.
The blacklist is the full service name.

A future commit can add support for interface blacklists.

Change-Id: I91f6ef2f7be63e4d13ac03d570bba18ef8277fae
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/src/main.cpp b/src/main.cpp
index e00e920..c291250 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,3 +1,5 @@
+#include "src/argument.hpp"
+
 #include <tinyxml2.h>
 
 #include <atomic>
@@ -29,6 +31,10 @@
                            std::shared_ptr<sdbusplus::asio::dbus_interface>>
     associationInterfaces;
 
+static boost::container::flat_set<std::string> service_whitelist;
+static boost::container::flat_set<std::string> service_blacklist;
+static boost::container::flat_set<std::string> iface_whitelist;
+
 /** Exception thrown when a path is not found in the object list. */
 struct NotFoundException final : public sdbusplus::exception_t
 {
@@ -302,8 +308,16 @@
                     continue;
                 }
 
-                if (ignored_interfaces.find(std::string(iface_name)) ==
-                    ignored_interfaces.end())
+                std::string iface{iface_name};
+
+                if (((ignored_interfaces.find(iface) ==
+                      ignored_interfaces.end()) &&
+                     (std::find_if(iface_whitelist.begin(),
+                                   iface_whitelist.end(),
+                                   [iface](const auto& prefix) {
+                                       return boost::starts_with(iface, prefix);
+                                   }) != iface_whitelist.end())) ||
+                    (iface == "org.freedesktop.DBus.ObjectManager"))
                 {
                     thisPathMap[transaction->process_name].emplace(iface_name);
                 }
@@ -357,9 +371,17 @@
 
 bool need_to_introspect(const std::string& process_name)
 {
-    return boost::starts_with(process_name, "xyz.openbmc_project.") ||
-           boost::starts_with(process_name, "org.openbmc.") ||
-           boost::starts_with(process_name, "com.intel.");
+    auto inWhitelist =
+        std::find_if(service_whitelist.begin(), service_whitelist.end(),
+                     [&process_name](const auto& prefix) {
+                         return boost::starts_with(process_name, prefix);
+                     }) != service_whitelist.end();
+
+    // This holds full service names, not prefixes
+    auto inBlacklist =
+        service_blacklist.find(process_name) != service_blacklist.end();
+
+    return inWhitelist && !inBlacklist;
 }
 
 void start_new_introspect(
@@ -442,13 +464,36 @@
         "ListNames");
 }
 
+void splitArgs(const std::string& stringArgs,
+               boost::container::flat_set<std::string>& listArgs)
+{
+    std::istringstream args;
+    std::string arg;
+
+    args.str(stringArgs);
+
+    while (!args.eof())
+    {
+        args >> arg;
+        if (!arg.empty())
+        {
+            listArgs.insert(arg);
+        }
+    }
+}
+
 int main(int argc, char** argv)
 {
     std::cerr << "started\n";
+    auto options = ArgumentParser(argc, argv);
     boost::asio::io_service io;
     std::shared_ptr<sdbusplus::asio::connection> system_bus =
         std::make_shared<sdbusplus::asio::connection>(io);
 
+    splitArgs(options["service-namespaces"], service_whitelist);
+    splitArgs(options["interface-namespaces"], iface_whitelist);
+    splitArgs(options["service-blacklists"], service_blacklist);
+
     system_bus->request_name(OBJECT_MAPPER_DBUS_NAME);
     sdbusplus::asio::object_server server(system_bus);