Modify Get Lan Configuration IP Address Source to use correct DBus DHCPEnabled type

The Get/Set Lan Configuration "IP Address Source" subcommand got
broken by phosphor-dbus-interfaces commit 12162be

12162be changed the DBus DHCPEnabled type from boolean to enum
type. The Get LAN Configuration IP address Source IPMI command did not
get changed to an enum type prior to 12162be being merged. This commit
retroactively updates the boolean type to enum type.

Tested:

ipmitool raw 0xc 2 3 4 0 0  # returns correct state
ipmitool raw 0xc 1 3 4 1    # changes DCHP to Static
ipmitool raw 0xc 1 3 4 2    # returns Static to DHCP

Assigned a static address via Redfish and tested using:
ipmitool raw 0xc 2 3 4 0 0  # returns correct state

Returned the NIC to use DHCP via Redfish and tested using:
ipmitool raw 0xc 2 3 4 0 0  # returns correct state

Change-Id: Ia66f7fcf3d5ad0a383b06658b18e8ce2b282e052
Signed-off-by: Johnathan Mantey <johnathanx.mantey@intel.com>
diff --git a/transporthandler.cpp b/transporthandler.cpp
index 6e11535..e48137f 100644
--- a/transporthandler.cpp
+++ b/transporthandler.cpp
@@ -31,6 +31,7 @@
 #include <utility>
 #include <vector>
 #include <xyz/openbmc_project/Common/error.hpp>
+#include <xyz/openbmc_project/Network/EthernetInterface/server.hpp>
 #include <xyz/openbmc_project/Network/IP/server.hpp>
 #include <xyz/openbmc_project/Network/Neighbor/server.hpp>
 
@@ -40,6 +41,7 @@
 using phosphor::logging::level;
 using phosphor::logging::log;
 using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
+using sdbusplus::xyz::openbmc_project::Network::server::EthernetInterface;
 using sdbusplus::xyz::openbmc_project::Network::server::IP;
 using sdbusplus::xyz::openbmc_project::Network::server::Neighbor;
 
@@ -458,25 +460,120 @@
  *
  *  @param[in] bus    - The bus object used for lookups
  *  @param[in] params - The parameters for the channel
- *  @return True if DHCP is enabled, false otherwise
+ *  @return DHCPConf enumeration
  */
