Add the network utility file

Moving utility functions from network manager to
util.cpp.

Added few more utility functions.

Change-Id: I2e73c873e9a3bea543d6979463b2181e8374e12e
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index 6c5aec9..f2a9174 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,7 +15,8 @@
 		network_config.hpp \
 		network_manager.hpp \
 		ipaddress.hpp \
-		types.hpp
+		types.hpp \
+		util.hpp
 
 phosphor_network_manager_SOURCES = \
 		ethernet_interface.cpp \
@@ -24,7 +25,8 @@
 		network_manager.cpp \
 		network_manager_main.cpp \
 		xyz/openbmc_project/Network/VLAN/Create/server.cpp \
-		xyz/openbmc_project/Network/IP/Create/server.cpp
+		xyz/openbmc_project/Network/IP/Create/server.cpp \
+		util.cpp
 
 CLEANFILES = \
 		xyz/openbmc_project/Network/VLAN/Create/server.cpp \
diff --git a/ethernet_interface.hpp b/ethernet_interface.hpp
index f9bd895..6ef1ec9 100644
--- a/ethernet_interface.hpp
+++ b/ethernet_interface.hpp
@@ -2,6 +2,7 @@
 
 #include "ipaddress.hpp"
 #include "types.hpp"
+#include "util.hpp"
 
 #include "xyz/openbmc_project/Network/EthernetInterface/server.hpp"
 #include "xyz/openbmc_project/Network/IP/Create/server.hpp"
diff --git a/network_manager.cpp b/network_manager.cpp
index 8ea82d5..a4a9b54 100644
--- a/network_manager.cpp
+++ b/network_manager.cpp
@@ -105,9 +105,9 @@
 
 IntfAddrMap Manager::getInterfaceAddrs() const
 {
-    IntfAddrMap intfMap;
-    AddrList addrList;
-    struct ifaddrs* ifaddr;
+    IntfAddrMap intfMap{};
+    AddrList addrList{};
+    struct ifaddrs* ifaddr = nullptr;
 
     using namespace sdbusplus::xyz::openbmc_project::Common::Error;
     // attempt to fill struct with ifaddrs
@@ -122,7 +122,7 @@
     details::AddrPtr ifaddrPtr(ifaddr);
     ifaddr = nullptr;
 
-    std::string intfName;
+    std::string intfName{};
 
     for (ifaddrs* ifa = ifaddrPtr.get(); ifa != nullptr; ifa = ifa->ifa_next)
     {
@@ -151,7 +151,7 @@
                 addrList.clear();
             }
             intfName = ifa->ifa_name;
-            AddrInfo info;
+            AddrInfo info{};
             char ip[INET6_ADDRSTRLEN] = { 0 };
             char subnetMask[INET6_ADDRSTRLEN] = { 0 };
 
@@ -185,9 +185,7 @@
 
             info.addrType = ifa->ifa_addr->sa_family;
             info.ipaddress = ip;
-
-            info.prefix = toCidr(info.addrType, subnetMask);
-
+            info.prefix = toCidr(info.addrType, std::string(subnetMask));
             addrList.emplace_back(info);
         }
     }
@@ -195,96 +193,5 @@
     return intfMap;
 }
 
