rsyslog-conf: add validation and error handling

Validate server IP address. Handle exceptions.

Change-Id: I6da9949dbf90dd12853afca8050b68b3aaad144e
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
diff --git a/phosphor-rsyslog-config/Makefile.am b/phosphor-rsyslog-config/Makefile.am
index f695946..d1c5425 100644
--- a/phosphor-rsyslog-config/Makefile.am
+++ b/phosphor-rsyslog-config/Makefile.am
@@ -1,3 +1,5 @@
+AM_CPPFLAGS = -I$(top_srcdir)
+
 noinst_HEADERS = \
 	utils.hpp \
 	server-conf.hpp
diff --git a/phosphor-rsyslog-config/server-conf.cpp b/phosphor-rsyslog-config/server-conf.cpp
index 1372e85..1b46965 100644
--- a/phosphor-rsyslog-config/server-conf.cpp
+++ b/phosphor-rsyslog-config/server-conf.cpp
@@ -1,6 +1,16 @@
 #include "server-conf.hpp"
 #include "utils.hpp"
+#include "xyz/openbmc_project/Common/error.hpp"
 #include <fstream>
+#include <phosphor-logging/log.hpp>
+#include <phosphor-logging/elog.hpp>
+#if __has_include("../../usr/include/phosphor-logging/elog-errors.hpp")
+#include "../../usr/include/phosphor-logging/elog-errors.hpp"
+#else
+#include <phosphor-logging/elog-errors.hpp>
+#endif
+#include <netdb.h>
+#include <arpa/inet.h>
 
 namespace phosphor
 {
@@ -8,30 +18,73 @@
 {
 
 namespace utils = phosphor::rsyslog_utils;
+using namespace phosphor::logging;
+using namespace sdbusplus::xyz::openbmc_project::Common::Error;
 
 std::string Server::address(std::string value)
 {
-    auto serverAddress = address();
-    if (serverAddress == value)
+    using Argument = xyz::openbmc_project::Common::InvalidArgument;
+    std::string result {};
+
+    try
     {
-        return serverAddress;
+        auto serverAddress = address();
+        if (serverAddress == value)
+        {
+            return serverAddress;
+        }
+
+        if (!value.empty() && !addressValid(value))
+        {
+            elog<InvalidArgument>(Argument::ARGUMENT_NAME("Address"),
+                                  Argument::ARGUMENT_VALUE(value.c_str()));
+        }
+
+        writeConfig(value, port(), configFilePath.c_str());
+        result = std::move(NetworkClient::address(value));
+    }
+    catch (const InvalidArgument& e)
+    {
+        throw;
+    }
+    catch (const InternalFailure& e)
+    {
+        throw;
+    }
+    catch (const std::exception& e)
+    {
+        log<level::ERR>(e.what());
+        elog<InternalFailure>();
     }
 
-    writeConfig(value, port(), configFilePath.c_str());
-    auto result = NetworkClient::address(value);
     return result;
 }
 
 uint16_t Server::port(uint16_t value)
 {
-    auto serverPort = port();
-    if (serverPort == value)
+    uint16_t result {};
+
+    try
     {
-        return serverPort;
+        auto serverPort = port();
+        if (serverPort == value)
+        {
+            return serverPort;
+        }
+
+        writeConfig(address(), value, configFilePath.c_str());
+        result = NetworkClient::port(value);
+    }
+    catch (const InternalFailure& e)
+    {
+        throw;
+    }
+    catch (const std::exception& e)
+    {
+        log<level::ERR>(e.what());
+        elog<InternalFailure>();
     }
 
-    writeConfig(address(), value, configFilePath.c_str());
-    auto result = NetworkClient::port(value);
     return result;
 }
 
@@ -56,5 +109,24 @@
     utils::restart();
 }
 
+bool Server::addressValid(const std::string& address)
+{
+    addrinfo hints{};
+    addrinfo* res = nullptr;
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_flags |= AI_CANONNAME;
+
+    auto result = getaddrinfo(address.c_str(), nullptr, &hints, &res);
+    if (result)
+    {
+        log<level::ERR>("bad address",
+                        entry("ADDRESS=%s", address.c_str()),
+                        entry("ERRNO=%d", result));
+        return false;
+    }
+    return true;
+}
+
 } // namespace rsyslog_config
 } // namespace phosphor
diff --git a/phosphor-rsyslog-config/server-conf.hpp b/phosphor-rsyslog-config/server-conf.hpp
index cb8882b..795cfb6 100644
--- a/phosphor-rsyslog-config/server-conf.hpp
+++ b/phosphor-rsyslog-config/server-conf.hpp
@@ -69,6 +69,12 @@
                  uint16_t serverPort,
                  const char* filePath);
 
+        /** @brief Checks if input IP address is valid (uses getaddrinfo)
+         *  @param[in] address - server address
+         *  @returns true if valid, false otherwise
+         */
+        bool addressValid(const std::string& address);
+
         std::string configFilePath{};
 };