-bool getDHCPProperty(sdbusplus::bus::bus& bus, const ChannelParams& params)
+EthernetInterface::DHCPConf getDHCPProperty(sdbusplus::bus::bus& bus,
+                                            const ChannelParams& params)
 {
-    return std::get<bool>(getDbusProperty(
+    std::string dhcpstr = std::get<std::string>(getDbusProperty(
         bus, params.service, params.logicalPath, INTF_ETHERNET, "DHCPEnabled"));
+    return EthernetInterface::convertDHCPConfFromString(dhcpstr);
 }
 
-/** @brief Sets the system value for DHCP on the given interface
+/** @brief Sets the DHCP v4 state on the given interface
  *
- *  @param[in] bus    - The bus object used for lookups
- *  @param[in] params - The parameters for the channel
- *  @param[in] on     - Whether or not to enable DHCP
+ *  @param[in] bus           - The bus object used for lookups
+ *  @param[in] params        - The parameters for the channel
+ *  @param[in] requestedDhcp - DHCP state to assign
+ *                             (EthernetInterface::DHCPConf::none,
+ *                              EthernetInterface::DHCPConf::v4,
+ *                              EthernetInterface::DHCPConf::v6,
+ *                              EthernetInterface::DHCPConf::both)
  */
-void setDHCPProperty(sdbusplus::bus::bus& bus, const ChannelParams& params,
-                     bool on)
+void setDHCPv4Property(sdbusplus::bus::bus& bus, const ChannelParams& params,
+                       const EthernetInterface::DHCPConf requestedDhcp)
 {
+    EthernetInterface::DHCPConf currentDhcp = getDHCPProperty(bus, params);
+    EthernetInterface::DHCPConf nextDhcp = EthernetInterface::DHCPConf::none;
+
+    if ((currentDhcp == EthernetInterface::DHCPConf::v6) &&
+        (requestedDhcp == EthernetInterface::DHCPConf::v4))
+    {
+        nextDhcp = EthernetInterface::DHCPConf::both;
+    }
+    else if ((currentDhcp == EthernetInterface::DHCPConf::none) &&
+             (requestedDhcp == EthernetInterface::DHCPConf::v4))
+
+    {
+        nextDhcp = requestedDhcp;
+    }
+    else if (requestedDhcp == EthernetInterface::DHCPConf::none)
+    {
+        if (currentDhcp == EthernetInterface::DHCPConf::both)
+        {
+            nextDhcp = EthernetInterface::DHCPConf::v6;
+        }
+        else if (currentDhcp == EthernetInterface::DHCPConf::v4)
+        {
+            nextDhcp = EthernetInterface::DHCPConf::none;
+        }
+    }
+    else
+    {
+        nextDhcp = currentDhcp;
+    }
+    std::string newDhcp =
+        sdbusplus::xyz::openbmc_project::Network::server::convertForMessage(
+            nextDhcp);
     setDbusProperty(bus, params.service, params.logicalPath, INTF_ETHERNET,
-                    "DHCPEnabled", on);
+                    "DHCPEnabled", newDhcp);
+}
+
+/** @brief Sets the DHCP v6 state on the given interface
+ *
+ *  @param[in] bus           - The bus object used for lookups
+ *  @param[in] params        - The parameters for the channel
+ *  @param[in] requestedDhcp - DHCP state to assign (none, v6, both)
+ *  @param[in] defaultMode   - True: Use algorithmic assignment
+ *                             False: requestedDhcp assigned unconditionally
+ */
+void setDHCPv6Property(sdbusplus::bus::bus& bus, const ChannelParams& params,
+                       const EthernetInterface::DHCPConf requestedDhcp,
+                       const bool defaultMode = true)
+{
+    EthernetInterface::DHCPConf currentDhcp = getDHCPProperty(bus, params);
+    EthernetInterface::DHCPConf nextDhcp = EthernetInterface::DHCPConf::none;
+
+    if (defaultMode)
+    {
+        if ((currentDhcp == EthernetInterface::DHCPConf::v4) &&
+            (requestedDhcp == EthernetInterface::DHCPConf::v6))
+        {
+            nextDhcp = EthernetInterface::DHCPConf::both;
+        }
+        else if ((currentDhcp == EthernetInterface::DHCPConf::none) &&
+                 (requestedDhcp == EthernetInterface::DHCPConf::v6))
+
+        {
+            nextDhcp = requestedDhcp;
+        }
+        else if (requestedDhcp == EthernetInterface::DHCPConf::none)
+        {
+            if (currentDhcp == EthernetInterface::DHCPConf::both)
+            {
+                nextDhcp = EthernetInterface::DHCPConf::v4;
+            }
+            else if (currentDhcp == EthernetInterface::DHCPConf::v6)
+            {
+                nextDhcp = EthernetInterface::DHCPConf::none;
+            }
+        }
+        else
+        {
+            nextDhcp = currentDhcp;
+        }
+    }
+    else
+    {
+        // allow the v6 call to set any value
+        nextDhcp = requestedDhcp;
+    }
+
+    std::string newDhcp =
+        sdbusplus::xyz::openbmc_project::Network::server::convertForMessage(
+            nextDhcp);
+    setDbusProperty(bus, params.service, params.logicalPath, INTF_ETHERNET,
+                    "DHCPEnabled", newDhcp);
 }
 
 /** @brief Converts a human readable MAC string into MAC bytes
@@ -1117,7 +1214,7 @@
     }
 
     // Clear out any settings on the lower physical interface
-    setDHCPProperty(bus, params, false);
+    setDHCPv6Property(bus, params, EthernetInterface::DHCPConf::none, false);
 }
 
 /** @brief Creates a new VLAN on the specified interface
@@ -1170,7 +1267,7 @@
         }
         ifaddrs6.push_back(std::move(*ifaddr6));
     }
-    auto dhcp = getDHCPProperty(bus, params);
+    EthernetInterface::DHCPConf dhcp = getDHCPProperty(bus, params);
     ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
     auto neighbor4 = findGatewayNeighbor<AF_INET>(bus, params, neighbors);
     auto neighbor6 = findGatewayNeighbor<AF_INET6>(bus, params, neighbors);
@@ -1179,7 +1276,7 @@
     createVLAN(bus, params, vlan);
 
     // Re-establish the saved settings
-    setDHCPProperty(bus, params, dhcp);
+    setDHCPv6Property(bus, params, dhcp, false);
     if (ifaddr4)
     {
         createIfAddr<AF_INET>(bus, params, ifaddr4->address, ifaddr4->prefix);
@@ -1407,7 +1504,10 @@
         }
         case LanParam::IP:
         {
-            if (channelCall<getDHCPProperty>(channel))
+            EthernetInterface::DHCPConf dhcp =
+                channelCall<getDHCPProperty>(channel);
+            if ((dhcp == EthernetInterface::DHCPConf::v4) ||
+                (dhcp == EthernetInterface::DHCPConf::both))
             {
                 return responseCommandNotAvailable();
             }
@@ -1437,13 +1537,19 @@
             {
                 case IPSrc::DHCP:
                 {
-                    channelCall<setDHCPProperty>(channel, true);
+                    // The IPSrc IPMI command is only for IPv4
+                    // management. Modifying IPv6 state is done using
+                    // a completely different Set LAN Configuration
+                    // subcommand.
+                    channelCall<setDHCPv4Property>(
+                        channel, EthernetInterface::DHCPConf::v4);
                     return responseSuccess();
                 }
                 case IPSrc::Unspecified:
                 case IPSrc::Static:
                 {
-                    channelCall<setDHCPProperty>(channel, false);
+                    channelCall<setDHCPv4Property>(
+                        channel, EthernetInterface::DHCPConf::none);
                     return responseSuccess();
                 }
                 case IPSrc::BIOS:
@@ -1473,7 +1579,10 @@
         }
         case LanParam::SubnetMask:
         {
-            if (channelCall<getDHCPProperty>(channel))
+            EthernetInterface::DHCPConf dhcp =
+                channelCall<getDHCPProperty>(channel);
+            if ((dhcp == EthernetInterface::DHCPConf::v4) ||
+                (dhcp == EthernetInterface::DHCPConf::both))
             {
                 return responseCommandNotAvailable();
             }
@@ -1490,7 +1599,10 @@
         }
         case LanParam::Gateway1:
         {
-            if (channelCall<getDHCPProperty>(channel))
+            EthernetInterface::DHCPConf dhcp =
+                channelCall<getDHCPProperty>(channel);
+            if ((dhcp == EthernetInterface::DHCPConf::v4) ||
+                (dhcp == EthernetInterface::DHCPConf::both))
             {
                 return responseCommandNotAvailable();
             }
@@ -1619,7 +1731,10 @@
                 return responseReqDataLenInvalid();
             }
             std::bitset<8> expected;
-            if (channelCall<getDHCPProperty>(channel))
+            EthernetInterface::DHCPConf dhcp =
+                channelCall<getDHCPProperty>(channel);
+            if ((dhcp == EthernetInterface::DHCPConf::both) |
+                (dhcp == EthernetInterface::DHCPConf::v6))
             {
                 expected[IPv6RouterControlFlag::Dynamic] = 1;
             }
@@ -1800,7 +1915,10 @@
         case LanParam::IPSrc:
         {
             auto src = IPSrc::Static;
-            if (channelCall<getDHCPProperty>(channel))
+            EthernetInterface::DHCPConf dhcp =
+                channelCall<getDHCPProperty>(channel);
+            if ((dhcp == EthernetInterface::DHCPConf::v4) ||
+                (dhcp == EthernetInterface::DHCPConf::both))
             {
                 src = IPSrc::DHCP;
             }
@@ -1931,7 +2049,10 @@
         case LanParam::IPv6RouterControl:
         {
             std::bitset<8> control;
-            if (channelCall<getDHCPProperty>(channel))
+            EthernetInterface::DHCPConf dhcp =
+                channelCall<getDHCPProperty>(channel);
+            if ((dhcp == EthernetInterface::DHCPConf::both) ||
+                (dhcp == EthernetInterface::DHCPConf::v6))
             {
                 control[IPv6RouterControlFlag::Dynamic] = 1;
             }
@@ -1945,7 +2066,10 @@
         case LanParam::IPv6StaticRouter1IP:
         {
             in6_addr gateway{};
-            if (!channelCall<getDHCPProperty>(channel))
+            EthernetInterface::DHCPConf dhcp =
+                channelCall<getDHCPProperty>(channel);
+            if ((dhcp == EthernetInterface::DHCPConf::v4) ||
+                (dhcp == EthernetInterface::DHCPConf::none))
             {
                 gateway =
                     channelCall<getGatewayProperty<AF_INET6>>(channel).value_or(