-uint8_t Manager::toCidr(int addressFamily, const std::string& subnetMask) const
-{
-    uint32_t buff = 0;
-
-    if (addressFamily == AF_INET6)
-    {
-        return toV6Cidr(std::string(subnetMask));
-    }
-
-    auto rc = inet_pton(addressFamily, subnetMask.c_str(), &buff);
-    if (rc <= 0)
-    {
-        log<level::ERR>("inet_pton failed:",
-                         entry("SUBNETMASK=%s", subnetMask.c_str()));
-    }
-
-    buff = be32toh(buff);
-    // total no of bits - total no of leading zero == total no of ones
-    if (((sizeof(buff) * 8) - (__builtin_ctz(buff))) == __builtin_popcount(buff))
-    {
-        return __builtin_popcount(buff);
-    }
-    else
-    {
-        log<level::ERR>("Invalid Mask",
-                         entry("SUBNETMASK=%s", subnetMask.c_str()));
-        return 0;
-    }
-}
-
-uint8_t Manager::toV6Cidr(const std::string& subnetMask) const
-{
-    uint8_t pos {};
-    uint8_t prevPos {};
-    uint8_t cidr {};
-    uint16_t buff {};
-
-    log<level::INFO>("toV6Cidr called with",
-                     entry("SUBNETMASK=%s", subnetMask));
-    do
-    {
-        //subnet mask look like ffff:ffff::
-        // or ffff:c000::
-        pos =  subnetMask.find(":", prevPos);
-        if (pos == std::string::npos)
-        {
-            return cidr;
-        }
-
-        auto str = subnetMask.substr(prevPos, (pos - prevPos));
-        prevPos = pos + 1;
-
-        // String length is 0
-        if (!str.length())
-        {
-            return cidr;
-        }
-        //converts it into number.
-        if (sscanf(str.c_str(), "%hx", &buff) <= 0)
-        {
-            log<level::ERR>("Invalid SubnetMask",
-                             entry("SUBNETMASK=%s", subnetMask));
-
-            return 0;
-        }
-
-        // convert the number into bitset
-        // and check for how many ones are there.
-        // if we don't have all the ones then make
-        // sure that all the ones should be left justify.
-
-        if (__builtin_popcount(buff) != 16)
-        {
-            if (((sizeof(buff) * 8) - (__builtin_ctz(buff))) != __builtin_popcount(buff))
-            {
-                log<level::ERR>("Invalid SubnetMask",
-                                 entry("SUBNETMASK=%s", subnetMask));
-
-                return 0;
-            }
-            cidr += __builtin_popcount(buff);
-            return cidr;
-        }
-        cidr += 16;
-
-    }
-    while (1);
-
-    return cidr;
-}
-
 }//namespace network
 }//namespace phosphor
diff --git a/network_manager.hpp b/network_manager.hpp
index d0cb779..553951c 100644
--- a/network_manager.hpp
+++ b/network_manager.hpp
@@ -80,19 +80,6 @@
          */
         IntfAddrMap getInterfaceAddrs() const;
 
-        /** @brief converts the given subnet into prefix notation
-         *  @param[in] addressFamily - IP address family(AF_INET/AF_INET6)
-         *  @param[in] subnetMask - SubnetMask which needs to be converted.
-         *  @returns prefix.
-         */
-        uint8_t toCidr(int addressFamily, const std::string& subnetMask) const;
-
-        /** @brief converts the given V6 subnet into prefix notation
-         *  @param[in] subnetMask - SubnetMask which needs to be converted.
-         *  @returns prefix.
-         */
-        uint8_t toV6Cidr(const std::string& subnetMask) const;
-
         /** @brief Persistent map of EthernetInterface dbus objects and their names */
         std::map<IntfName, std::unique_ptr<EthernetInterface>> interfaces;
 
