Integrate inotify watcher into network daemon

This commit integrates watching for DNS entries and updating
/etc/resolv.conf functionality into network manager daemon
as opposed to having another daemon doing just that.

Change-Id: Id858815675ed4a23ee8c6a31ba3ae6e5ee0054fd
Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
diff --git a/configure.ac b/configure.ac
index bbf5c4f..e195d91 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,6 +69,10 @@
     AC_SUBST([OESDK_TESTCASE_FLAGS], [$testcase_flags])
 )
 
+AC_ARG_VAR(DNS_ENTRY_FILE, [File having DNS entries supplied by DHCP])
+AS_IF([test "x$DNS_ENTRY_FILE" == "x"], [DNS_ENTRY_FILE="/run/systemd/netif/state"])
+AC_DEFINE_UNQUOTED([DNS_ENTRY_FILE], ["$DNS_ENTRY_FILE"], [File having DNS entries supplied by DHCP])
+
 AC_ARG_VAR(BUSNAME_NETWORK, [The Dbus busname to own])
 AS_IF([test "x$BUSNAME_NETWORK" == "x"], [BUSNAME_NETWORK="xyz.openbmc_project.Network"])
 AC_DEFINE_UNQUOTED([BUSNAME_NETWORK], ["$BUSNAME_NETWORK"], [The DBus busname to own])
diff --git a/dns_updater.cpp b/dns_updater.cpp
index 5c4d058..1b3b8ea 100644
--- a/dns_updater.cpp
+++ b/dns_updater.cpp
@@ -17,8 +17,8 @@
 namespace updater
 {
 
-void processDNSEntries(const fs::path& inFile,
-                       const fs::path& outFile)
+void updateDNSEntries(const fs::path& inFile,
+                      const fs::path& outFile)
 {
     using namespace phosphor::logging;
     using namespace sdbusplus::xyz::openbmc_project::Common::Error;
diff --git a/dns_updater.hpp b/dns_updater.hpp
index 44c0e32..84646c6 100644
--- a/dns_updater.hpp
+++ b/dns_updater.hpp
@@ -20,8 +20,8 @@
  *  @param[in] inFile  - File having DNS entries supplied by DHCP
  *  @param[in] outFile - File to write the nameserver entries to
  */
-void processDNSEntries(const fs::path& inFile,
-                       const fs::path& outFile);
+void updateDNSEntries(const fs::path& inFile,
+                      const fs::path& outFile);
 
 /** @brief User callback handler invoked by inotify watcher
  *
@@ -32,7 +32,7 @@
  */
 inline void processDNSEntries(const fs::path& inFile)
 {
-    return processDNSEntries(inFile, RESOLV_CONF);
+    return updateDNSEntries(inFile, RESOLV_CONF);
 }
 
 } // namepsace updater
diff --git a/netman_watch_dns.c b/netman_watch_dns.c
index 33e6f14..b60b699 100644
--- a/netman_watch_dns.c
+++ b/netman_watch_dns.c
@@ -380,12 +380,20 @@
 
     printf("Watching for changes in DNS settings..\n");
 
-    /* Now that we have checked it once. rest is all notification bases. */
+     /* Commenting since this functionality has been built into network
+      * manager and this file will be deleted in the very next commit
+      */
+    /*
     rc = watch_for_dns_change(netif_dir, state_file);
     if(rc < 0)
     {
         fprintf(stderr,"Error watching for DNS changes\n");
     }
+    */
 
-    return 0;
+    // Returning will result in app getting launched again per Restart
+    // policy in service file
+    pause();
+
+    return rc;
 }
diff --git a/network_manager_main.cpp b/network_manager_main.cpp
index 0c95c8d..b08d5ac 100644
--- a/network_manager_main.cpp
+++ b/network_manager_main.cpp
@@ -2,6 +2,8 @@
 #include "network_manager.hpp"
 #include "rtnetlink_server.hpp"
 #include "timer.hpp"
+#include "watch.hpp"
+#include "dns_updater.hpp"
 
 #include <memory>
 
@@ -83,8 +85,6 @@
                                                          OBJ_NETWORK,
                                                          NETWORK_CONF_DIR);
 
