Implement network monitor

This commit listens for the ipaddress add event
and prints the message once it gets the NEWADDR
signal.

Change-Id: I5cdebc023dc8848fc736eca8d785c33387d401df
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
diff --git a/rtnetlink_server.cpp b/rtnetlink_server.cpp
new file mode 100644
index 0000000..d3cac19
--- /dev/null
+++ b/rtnetlink_server.cpp
@@ -0,0 +1,144 @@
+#include "xyz/openbmc_project/Common/error.hpp"
+#include "rtnetlink_server.hpp"
+#include "types.hpp"
+#include "util.hpp"
+
+
+#include <netinet/in.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <net/if.h>
+#include <sys/types.h>
+#include <systemd/sd-daemon.h>
+#include <unistd.h>
+
+#include <phosphor-logging/log.hpp>
+#include <phosphor-logging/elog-errors.hpp>
+
+#include <memory>
+#include <iostream>
+
+namespace phosphor
+{
+namespace network
+{
+namespace rtnetlink
+{
+
+/* Call Back for the sd event loop */
+static int eventHandler(sd_event_source* es, int fd, uint32_t revents,
+                        void* userdata)
+{
+    char buffer[phosphor::network::rtnetlink::BUFSIZE] {};
+    int len {};
+
+    auto netLinkHeader = reinterpret_cast<struct nlmsghdr*>(buffer);
+    while ((len = recv(fd, netLinkHeader,
+                        phosphor::network::rtnetlink::BUFSIZE, 0)) > 0)
+    {
+        for (; (NLMSG_OK(netLinkHeader, len)) &&
+               (netLinkHeader->nlmsg_type != NLMSG_DONE);
+                    netLinkHeader = NLMSG_NEXT(netLinkHeader, len))
+        {
+            if (netLinkHeader->nlmsg_type == RTM_NEWADDR ||
+                netLinkHeader->nlmsg_type == RTM_DELADDR)
+            {
+                // TODO delete the below trace in later commit.
+                std::cout << "Address Changed\n";
+
+            } // end if
+
+        } // end for
+
+    } // end while
+
+    return 0;
+}
+
+
+int Server::run()
+{
+    using namespace phosphor::logging;
+
+    struct sockaddr_nl addr {};
+
+    int fd = -1;
+    phosphor::Descriptor smartSock(fd);
+
+    int r {};
+
+    sigset_t ss {};
+
+
+    if (sigemptyset(&ss) < 0 || sigaddset(&ss, SIGTERM) < 0 ||
+        sigaddset(&ss, SIGINT) < 0)
+    {
+        r = -errno;
+        goto finish;
+    }
+    /* Block SIGTERM first, so that the event loop can handle it */
+    if (sigprocmask(SIG_BLOCK, &ss, NULL) < 0)
+    {
+        r = -errno;
+        goto finish;
+    }
+
+    /* Let's make use of the default handler and "floating"
+       reference features of sd_event_add_signal() */
+
+    r = sd_event_add_signal(eventPtr.get(), NULL, SIGTERM, NULL, NULL);
+    if (r < 0)
+    {
+        goto finish;
+    }
+
+    r = sd_event_add_signal(eventPtr.get(), NULL, SIGINT, NULL, NULL);
+    if (r < 0)
+    {
+        goto finish;
+    }
+
+    fd = socket(PF_NETLINK, SOCK_RAW | SOCK_NONBLOCK, NETLINK_ROUTE);
+    if (fd < 0)
+    {
+        r = -errno;
+        goto finish;
+    }
+
+    smartSock.set(fd);
+    fd = -1;
+
+    memset(&addr, 0, sizeof(addr));
+    addr.nl_family = AF_NETLINK;
+    addr.nl_groups = RTMGRP_IPV4_IFADDR;
+
+    if (bind(smartSock(), (struct sockaddr*)&addr, sizeof(addr)) < 0)
+    {
+        r = -errno;
+        goto finish;
+    }
+
+    r = sd_event_add_io(eventPtr.get(), nullptr,
+                        smartSock(), EPOLLIN, eventHandler, nullptr);
+    if (r < 0)
+    {
+        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));
+    }
+
+    return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+
+} //rtnetlink
+} //network
+} //phosphor