Fetch the network portion of the IP address

eg 192.168.2.24/24 ==> 192.168.2.0

Change-Id: I5e46ce7b371360c90ef74fac175c8379c6f31d4c
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index 003ba37..3ccff0d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -44,11 +44,13 @@
 		$(SYSTEMD_LIBS) \
 		$(SDBUSPLUS_LIBS) \
 		$(PHOSPHOR_DBUS_INTERFACES_LIBS) \
+		$(PHOSPHOR_LOGGING_LIBS) \
 		-lstdc++fs
 
 phosphor_network_manager_CXXFLAGS = \
 		$(SYSTEMD_CFLAGS) \
 		$(SDBUSPLUS_CFLAGS) \
+		$(PHOSPHOR_LOGGING_CFLAGS) \
 		$(PHOSPHOR_DBUS_INTERFACES_CFLAGS)
 
 xyz/openbmc_project/Network/VLAN/Create/server.cpp: xyz/openbmc_project/Network/VLAN/Create.interface.yaml xyz/openbmc_project/Network/VLAN/Create/server.hpp
diff --git a/test/Makefile.am b/test/Makefile.am
index 87d0742..1fd0f33 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -11,12 +11,17 @@
 	test_ethernet_interface.cpp
 
 test_CPPFLAGS = -Igtest $(GTEST_CPPFLAGS) $(AM_CPPFLAGS)
-test_CXXFLAGS = $(PTHREAD_CFLAGS)
+test_CXXFLAGS = $(PTHREAD_CFLAGS) \
+				$(SYSTEMD_CFLAGS) \
+				$(SDBUSPLUS_CFLAGS) \
+				$(PHOSPHOR_LOGGING_CFLAGS) \
+				$(PHOSPHOR_DBUS_INTERFACES_CFLAGS)
 
 test_LDFLAGS =	-lgtest_main -lgtest -lstdc++fs \
 				$(OESDK_TESTCASE_FLAGS) \
 				$(SYSTEMD_LIBS) \
 				$(SDBUSPLUS_LIBS) \
+				$(PHOSPHOR_LOGGING_LIBS) \
 				$(PHOSPHOR_DBUS_INTERFACES_LIBS)
 
 test_LDADD = $(top_builddir)/ethernet_interface.cpp \
diff --git a/test/test_util.cpp b/test/test_util.cpp
index d0888ca..9b1d34a 100644
--- a/test/test_util.cpp
+++ b/test/test_util.cpp
@@ -61,7 +61,7 @@
     EXPECT_EQ(prefix, 0);
 }
 
-TEST_F(TestUtil, isLinLocaladdress)
+TEST_F(TestUtil, isLinkLocaladdress)
 {
     std::string ipaddress = "fe80:fec0::";
     EXPECT_TRUE(isLinkLocal(ipaddress));
@@ -85,5 +85,27 @@
     EXPECT_EQ(mask, "255.255.255.224");
 }
 
+TEST_F(TestUtil, getNetworkAddress)
+{
+    std::string address = getNetworkID(AF_INET,"9.3.23.251",24);
+    EXPECT_EQ("9.3.23.0",address);
+
+    address = getNetworkID(AF_INET,"9.3.23.251",25);
+    EXPECT_EQ("9.3.23.128",address);
+
+    address = getNetworkID(AF_INET6,"2001:db8:abcd:dd12::0",64);
+    EXPECT_EQ("2001:db8:abcd:dd12::",address);
+
+    address = getNetworkID(AF_INET,"a.b.c.d",25);
+    EXPECT_EQ("",address);
+
+    address = getNetworkID(AF_INET6,"2001:db8:gghh:dd12::0",64);
+    EXPECT_EQ("",address);
+
+
+    address = getNetworkID(AF_INET6,"fe80::201:6cff:fe80:228",64);
+    EXPECT_EQ("fe80::",address);
+}
+
 }// namespce network
 }// namespace phosphor
diff --git a/util.cpp b/util.cpp
index 740d4a7..43ebf43 100644
--- a/util.cpp
+++ b/util.cpp
@@ -1,12 +1,15 @@
 #include <arpa/inet.h>
 #include <dirent.h>
 #include <net/if.h>
