Implement network factory reset in network_manager

This commit implements a factory reset interface for the BMC
network. This factory reset is accomplished by removing any
/etc/systemd/network/*.network files, then writing new ones
configured for DHCP for each known interface.

Resolves openbmc/openbmc#1575

Change-Id: Ic006cd43fb336029479cffa783b56ab91e0339bd
Signed-off-by: Michael Tritz <mtritz@us.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index 75c49e6..29517f9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -12,6 +12,7 @@
 
 noinst_HEADERS = \
 		ethernet_interface.hpp \
+		network_config.hpp \
 		network_manager.hpp \
 		ipaddress.hpp \
 		types.hpp
@@ -19,6 +20,7 @@
 phosphor_network_manager_SOURCES = \
 		ethernet_interface.cpp \
 		ipaddress.cpp \
+		network_config.cpp \
 		network_manager.cpp \
 		network_manager_main.cpp \
 		xyz/openbmc_project/Network/VLAN/Create/server.cpp \
@@ -65,4 +67,3 @@
 	@mkdir -p `dirname $@`
 	$(SDBUSPLUSPLUS) -r $(srcdir) interface server-header xyz.openbmc_project.Network.IP.Create > $@
 	sed -i '5i #include \"xyz\/openbmc_project\/Network\/IP\/server.hpp\"' $@
-
diff --git a/network_config.cpp b/network_config.cpp
new file mode 100644
index 0000000..4540ad8
--- /dev/null
+++ b/network_config.cpp
@@ -0,0 +1,25 @@
+#include "network_config.hpp"
+#include <fstream>
+#include <string>
+
+namespace phosphor
+{
+namespace network
+{
+
+namespace bmc
+{
+    void writeDHCPDefault(const std::string& filename,
+            const std::string& interface)
+    {
+        std::ofstream filestream;
+
+        filestream.open(filename);
+        filestream << "[Match]\nName=" << interface <<
+                "\n[Network]\nDHCP=true\n[DHCP]\nClientIdentifier=mac\n";
+        filestream.close();
+    }
+}
+
+}//namespace network
+}//namespace phosphor
diff --git a/network_config.hpp b/network_config.hpp
new file mode 100644
index 0000000..0868820
--- /dev/null
+++ b/network_config.hpp
@@ -0,0 +1,15 @@
+#include <string>
+
+namespace phosphor
+{
+namespace network
+{
+
+namespace bmc
+{
+    void writeDHCPDefault(const std::string& filename,
+            const std::string& interface);
+}
+
+}//namespace network
+}//namespace phosphor
diff --git a/network_manager.cpp b/network_manager.cpp
index e0ebdfc..95e1476 100644
--- a/network_manager.cpp
+++ b/network_manager.cpp
@@ -1,5 +1,6 @@
 #include "config.h"
 #include "network_manager.hpp"
+#include "network_config.hpp"
 
 #include <phosphor-logging/log.hpp>
 
@@ -12,6 +13,7 @@
 #include <dirent.h>
 #include <net/if.h>
 
+#include <string>
 
 namespace phosphor
 {
@@ -48,6 +50,57 @@
 {
 }
 
+void Manager::reset()
+{
+    const std::string networkConfig = "/etc/systemd/network/";
+    bool filesExist, interfacesMapped = false;
+
+    if(fs::is_directory(networkConfig))
+    {
+        for(auto& file : fs::directory_iterator(networkConfig))
+        {
+            std::string filename = file.path().filename().c_str();
+
+            if(filename.substr(filename.find_last_of(".") + 1) == "network")
+            {
+                fs::remove(file.path());
+                filesExist = true;
+            }
+        }
+
+        if(!filesExist)
+        {
+            log<level::INFO>("No existing network configuration was found.");
+        }
+
+        for (auto& intf : interfaces)
+        {
+            std::string filename = networkConfig + "00-bmc-" + intf.first +
+                    ".network";
+
+            bmc::writeDHCPDefault(filename, intf.first);
+            interfacesMapped = true;
+        }
+
+        if(interfacesMapped)
+        {
+            log<level::INFO>("Network configuration reset to DHCP.");
+        }
+        else
+        {
+            log<level::ERR>("No network interfaces are mapped.");
+            // TODO: openbmc/openbmc#1721 - Log ResetFailed error here.
+        }
+    }
+    else
+    {
+        log<level::ERR>("Network configuration directory not found!");
+        // TODO: openbmc/openbmc#1721 - Log ResetFailed error here.
+    }
+
+    return;
+}
+
 IntfAddrMap Manager::getInterfaceAddrs() const
 {
     IntfAddrMap intfMap;
diff --git a/network_manager.hpp b/network_manager.hpp
index f37544c..0bd082b 100644
--- a/network_manager.hpp
+++ b/network_manager.hpp
@@ -3,6 +3,7 @@
 #include "ethernet_interface.hpp"
 #include "types.hpp"
 #include "xyz/openbmc_project/Network/VLAN/Create/server.hpp"
+#include <xyz/openbmc_project/Common/FactoryReset/server.hpp>
 
 #include <sdbusplus/bus.hpp>
 #include <ifaddrs.h>
@@ -20,12 +21,12 @@
 namespace details
 {
 
-template <typename T>
-using ServerObject = typename sdbusplus::server::object::object<T>;
+template <typename T, typename U>
+using ServerObject = typename sdbusplus::server::object::object<T, U>;
 
-using VLANCreateIface =
-    details::ServerObject<sdbusplus::xyz::openbmc_project::
-    Network::VLAN::server::Create>;
+using VLANCreateIface = details::ServerObject<
+    sdbusplus::xyz::openbmc_project::Network::VLAN::server::Create,
+    sdbusplus::xyz::openbmc_project::Common::server::FactoryReset>;
 
 using IntfName = std::string;
 
@@ -85,6 +86,9 @@
         /** @brief Persistent map of EthernetInterface dbus objects and their names */
         std::map<IntfName, std::unique_ptr<EthernetInterface>> interfaces;
 
+        /** @brief BMC network reset - resets network configuration for BMC. */
+        void reset() override;
+
 };
 
 } // namespace network