-    phosphor::network::rtnetlink::Server svr(eventPtr);
-
     // create the network interface dbus objects and system config
     phosphor::network::manager->createChildObjects();
 
@@ -99,6 +99,22 @@
         // will create it.
         phosphor::network::restartNetwork();
     }
-    return svr.run();
+
+    // RTNETLINK event handler
+    phosphor::network::rtnetlink::Server svr(eventPtr);
+
+    // DNS entry handler
+    phosphor::network::inotify::Watch watch(eventPtr, DNS_ENTRY_FILE,
+            std::bind(&phosphor::network::dns::updater::processDNSEntries,
+                std::placeholders::_1));
+
+    // At this point, we have registered for the notifications for future
+    // events. However, if the file is already populated before this, then
+    // they won't ever get notified and thus we need to read once before
+    // waiting on change events
+    phosphor::network::dns::updater::processDNSEntries(DNS_ENTRY_FILE);
+
+    // Run the server
+    sd_event_loop(eventPtr.get());
 }
 
diff --git a/rtnetlink_server.cpp b/rtnetlink_server.cpp
index 31dbfd1..c0e5ad5 100644
--- a/rtnetlink_server.cpp
+++ b/rtnetlink_server.cpp
@@ -13,6 +13,8 @@
 #include <unistd.h>
 
 #include <phosphor-logging/log.hpp>
+#include <phosphor-logging/elog-errors.hpp>
+#include <xyz/openbmc_project/Common/error.hpp>
 
 #include <memory>
 
@@ -63,10 +65,11 @@
     return 0;
 }
 
-int Server::run()
+Server::Server(EventPtr& eventPtr)
 {
     using namespace phosphor::logging;
-
+    using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
+                                    Error::InternalFailure;
     struct sockaddr_nl addr {};
 
     int fd = -1;
@@ -132,17 +135,14 @@
         goto finish;
     }
 
-    r = sd_event_loop(eventPtr.get());
-
 finish:
 
     if (r < 0)
     {
         log<level::ERR>("Failure Occured in starting of server:",
                         entry("errno = %d", errno));
+        elog<InternalFailure>();
     }
-
-    return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 }
 
 
diff --git a/rtnetlink_server.hpp b/rtnetlink_server.hpp
index 51cf7bb..a00e6b7 100644
--- a/rtnetlink_server.hpp
+++ b/rtnetlink_server.hpp
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "types.hpp"
+#include "util.hpp"
 
 #include <systemd/sd-event.h>
 
@@ -26,28 +27,18 @@
 
         /** @brief Constructor
          *
-         *  @param[in] event - Unique ptr reference to sd_event.
+         *  @details Sets up the server to handle incoming RTNETLINK events
+         *
+         *  @param[in] eventPtr - Unique ptr reference to sd_event.
          */
+        Server(EventPtr& eventPtr);
 
-        Server(EventPtr& event):
-            eventPtr(event) {};
-
+        Server() = delete;
+        ~Server() = default;
         Server(const Server&) = delete;
         Server& operator=(const Server&) = delete;
         Server(Server&&) = default;
         Server& operator=(Server &&) = default;
-
-        /** @brief Initialise the event loop and add the handler for incoming
-         *         RTNETLINK events.
-         *
-         *  @return EXIT_SUCCESS on success and EXIT_FAILURE on failure.
-         */
-        int run();
-
-    private:
-        /** @brief reference to sd_event wrapped in unique_ptr */
-        EventPtr& eventPtr;
-
 };
 
 } //namespace rtnetlink
diff --git a/test/test_dns_updater.cpp b/test/test_dns_updater.cpp
index 8fb4bcb..5d92cd3 100644
--- a/test/test_dns_updater.cpp
+++ b/test/test_dns_updater.cpp
@@ -53,7 +53,7 @@
  */
 TEST_F(DnsUpdateTest, validateOutFile)
 {
-    phosphor::network::dns::updater::processDNSEntries(IN_FILE, OUT_FILE);
+    phosphor::network::dns::updater::updateDNSEntries(IN_FILE, OUT_FILE);
 
     // Read files and compare
     std::ifstream resolv(OUT_FILE);