+#include "xyz/openbmc_project/Common/error.hpp"
+
+#include <phosphor-logging/log.hpp>
+#include <phosphor-logging/elog-errors.hpp>
 
 #include <iostream>
 #include <list>
 #include <string>
 #include <algorithm>
-#include <phosphor-logging/log.hpp>
 
 namespace phosphor
 {
@@ -16,6 +19,7 @@
 {
 
 using namespace phosphor::logging;
+using namespace sdbusplus::xyz::openbmc_project::Common::Error;
 
 uint8_t toV6Cidr(const std::string& subnetMask)
 {
@@ -89,7 +93,7 @@
     if (rc <= 0)
     {
         log<level::ERR>("inet_pton failed:",
-                         entry("SUBNETMASK=%s", subnetMask));
+                        entry("SUBNETMASK=%s", subnetMask));
         return 0;
     }
 
@@ -102,7 +106,7 @@
     else
     {
         log<level::ERR>("Invalid Mask",
-                         entry("SUBNETMASK=%s", subnetMask));
+                        entry("SUBNETMASK=%s", subnetMask));
         return 0;
     }
 }
@@ -132,6 +136,64 @@
     return inet_ntoa(netmask);
 }
 
+std::string getNetworkID(int addressFamily, const std::string& ipaddress,
+                       uint8_t prefix)
+{
+    unsigned char* pntMask = nullptr;
+    unsigned char* pntNetwork = nullptr;
+    int bit {};
+    int offset {};
+    struct in6_addr netmask {};
+    const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
+                              0xf8, 0xfc, 0xfe, 0xff
+                             };
+
+    pntMask = reinterpret_cast<unsigned char*>(&netmask);
+
+    offset = prefix / 8;
+    bit = prefix % 8;
+
+    while (offset--)
+    {
+        *pntMask++ = 0xff;
+    }
+
+    if (bit)
+    {
+        *pntMask = maskbit[bit];
+    }
+
+    // convert ipaddres string into network address
+    struct in6_addr ipaddressNetwork;
+    if (inet_pton(addressFamily, ipaddress.c_str(), &ipaddressNetwork) <= 0)
+    {
+        log<level::ERR>("inet_pton failure",
+            entry("IPADDRESS=%s",ipaddress.c_str()));
+        report<InternalFailure>();
+
+        return "";
+    }
+
+    // Now bit wise and gets you the network address
+    pntMask = reinterpret_cast<unsigned char*>(&netmask);
+    pntNetwork = reinterpret_cast<unsigned char*>(&ipaddressNetwork);
+
+    for (int i = 0; i < 16 ; i++)
+    {
+        pntNetwork[i] = pntNetwork[i] & pntMask[i];
+    }
+
+    //convert the network address into string fomat.
+    char networkString[INET6_ADDRSTRLEN] = { 0 };
+    if (inet_ntop(addressFamily, &ipaddressNetwork, networkString,
+                  INET6_ADDRSTRLEN) == NULL)
+    {
+        log<level::ERR>("inet_ntop failure");
+        report<InternalFailure>();
+    }
+    return networkString;
+}
+
 bool isLinkLocal(const std::string& address)
 {
     std::string linklocal = "fe80";
diff --git a/util.hpp b/util.hpp
index c305724..fb511fe 100644
--- a/util.hpp
+++ b/util.hpp
@@ -27,6 +27,15 @@
  */
 bool isLinkLocal(const std::string& address);
 
+/* @brief gets the network section of the ip adress.
+ * @param[in] addressFamily - IP address family(AF_INET/AF_INET6).
+ * @param[in] ipaddress - IP address.
+ * @param[in] prefix - prefix length.
+ * @returns network section of the ipaddress.
+ */
+std::string getNetworkID(int addressFamily, const std::string& ipaddress,
+                         uint8_t prefix);
+
 } //namespace network
 
 class Descriptor
@@ -40,7 +49,7 @@
         Descriptor(const Descriptor&) = delete;
         Descriptor& operator=(const Descriptor&) = delete;
         Descriptor(Descriptor&&) = delete;
-        Descriptor& operator=(Descriptor&&) = delete;
+        Descriptor& operator=(Descriptor &&) = delete;
 
         Descriptor(int fd) : fd(fd) {}