Move LAN handling commands to the new xyz interfaces

Change-Id: I4631c79c171883e5f0d531cfb5957a09496e4b3a
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
diff --git a/apphandler.cpp b/apphandler.cpp
index 6759462..7b30edd 100644
--- a/apphandler.cpp
+++ b/apphandler.cpp
@@ -1,6 +1,9 @@
 #include "apphandler.h"
 #include "host-ipmid/ipmid-api.h"
 #include "ipmid.hpp"
+#include "types.hpp"
+#include "utils.hpp"
+
 #include <stdio.h>
 #include <string.h>
 #include <stdint.h>
@@ -8,7 +11,12 @@
 #include <mapper.h>
 #include <array>
 #include <arpa/inet.h>
-#include "transporthandler.h"
+#include "transporthandler.hpp"
+
+#include <phosphor-logging/log.hpp>
+#include <phosphor-logging/elog-errors.hpp>
+#include "xyz/openbmc_project/Common/error.hpp"
+
 
 extern sd_bus *bus;
 
@@ -16,8 +24,13 @@
 constexpr auto app_ifc = "org.openbmc.NetworkManager";
 constexpr auto app_nwinterface = "eth0";
 
+constexpr auto ipv4Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
+
 void register_netfn_app_functions() __attribute__((constructor));
 
+using namespace phosphor::logging;
+using namespace sdbusplus::xyz::openbmc_project::Common::Error;
+
 // Offset in get device id command.
 typedef struct
 {
@@ -508,114 +521,146 @@
     return rc;
 }
 
-extern struct channel_config_t channel_config;
+extern struct ChannelConfig_t channelConfig;
 
-ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
-                             ipmi_request_t request, ipmi_response_t response,
-                             ipmi_data_len_t data_len, ipmi_context_t context)
+ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn,
+                                   ipmi_cmd_t cmd,
+                                   ipmi_request_t request,
+                                   ipmi_response_t response,
+                                   ipmi_data_len_t data_len,
+                                   ipmi_context_t context)
 {
     ipmi_ret_t rc = IPMI_CC_OK;
 
-    sd_bus *bus = ipmid_get_sd_bus_connection();
-    sd_bus_message *reply = nullptr;
-    sd_bus_error error = SD_BUS_ERROR_NULL;
-    int r = 0;
-    char *app = nullptr;
-    int family = 0;
-    unsigned char prefixlen = 0;
-    char* ipaddr = nullptr;
-    uint32_t mask = 0xFFFFFFFF;
-    char* gateway = nullptr;
-    char tmp_netmask[INET_ADDRSTRLEN];
+    std::string ipaddress;
+    std::string gateway;
+    uint8_t prefix {};
 
     // Todo: parse the request data if needed.
 
     // Using Set Channel cmd to apply changes of Set Lan Cmd.
+    try
+    {
 
-    r = mapper_get_service(bus, app_obj, &app);
-    if (r < 0) {
-        fprintf(stderr, "Failed to get %s bus name: %s\n",
-                app_obj, strerror(-r));
-        rc = IPMI_CC_UNSPECIFIED_ERROR;
-        goto finish;
+        sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
+
+        log<level::INFO>("Network data from Cache",
+                         entry("PREFIX=%s", channelConfig.netmask.c_str()),
+                         entry("ADDRESS=%s", channelConfig.ipaddr.c_str()),
+                         entry("GATEWAY=%s", channelConfig.gateway.c_str()));
+
+        auto systemObject = ipmi::getDbusObject(bus,
+                                 ipmi::network::SYSTEMCONFIG_INTERFACE,
+                                 ipmi::network::ROOT);
+
+        // TODO Currently IPMI supports single interface,need to handle
+        // Multiple interface through
+        // https://github.com/openbmc/openbmc/issues/2138
+
+        auto networkInterfaceObject = ipmi::getDbusObject(
+                    bus,
+                    ipmi::network::ETHERNET_INTERFACE,
+                    ipmi::network::ROOT,
+                    ipmi::network::INTERFACE);
+
+
+
+        // check wthether user has given all the data
+        if (!channelConfig.ipaddr.empty() &&
+            !channelConfig.netmask.empty() &&
+            !channelConfig.gateway.empty())
+        {
+            //convert mask into prefix
+            ipaddress = channelConfig.ipaddr;
+            prefix = ipmi::network::toPrefix(AF_INET, channelConfig.netmask);
+            gateway = channelConfig.gateway;
+        }
+        else
+        {
+            // gets the network data from the system as user has
+            // not given all the data then use the data fetched from the
+            // system but it is implementation dependent,IPMI spec doesn't
+            // force it.
+
+            // if system is not having any ip object don't throw error,
+            try
+            {
+
+                auto ipObjectInfo = ipmi::getDbusObject(bus,
+                        ipmi::network::IP_INTERFACE,
+                        ipmi::network::ROOT,
+                        ipmi::network::IP_TYPE);
+
+                auto properties = ipmi::getAllDbusProperties(bus,
+                        ipObjectInfo.second,
+                        ipObjectInfo.first,
+                        ipmi::network::IP_INTERFACE);
+
+                ipaddress = channelConfig.ipaddr.empty() ?
+                    std::move(properties["Address"].get<std::string>()) :
+                    channelConfig.ipaddr;
+
+                prefix = channelConfig.netmask.empty() ?
+                    properties["PrefixLength"].get<uint8_t>() :
+                    ipmi::network::toPrefix(AF_INET,
+                                            channelConfig.netmask);
+
+            }
+            catch (InternalFailure& e)
+            {
+                log<level::INFO>("Failed to get IP object which matches",
+                        entry("INTERFACE=%s", ipmi::network::IP_INTERFACE),
+                        entry("MATCH=%s", ipmi::network::IP_TYPE));
+            }
+
+            auto systemProperties = ipmi::getAllDbusProperties(
+                    bus,
+                    systemObject.second,
+                    systemObject.first,
+                    ipmi::network::SYSTEMCONFIG_INTERFACE);
+
+            gateway = channelConfig.gateway.empty() ?
+                std::move(systemProperties["DefaultGateway"].get<std::string>()) :
+                channelConfig.gateway;
+
+        }
+
+        // Currently network manager doesn't support purging of all the
+        // ip addresses from the parent interface,
+        // TODO once the support is there, will make the change here.
+        // https://github.com/openbmc/openbmc/issues/2141.
+
+        // TODO Currently IPMI supports single interface,need to handle
+        // Multiple interface through
+        // https://github.com/openbmc/openbmc/issues/2138
+
+        //delete all the ipv4  addresses
+
+        ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT,
+                                   ipmi::network::IP_INTERFACE,
+                                   ipmi::network::IP_TYPE);
+
+        ipmi::network::createIP(bus, networkInterfaceObject.second,
+                                networkInterfaceObject.first,
+                                ipv4Protocol, ipaddress, prefix);
+
+        ipmi::setDbusProperty(bus, systemObject.second, systemObject.first,
+                              ipmi::network::SYSTEMCONFIG_INTERFACE,
+                              "DefaultGateway", gateway);
+
     }
+    catch (InternalFailure& e)
+    {
+        log<level::ERR>("Failed to set network data",
+                        entry("PREFIX=%d", prefix),
+                        entry("ADDRESS=%s", ipaddress),
+                        entry("GATEWAY=%s", gateway));
 
-    r = sd_bus_call_method(bus, app, app_obj, app_ifc, "GetAddress4", &error,
-                            &reply, "s", app_nwinterface);
-    if (r < 0) {
-        fprintf(stderr, "Failed to call Get Method: %s\n", strerror(-r));
-        rc = IPMI_CC_UNSPECIFIED_ERROR;
-        goto finish;
-    }
-
-    r = sd_bus_message_read(reply, "iyss",
-                            &family, &prefixlen, &ipaddr, &gateway);
-    if (r < 0) {
-        fprintf(stderr, "Failed to get a response: %s\n", strerror(-r));
-        rc = IPMI_CC_RESPONSE_ERROR;
-        goto finish;
-    }
-
-    printf("N/W data from Cache: %s:%s:%s\n",
-            channel_config.new_ipaddr.c_str(),
-            channel_config.new_netmask.c_str(),
-            channel_config.new_gateway.c_str());
-
-    if(channel_config.new_ipaddr.empty()) {
-        channel_config.new_ipaddr.assign(ipaddr);
-    }
-
-    if(channel_config.new_netmask.empty()) {
-        mask = htonl(mask<<(32-prefixlen));
-        uint8_t* p = (uint8_t*)&mask;
-
-        snprintf(tmp_netmask, INET_ADDRSTRLEN, "%d.%d.%d.%d",
-            *p, *(p+1), *(p+2), *(p+3));
-        channel_config.new_netmask.assign(tmp_netmask);
-    }
-
-    if(channel_config.new_gateway.empty()) {
-        channel_config.new_gateway.assign(gateway);
-    }
-
-    printf("N/W data from HW %s:%d:%s:%s\n",
-            family==AF_INET?"IPv4":"IPv6", prefixlen, ipaddr,gateway);
-    printf("N/W data from Cache: %s:%s:%s\n",
-            channel_config.new_ipaddr.c_str(),
-            channel_config.new_netmask.c_str(),
-            channel_config.new_gateway.c_str());
-
-    r = sd_bus_call_method(bus,            // On the System Bus
-                            app,            // Service to contact
-                            app_obj,            // Object path
-                            app_ifc,            // Interface name
-                            "SetAddress4",  // Method to be called
-                            &error,         // object to return error
-                            &reply,         // Response message on success
-                            "ssss",         // input message (Interface,
-                                            // IP Address, Netmask, Gateway)
-                            app_nwinterface,    // eth0
-                            channel_config.new_ipaddr.c_str(),
-                            channel_config.new_netmask.c_str(),
-                            channel_config.new_gateway.c_str());
-    if(r < 0) {
-        fprintf(stderr, "Failed to set network data %s:%s:%s %s\n",
-                channel_config.new_ipaddr.c_str(),
-                channel_config.new_netmask.c_str(),
-                channel_config.new_gateway.c_str(),
-                error.message);
+        commit<InternalFailure>();
         rc = IPMI_CC_UNSPECIFIED_ERROR;
     }
 
-    channel_config.new_ipaddr.clear();
-    channel_config.new_netmask.clear();
-    channel_config.new_gateway.clear();
-
-finish:
-    sd_bus_error_free(&error);
-    reply = sd_bus_message_unref(reply);
-    free(app);
-
+    channelConfig.clear();
     return rc;
 }