diff --git a/util.cpp b/util.cpp
new file mode 100644
index 0000000..740d4a7
--- /dev/null
+++ b/util.cpp
@@ -0,0 +1,144 @@
+#include <arpa/inet.h>
+#include <dirent.h>
+#include <net/if.h>
+
+#include <iostream>
+#include <list>
+#include <string>
+#include <algorithm>
+#include <phosphor-logging/log.hpp>
+
+namespace phosphor
+{
+namespace network
+{
+namespace
+{
+
+using namespace phosphor::logging;
+
+uint8_t toV6Cidr(const std::string& subnetMask)
+{
+    uint8_t pos = 0;
+    uint8_t prevPos = 0;
+    uint8_t cidr = 0;
+    uint16_t buff {};
+    do
+    {
+        //subnet mask look like ffff:ffff::
+        // or ffff:c000::
+        pos =  subnetMask.find(":", prevPos);
+        if (pos == std::string::npos)
+        {
+            break;
+        }
+
+        auto str = subnetMask.substr(prevPos, (pos - prevPos));
+        prevPos = pos + 1;
+
+        // String length is 0
+        if (!str.length())
+        {
+            return cidr;
+        }
+        //converts it into number.
+        if (sscanf(str.c_str(), "%hx", &buff) <= 0)
+        {
+            log<level::ERR>("Invalid Mask",
+                             entry("SUBNETMASK=%s", subnetMask));
+
+            return 0;
+        }
+
+        // convert the number into bitset
+        // and check for how many ones are there.
+        // if we don't have all the ones then make
+        // sure that all the ones should be left justify.
+
+        if (__builtin_popcount(buff) != 16)
+        {
+            if (((sizeof(buff) * 8) - (__builtin_ctz(buff))) != __builtin_popcount(buff))
+            {
+                log<level::ERR>("Invalid Mask",
+                                entry("SUBNETMASK=%s", subnetMask));
+
+                return 0;
+            }
+            cidr += __builtin_popcount(buff);
+            return cidr;
+        }
+
+        cidr += 16;
+    }
+    while (1);
+
+    return cidr;
+}
+}// anonymous namespace
+
+uint8_t toCidr(int addressFamily, const std::string& subnetMask)
+{
+    if (addressFamily == AF_INET6)
+    {
+        return toV6Cidr(subnetMask);
+    }
+
+    uint32_t buff;
+
+    auto rc = inet_pton(addressFamily, subnetMask.c_str(), &buff);
+    if (rc <= 0)
+    {
+        log<level::ERR>("inet_pton failed:",
+                         entry("SUBNETMASK=%s", subnetMask));
+        return 0;
+    }
+
+    buff = be32toh(buff);
+    // total no of bits - total no of leading zero == total no of ones
+    if (((sizeof(buff) * 8) - (__builtin_ctz(buff))) == __builtin_popcount(buff))
+    {
+        return __builtin_popcount(buff);
+    }
+    else
+    {
+        log<level::ERR>("Invalid Mask",
+                         entry("SUBNETMASK=%s", subnetMask));
+        return 0;
+    }
+}
+
+std::string toMask(int addressFamily, uint8_t prefix)
+{
+    if (addressFamily == AF_INET6)
+    {
+        //TODO:- conversion for v6
+        return "";
+    }
+
+    if (prefix < 1 || prefix > 30)
+    {
+        log<level::ERR>("Invalid Prefix",
+                        entry("PREFIX=%d", prefix));
+        return "";
+    }
+    /* Create the netmask from the number of bits */
+    unsigned long mask = 0;
+    for (auto i = 0 ; i < prefix ; i++)
+    {
+        mask |= 1 << (31 - i);
+    }
+    struct in_addr netmask;
+    netmask.s_addr = htonl(mask);
+    return inet_ntoa(netmask);
+}
+
+bool isLinkLocal(const std::string& address)
+{
+    std::string linklocal = "fe80";
+    return std::mismatch(linklocal.begin(), linklocal.end(),
+                         address.begin()).first == linklocal.end() ?
+                            true : false;
+}
+
+}//namespace network
+}//namespace phosphor
diff --git a/util.hpp b/util.hpp
new file mode 100644
index 0000000..c305724
--- /dev/null
+++ b/util.hpp
@@ -0,0 +1,61 @@
+#pragma once
+
+#include <unistd.h>
+
+namespace phosphor
+{
+namespace network
+{
+
+/* @brief converts the given subnet into prefix notation.
+ * @param[in] addressFamily - IP address family(AF_INET/AF_INET6).
+ * @param[in] mask - Subnet Mask.
+ * @returns prefix.
+ */
+uint8_t toCidr(int addressFamily, const std::string& mask);
+
+/* @brief converts the prefix into subnetmask.
+ * @param[in] addressFamily - IP address family(AF_INET/AF_INET6).
+ * @param[in] prefix - prefix length.
+ * @returns subnet mask.
+ */
+std::string toMask(int addressFamily, uint8_t prefix);
+
+/* @brief checks that the given ip address is link local or not.
+ * @param[in] address - IP address.
+ * @returns true if it is linklocal otherwise false.
+ */
+bool isLinkLocal(const std::string& address);
+
+} //namespace network
+
+class Descriptor
+{
+    private:
+        /** default value */
+        int fd = -1;
+
+    public:
+        Descriptor() = delete;
+        Descriptor(const Descriptor&) = delete;
+        Descriptor& operator=(const Descriptor&) = delete;
+        Descriptor(Descriptor&&) = delete;
+        Descriptor& operator=(Descriptor&&) = delete;
+
+        Descriptor(int fd) : fd(fd) {}
+
+        ~Descriptor()
+        {
+            if (fd >= 0)
+            {
+                close(fd);
+            }
+        }
+
+        int operator()() const
+        {
+            return fd;
+        }
+};
+
+} //namespace phosphor