diff --git a/transporthandler.hpp b/transporthandler.hpp
index c13e05a..a5ec6ea 100644
--- a/transporthandler.hpp
+++ b/transporthandler.hpp
@@ -1,13 +1,64 @@
 #pragma once
 
+#include "app/channel.hpp"
+#include "user_channel/cipher_mgmt.hpp"
+
+#include <arpa/inet.h>
+#include <netinet/ether.h>
+
+#include <array>
+#include <bitset>
+#include <cinttypes>
 #include <cstdint>
+#include <cstring>
+#include <fstream>
+#include <functional>
 #include <ipmid/api-types.hpp>
+#include <ipmid/api.hpp>
+#include <ipmid/message.hpp>
+#include <ipmid/message/types.hpp>
+#include <ipmid/types.hpp>
+#include <ipmid/utils.hpp>
+#include <optional>
+#include <phosphor-logging/elog-errors.hpp>
+#include <phosphor-logging/elog.hpp>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/exception.hpp>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <unordered_map>
+#include <unordered_set>
+#include <user_channel/channel_layer.hpp>
+#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>
 
 namespace ipmi
 {
 namespace transport
 {
 
+// D-Bus Network Daemon definitions
+constexpr auto PATH_ROOT = "/xyz/openbmc_project/network";
+constexpr auto PATH_SYSTEMCONFIG = "/xyz/openbmc_project/network/config";
+
+constexpr auto INTF_SYSTEMCONFIG =
+    "xyz.openbmc_project.Network.SystemConfiguration";
+constexpr auto INTF_ETHERNET = "xyz.openbmc_project.Network.EthernetInterface";
+constexpr auto INTF_IP = "xyz.openbmc_project.Network.IP";
+constexpr auto INTF_IP_CREATE = "xyz.openbmc_project.Network.IP.Create";
+constexpr auto INTF_MAC = "xyz.openbmc_project.Network.MACAddress";
+constexpr auto INTF_NEIGHBOR = "xyz.openbmc_project.Network.Neighbor";
+constexpr auto INTF_NEIGHBOR_CREATE_STATIC =
+    "xyz.openbmc_project.Network.Neighbor.CreateStatic";
+constexpr auto INTF_VLAN = "xyz.openbmc_project.Network.VLAN";
+constexpr auto INTF_VLAN_CREATE = "xyz.openbmc_project.Network.VLAN.Create";
+
 /** @brief IPMI LAN Parameters */
 enum class LanParam : uint8_t
 {
@@ -111,5 +162,523 @@
 constexpr uint8_t MAX_IPV6_STATIC_ADDRESSES = 15;
 constexpr uint8_t MAX_IPV6_DYNAMIC_ADDRESSES = 15;
 
+/** @brief The dbus parameters for the interface corresponding to a channel
+ *         This helps reduce the number of mapper lookups we need for each
+ *         query and simplifies finding the VLAN interface if needed.
+ */
+struct ChannelParams
+{
+    /** @brief The channel ID */
+    int id;
+    /** @brief channel name for the interface */
+    std::string ifname;
+    /** @brief Name of the service on the bus */
+    std::string service;
+    /** @brief Lower level adapter path that is guaranteed to not be a VLAN */
+    std::string ifPath;
+    /** @brief Logical adapter path used for address assignment */
+    std::string logicalPath;
+};
+
+/** @brief A trivial helper used to determine if two PODs are equal
+ *
+ *  @params[in] a - The first object to compare
+ *  @params[in] b - The second object to compare
+ *  @return True if the objects are the same bytewise
+ */
+template <typename T>
+bool equal(const T& a, const T& b)
+{
+    static_assert(std::is_trivially_copyable_v<T>);
+    return std::memcmp(&a, &b, sizeof(T)) == 0;
+}
+
+/** @brief Copies bytes from an array into a trivially copyable container
+ *
+ *  @params[out] t     - The container receiving the data
+ *  @params[in]  bytes - The data to copy
+ */
+template <size_t N, typename T>
+void copyInto(T& t, const std::array<uint8_t, N>& bytes)
+{
+    static_assert(std::is_trivially_copyable_v<T>);
+    static_assert(N == sizeof(T));
+    std::memcpy(&t, bytes.data(), bytes.size());
+}
+
+/** @brief Gets a generic view of the bytes in the input container
+ *
+ *  @params[in] t - The data to reference
+ *  @return A string_view referencing the bytes in the container
+ */
+template <typename T>
+std::string_view dataRef(const T& t)
+{
+    static_assert(std::is_trivially_copyable_v<T>);
+    return {reinterpret_cast<const char*>(&t), sizeof(T)};
+}
+
+/** @brief Determines the ethernet interface name corresponding to a channel
+ *         Tries to map a VLAN object first so that the address information
+ *         is accurate. Otherwise it gets the standard ethernet interface.
+ *
+ *  @param[in] bus     - The bus object used for lookups
+ *  @param[in] channel - The channel id corresponding to an ethernet interface
+ *  @return Ethernet interface service and object path if it exists
+ */
+std::optional<ChannelParams> maybeGetChannelParams(sdbusplus::bus::bus& bus,
+                                                   uint8_t channel);
+
+/** @brief A trivial helper around maybeGetChannelParams() that throws an
+ *         exception when it is unable to acquire parameters for the channel.
+ *
+ *  @param[in] bus     - The bus object used for lookups
+ *  @param[in] channel - The channel id corresponding to an ethernet interface
+ *  @return Ethernet interface service and object path
+ */
+ChannelParams getChannelParams(sdbusplus::bus::bus& bus, uint8_t channel);
+
+/** @brief Trivializes using parameter getter functions by providing a bus
+ *         and channel parameters automatically.
+ *
+ *  @param[in] channel - The channel id corresponding to an ethernet interface
+ *  ...
+ */
+template <auto func, typename... Args>
+auto channelCall(uint8_t channel, Args&&... args)
+{
+    sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
+    auto params = getChannelParams(bus, channel);
+    return std::invoke(func, bus, params, std::forward<Args>(args)...);
+}
+
+/** @brief Generic paramters for different address families */
+template <int family>
+struct AddrFamily
+{
+};
+
+/** @brief Parameter specialization for IPv4 */
+template <>
+struct AddrFamily<AF_INET>
+{
+    using addr = in_addr;
+    static constexpr auto protocol =
+        sdbusplus::xyz::openbmc_project::Network::server::IP::Protocol::IPv4;
+    static constexpr size_t maxStrLen = INET6_ADDRSTRLEN;
+    static constexpr uint8_t defaultPrefix = 32;
+    static constexpr char propertyGateway[] = "DefaultGateway";
+};
+
+/** @brief Parameter specialization for IPv6 */
+template <>
+struct AddrFamily<AF_INET6>
+{
+    using addr = in6_addr;
+    static constexpr auto protocol =
+        sdbusplus::xyz::openbmc_project::Network::server::IP::Protocol::IPv6;
+    static constexpr size_t maxStrLen = INET6_ADDRSTRLEN;
+    static constexpr uint8_t defaultPrefix = 128;
+    static constexpr char propertyGateway[] = "DefaultGateway6";
+};
+
+/** @brief Interface Neighbor configuration parameters */
+template <int family>
+struct IfNeigh
+{
+    std::string path;
+    typename AddrFamily<family>::addr ip;
+    ether_addr mac;
+};
+
+/** @brief Interface IP Address configuration parameters */
+template <int family>
+struct IfAddr
+{
+    std::string path;
+    typename AddrFamily<family>::addr address;
+    sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin origin;
+    uint8_t prefix;
+};
+
+/** @brief Valid address origins for IPv6 */
+static inline const std::unordered_set<
+    sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin>
+    originsV6Static = {sdbusplus::xyz::openbmc_project::Network::server::IP::
+                           AddressOrigin::Static};
+static inline const std::unordered_set<
+    sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin>
+    originsV6Dynamic = {
+        sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin::
+            DHCP,
+        sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin::
+            SLAAC,
+};
+
+/** @brief A lazy lookup mechanism for iterating over object properties stored
+ *         in DBus. This will only perform the object lookup when needed, and
+ *         retains a cache of previous lookups to speed up future iterations.
+ */
+class ObjectLookupCache
+{
+  public:
+    using PropertiesCache = std::unordered_map<std::string, PropertyMap>;
+
+    /** @brief Creates a new ObjectLookupCache for the interface on the bus
+     *         NOTE: The inputs to this object must outlive the object since
+     *         they are only referenced by it.
+     *
+     *  @param[in] bus    - The bus object used for lookups
+     *  @param[in] params - The parameters for the channel
+     *  @param[in] intf   - The interface we are looking up
+     */
+    ObjectLookupCache(sdbusplus::bus::bus& bus, const ChannelParams& params,
+                      const char* intf) :
+        bus(bus),
+        params(params), intf(intf),
+        objs(getAllDbusObjects(bus, params.logicalPath, intf, ""))
+    {
+    }
+
+    class iterator : public ObjectTree::const_iterator
+    {
+      public:
+        using value_type = PropertiesCache::value_type;
+
+        iterator(ObjectTree::const_iterator it, ObjectLookupCache& container) :
+            ObjectTree::const_iterator(it), container(container),
+            ret(container.cache.end())
+        {
+        }
+        value_type& operator*()
+        {
+            ret = container.get(ObjectTree::const_iterator::operator*().first);
+            return *ret;
+        }
+        value_type* operator->()
+        {
+            return &operator*();
+        }
+
+      private:
+        ObjectLookupCache& container;
+        PropertiesCache::iterator ret;
+    };
+
+    iterator begin() noexcept
+    {
+        return iterator(objs.begin(), *this);
+    }
+
+    iterator end() noexcept
+    {
+        return iterator(objs.end(), *this);
+    }
+
+  private:
+    sdbusplus::bus::bus& bus;
+    const ChannelParams& params;
+    const char* const intf;
+    const ObjectTree objs;
+    PropertiesCache cache;
+
+    /** @brief Gets a cached copy of the object properties if possible
+     *         Otherwise performs a query on DBus to look them up
+     *
+     *  @param[in] path - The object path to lookup
+     *  @return An iterator for the specified object path + properties
+     */
+    PropertiesCache::iterator get(const std::string& path)
+    {
+        auto it = cache.find(path);
+        if (it != cache.end())
+        {
+            return it;
+        }
+        auto properties = getAllDbusProperties(bus, params.service, path, intf);
+        return cache.insert({path, std::move(properties)}).first;
+    }
+};
+
+/** @brief Turns an IP address string into the network byte order form
+ *         NOTE: This version strictly validates family matches
+ *
+ *  @param[in] address - The string form of the address
+ *  @return A network byte order address or none if conversion failed
+ */
+template <int family>
+std::optional<typename AddrFamily<family>::addr>
+    maybeStringToAddr(const char* address)
+{
+    typename AddrFamily<family>::addr ret;
+    if (inet_pton(family, address, &ret) == 1)
+    {
+        return ret;
+    }
+    return std::nullopt;
+}
+
+/** @brief Turns an IP address string into the network byte order form
+ *         NOTE: This version strictly validates family matches
+ *
+ *  @param[in] address - The string form of the address
+ *  @return A network byte order address
+ */
+template <int family>
+typename AddrFamily<family>::addr stringToAddr(const char* address)
+{
+    auto ret = maybeStringToAddr<family>(address);
+    if (!ret)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Failed to convert IP Address",
+            phosphor::logging::entry("FAMILY=%d", family),
+            phosphor::logging::entry("ADDRESS=%s", address));
+        phosphor::logging::elog<
+            sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>();
+    }
+    return *ret;
+}
+
+/** @brief Turns an IP address in network byte order into a string
+ *
+ *  @param[in] address - The string form of the address
+ *  @return A network byte order address
+ */
+template <int family>
+std::string addrToString(const typename AddrFamily<family>::addr& address)
+{
+    std::string ret(AddrFamily<family>::maxStrLen, '\0');
+    inet_ntop(family, &address, ret.data(), ret.size());
+    ret.resize(strlen(ret.c_str()));
+    return ret;
+}
+
+/** @brief Converts a human readable MAC string into MAC bytes
+ *
+ *  @param[in] mac - The MAC string
+ *  @return MAC in bytes
+ */
+ether_addr stringToMAC(const char* mac);
+/** @brief Searches the ip object lookup cache for an address matching
+ *         the input parameters. NOTE: The index lacks stability across address
+ *         changes since the network daemon has no notion of stable indicies.
+ *
+ *  @param[in] bus     - The bus object used for lookups
+ *  @param[in] params  - The parameters for the channel
+ *  @param[in] idx     - The index of the desired address on the interface
+ *  @param[in] origins - The allowed origins for the address objects
+ *  @param[in] ips     - The object lookup cache holding all of the address info
+ *  @return The address and prefix if it was found
+ */
+template <int family>
+std::optional<IfAddr<family>> findIfAddr(
+    sdbusplus::bus::bus& bus, const ChannelParams& params, uint8_t idx,
+    const std::unordered_set<
+        sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin>&
+        origins,
+    ObjectLookupCache& ips)
+{
+    for (const auto& [path, properties] : ips)
+    {
+        const auto& addrStr = std::get<std::string>(properties.at("Address"));
+        auto addr = maybeStringToAddr<family>(addrStr.c_str());
+        if (!addr)
+        {
+            continue;
+        }
+
+        sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin
+            origin = sdbusplus::xyz::openbmc_project::Network::server::IP::
+                convertAddressOriginFromString(
+                    std::get<std::string>(properties.at("Origin")));
+        if (origins.find(origin) == origins.end())
+        {
+            continue;
+        }
+
+        if (idx > 0)
+        {
+            idx--;
+            continue;
+        }
+
+        IfAddr<family> ifaddr;
+        ifaddr.path = path;
+        ifaddr.address = *addr;
+        ifaddr.prefix = std::get<uint8_t>(properties.at("PrefixLength"));
+        ifaddr.origin = origin;
+        return std::move(ifaddr);
+    }
+
+    return std::nullopt;
+}
+/** @brief Trivial helper around findIfAddr that simplifies calls
+ *         for one off lookups. Don't use this if you intend to do multiple
+ *         lookups at a time.
+ *
+ *  @param[in] bus     - The bus object used for lookups
+ *  @param[in] params  - The parameters for the channel
+ *  @param[in] idx     - The index of the desired address on the interface
+ *  @param[in] origins - The allowed origins for the address objects
+ *  @return The address and prefix if it was found
+ */
+template <int family>
+auto getIfAddr(
+    sdbusplus::bus::bus& bus, const ChannelParams& params, uint8_t idx,
+    const std::unordered_set<
+        sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin>&
+        origins)
+{
+    ObjectLookupCache ips(bus, params, INTF_IP);
+    return findIfAddr<family>(bus, params, idx, origins, ips);
+}
+
+/** @brief Determines if the ethernet interface is using DHCP
+ *
+ *  @param[in] bus    - The bus object used for lookups
+ *  @param[in] params - The parameters for the channel
+ *  @return DHCPConf enumeration
+ */
+sdbusplus::xyz::openbmc_project::Network::server::EthernetInterface::DHCPConf
+    getDHCPProperty(sdbusplus::bus::bus& bus, const ChannelParams& params);
+
+/** @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 sdbusplus::xyz::openbmc_project::Network::server::
+                           EthernetInterface::DHCPConf requestedDhcp,
+                       const bool defaultMode);
+
+/** @brief Reconfigures the IPv6 address info configured for the interface
+ *
+ *  @param[in] bus     - The bus object used for lookups
+ *  @param[in] params  - The parameters for the channel
+ *  @param[in] idx     - The address index to operate on
+ *  @param[in] address - The new address
+ *  @param[in] prefix  - The new address prefix
+ */
+void reconfigureIfAddr6(sdbusplus::bus::bus& bus, const ChannelParams& params,
+                        uint8_t idx, const in6_addr& address, uint8_t prefix);
+
+/** @brief Retrieves the current gateway for the address family on the system
+ *         NOTE: The gateway is currently system wide and not per channel
+ *
+ *  @param[in] bus    - The bus object used for lookups
+ *  @param[in] params - The parameters for the channel
+ *  @return An address representing the gateway address if it exists
+ */
+template <int family>
+std::optional<typename AddrFamily<family>::addr>
+    getGatewayProperty(sdbusplus::bus::bus& bus, const ChannelParams& params)
+{
+    auto gatewayStr = std::get<std::string>(getDbusProperty(
+        bus, params.service, PATH_SYSTEMCONFIG, INTF_SYSTEMCONFIG,
+        AddrFamily<family>::propertyGateway));
+    if (gatewayStr.empty())
+    {
+        return std::nullopt;
+    }
+    return stringToAddr<family>(gatewayStr.c_str());
+}
+
+template <int family>
+std::optional<IfNeigh<family>>
+    findStaticNeighbor(sdbusplus::bus::bus& bus, const ChannelParams& params,
+                       const typename AddrFamily<family>::addr& ip,
+                       ObjectLookupCache& neighbors)
+{
+    using sdbusplus::xyz::openbmc_project::Network::server::Neighbor;
+    const auto state =
+        sdbusplus::xyz::openbmc_project::Network::server::convertForMessage(
+            Neighbor::State::Permanent);
+    for (const auto& [path, neighbor] : neighbors)
+    {
+        const auto& ipStr = std::get<std::string>(neighbor.at("IPAddress"));
+        auto neighIP = maybeStringToAddr<family>(ipStr.c_str());
+        if (!neighIP)
+        {
+            continue;
+        }
+        if (!equal(*neighIP, ip))
+        {
+            continue;
+        }
+        if (state != std::get<std::string>(neighbor.at("State")))
+        {
+            continue;
+        }
+
+        IfNeigh<family> ret;
+        ret.path = path;
+        ret.ip = ip;
+        const auto& macStr = std::get<std::string>(neighbor.at("MACAddress"));
+        ret.mac = stringToMAC(macStr.c_str());
+        return std::move(ret);
+    }
+
+    return std::nullopt;
+}
+
+template <int family>
+void createNeighbor(sdbusplus::bus::bus& bus, const ChannelParams& params,
+                    const typename AddrFamily<family>::addr& address,
+                    const ether_addr& mac)
+{
+    auto newreq =
+        bus.new_method_call(params.service.c_str(), params.logicalPath.c_str(),
+                            INTF_NEIGHBOR_CREATE_STATIC, "Neighbor");
+    std::string macStr = ether_ntoa(&mac);
+    newreq.append(addrToString<family>(address), macStr);
+    bus.call_noreply(newreq);
+}
+
+/** @brief Deletes the dbus object. Ignores empty objects or objects that are
+ *         missing from the bus.
+ *
+ *  @param[in] bus     - The bus object used for lookups
+ *  @param[in] service - The name of the service
+ *  @param[in] path    - The path of the object to delete
+ */
+void deleteObjectIfExists(sdbusplus::bus::bus& bus, const std::string& service,
+                          const std::string& path);
+
+/** @brief Sets the system wide value for the default gateway
+ *
+ *  @param[in] bus     - The bus object used for lookups
+ *  @param[in] params  - The parameters for the channel
+ *  @param[in] gateway - Gateway address to apply
+ */
+template <int family>
+void setGatewayProperty(sdbusplus::bus::bus& bus, const ChannelParams& params,
+                        const typename AddrFamily<family>::addr& address)
+{
+    // Save the old gateway MAC address if it exists so we can recreate it
+    auto gateway = getGatewayProperty<family>(bus, params);
+    std::optional<IfNeigh<family>> neighbor;
+    if (gateway)
+    {
+        ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
+        neighbor = findStaticNeighbor<family>(bus, params, *gateway, neighbors);
+    }
+
+    setDbusProperty(bus, params.service, PATH_SYSTEMCONFIG, INTF_SYSTEMCONFIG,
+                    AddrFamily<family>::propertyGateway,
+                    addrToString<family>(address));
+
+    // Restore the gateway MAC if we had one
+    if (neighbor)
+    {
+        deleteObjectIfExists(bus, params.service, neighbor->path);
+        createNeighbor<family>(bus, params, address, neighbor->mac);
+    }
+}
+
 } // namespace transport
 } // namespace ipmi
