diff --git a/ipmbbridged.cpp b/ipmbbridged.cpp
new file mode 100644
index 0000000..2f78cd0
--- /dev/null
+++ b/ipmbbridged.cpp
@@ -0,0 +1,752 @@
+/* Copyright 2018 Intel
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#include "ipmbbridged.hpp"
+
+#include "ipmbdefines.hpp"
+#include "ipmbutils.hpp"
+
+#include <linux/i2c-dev-user.h>
+
+#include <phosphor-logging/log.hpp>
+#include <tuple>
+
+/**
+ * @brief Dbus
+ */
+static constexpr const char *ipmbBus = "xyz.openbmc_project.Ipmi.Channel.Ipmb";
+static constexpr const char *ipmbObj = "/xyz/openbmc_project/Ipmi/Channel/Ipmb";
+static constexpr const char *hostIpmiIntf = "org.openbmc.HostIpmi";
+static constexpr const char *ipmbDbusIntf = "org.openbmc.Ipmb";
+
+boost::asio::io_service io;
+auto conn = std::make_shared<sdbusplus::asio::connection>(io);
+
+/**
+ * @brief Channel configuration table
+ * TODO : move to user configuration as JSON file
+ */
+static const std::vector<IpmbChannelConfig> ipmbChannelsConfig = {
+    // ME channel
+    {ipmbChannelType::me, "/sys/bus/i2c/devices/5-1010/slave-mqueue",
+     "/dev/i2c-5", 0x20, 0x2C}, // 8 bit addresses
+    // IPMB header channel
+    {ipmbChannelType::ipmb, "/sys/bus/i2c/devices/0-1010/slave-mqueue",
+     "/dev/i2c-0", 0x20, 0x58}}; // 8 bit addresses
+
+static std::list<IpmbChannel> ipmbChannels;
+
+/**
+ * @brief Ipmb request class methods
+ */
+IpmbRequest::IpmbRequest()
+{
+    data.reserve(ipmbMaxDataSize);
+}
+
+IpmbRequest::IpmbRequest(uint8_t address, uint8_t netFn, uint8_t rsLun,
+                         uint8_t rqSA, uint8_t seq, uint8_t rqLun, uint8_t cmd,
+                         std::vector<uint8_t> &inputData) :
+    address(address),
+    netFn(netFn), rsLun(rsLun), rqSA(rqSA), seq(seq), rqLun(rqLun), cmd(cmd),
+    timer(io)
+{
+    data.reserve(ipmbMaxDataSize);
+    state = ipmbRequestState::invalid;
+
+    if (inputData.size() > 0)
+    {
+        data = std::move(inputData);
+    }
+}
+
+void IpmbRequest::incomingMessageHandler()
+{
+    sdbusplus::message::message mesg =
+        conn->new_signal(ipmbObj, hostIpmiIntf, "ReceivedMessage");
+    mesg.append(seq, netFn, rsLun, cmd, data);
+    mesg.signal_send();
+}
+
+void IpmbRequest::i2cToIpmbConstruct(IPMB_HEADER *ipmbBuffer,
+                                     size_t bufferLength)
+{
+    // constructing ipmb request from i2c buffer
+    netFn = ipmbNetFnGet(ipmbBuffer->Header.Req.rsNetFnLUN);
+    rsLun = ipmbLunFromNetFnLunGet(ipmbBuffer->Header.Req.rsNetFnLUN);
+    rqSA = ipmbBuffer->Header.Req.rqSA;
+    seq = ipmbSeqGet(ipmbBuffer->Header.Req.rqSeqLUN);
+    rqLun = ipmbLunFromSeqLunGet(ipmbBuffer->Header.Req.rqSeqLUN);
+    cmd = ipmbBuffer->Header.Req.cmd;
+
+    size_t dataLength =
+        bufferLength - (ipmbConnectionHeaderLength +
+                        ipmbRequestDataHeaderLength + ipmbChecksumSize);
+
+    if (dataLength > 0)
+    {
+        data.insert(data.end(), ipmbBuffer->Header.Req.data,
+                    &ipmbBuffer->Header.Req.data[dataLength]);
+    }
+}
+
+int IpmbRequest::ipmbToi2cConstruct(std::vector<uint8_t> &buffer)
+{
+    size_t bufferLength = data.size() + ipmbRequestDataHeaderLength +
+                          ipmbConnectionHeaderLength + ipmbChecksumSize;
+
+    if (bufferLength > ipmbMaxFrameLength)
+    {
+        return -1;
+    }
+
+    buffer.resize(bufferLength);
+    static_assert(ipmbMaxFrameLength >= sizeof(IPMB_HEADER));
+    auto ipmbBuffer = reinterpret_cast<IPMB_HEADER *>(buffer.data());
+
+    // constructing buffer from ipmb request
+    ipmbBuffer->Header.Req.address = address;
+    ipmbBuffer->Header.Req.rsNetFnLUN = ipmbNetFnLunSet(netFn, rsLun);
+    ipmbBuffer->Header.Req.rqSA = rqSA;
+    ipmbBuffer->Header.Req.rqSeqLUN = ipmbSeqLunSet(seq, rqLun);
+    ipmbBuffer->Header.Req.cmd = cmd;
+
+    ipmbBuffer->Header.Resp.checksum1 = ipmbChecksumCompute(
+        buffer.data(), ipmbConnectionHeaderLength - ipmbChecksumSize);
+
+    if (data.size() > 0)
+    {
+        std::copy(data.begin(), data.end(), ipmbBuffer->Header.Req.data);
+    }
+
+    buffer[bufferLength - ipmbChecksumSize] =
+        ipmbChecksumCompute(buffer.data() + ipmbChecksum2StartOffset,
+                            (ipmbRequestDataHeaderLength + data.size()));
+
+    return 0;
+}
+
+std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
+    IpmbRequest::returnMatchedResponse()
+{
+    return std::make_tuple(
+        static_cast<int>(ipmbResponseStatus::success), matchedResponse->netFn,
+        matchedResponse->rsLun, matchedResponse->cmd,
+        matchedResponse->completionCode, matchedResponse->data);
+}
+
+static std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
+    returnStatus(ipmbResponseStatus status)
+{
+    // we only want to send status here, other fields are not relevant
+    return std::make_tuple(static_cast<int>(status), 0, 0, 0, 0,
+                           std::vector<uint8_t>(0));
+}
+
+// TODO w/a to differentiate channel origin of incoming IPMI response: saving
+// channel number at two oldest unused bits of seq
+void IpmbRequest::addChannelToSeq(const ipmbChannelType &channelType)
+{
+    uint8_t newSeq = (seq | ((static_cast<uint8_t>(channelType) & 0x3) << 6));
+    seq = newSeq;
+}
+
+/**
+ * @brief Ipmb response class methods
+ */
+IpmbResponse::IpmbResponse()
+{
+    data.reserve(ipmbMaxDataSize);
+}
+
+IpmbResponse::IpmbResponse(uint8_t address, uint8_t netFn, uint8_t rqLun,
+                           uint8_t rsSA, uint8_t seq, uint8_t rsLun,
+                           uint8_t cmd, uint8_t completionCode,
+                           std::vector<uint8_t> &inputData) :
+    address(address),
+    netFn(netFn), rqLun(rqLun), rsSA(rsSA), seq(seq), rsLun(rsLun), cmd(cmd),
+    completionCode(completionCode)
+{
+    data.reserve(ipmbMaxDataSize);
+
+    if (inputData.size() > 0)
+    {
+        data = std::move(inputData);
+    }
+}
+
+void IpmbResponse::i2cToIpmbConstruct(IPMB_HEADER *ipmbBuffer,
+                                      size_t bufferLength)
+{
+    netFn = ipmbNetFnGet(ipmbBuffer->Header.Resp.rqNetFnLUN);
+    rqLun = ipmbLunFromNetFnLunGet(ipmbBuffer->Header.Resp.rqNetFnLUN);
+    rsSA = ipmbBuffer->Header.Resp.rsSA;
+    seq = ipmbSeqGet(ipmbBuffer->Header.Resp.rsSeqLUN);
+    rsLun = ipmbLunFromSeqLunGet(ipmbBuffer->Header.Resp.rsSeqLUN);
+    cmd = ipmbBuffer->Header.Resp.cmd;
+    completionCode = ipmbBuffer->Header.Resp.completionCode;
+
+    size_t dataLength =
+        bufferLength - (ipmbConnectionHeaderLength +
+                        ipmbResponseDataHeaderLength + ipmbChecksumSize);
+
+    if (dataLength > 0)
+    {
+        data.insert(data.end(), ipmbBuffer->Header.Resp.data,
+                    &ipmbBuffer->Header.Resp.data[dataLength]);
+    }
+}
+
+int IpmbResponse::ipmbToi2cConstruct(std::vector<uint8_t> &buffer)
+{
+    size_t bufferLength = data.size() + ipmbResponseDataHeaderLength +
+                          ipmbConnectionHeaderLength + ipmbChecksumSize;
+
+    if (bufferLength > ipmbMaxFrameLength)
+    {
+        return -1;
+    }
+
+    buffer.resize(bufferLength);
+    auto ipmbBuffer = reinterpret_cast<IPMB_HEADER *>(buffer.data());
+
+    ipmbBuffer->Header.Resp.address = address;
+    ipmbBuffer->Header.Resp.rqNetFnLUN = ipmbNetFnLunSet(netFn, rqLun);
+    ipmbBuffer->Header.Resp.rsSA = rsSA;
+    ipmbBuffer->Header.Resp.rsSeqLUN = ipmbSeqLunSet(seq, rsLun);
+    ipmbBuffer->Header.Resp.cmd = cmd;
+    ipmbBuffer->Header.Resp.completionCode = completionCode;
+
+    ipmbBuffer->Header.Resp.checksum1 = ipmbChecksumCompute(
+        buffer.data(), ipmbConnectionHeaderLength - ipmbChecksumSize);
+
+    if (data.size() > 0)
+    {
+        std::copy(data.begin(), data.end(), ipmbBuffer->Header.Resp.data);
+    }
+
+    buffer[bufferLength - ipmbChecksumSize] =
+        ipmbChecksumCompute(buffer.data() + ipmbChecksum2StartOffset,
+                            (ipmbResponseDataHeaderLength + data.size()));
+
+    return 0;
+}
+
+bool IpmbCommandFilter::isBlocked(const uint8_t reqNetFn, const uint8_t cmd)
+{
+    auto blockedCmd = unhandledCommands.find({reqNetFn, cmd});
+
+    if (blockedCmd != unhandledCommands.end())
+    {
+        return true;
+    }
+
+    return false;
+}
+
+void IpmbCommandFilter::addFilter(const uint8_t reqNetFn, const uint8_t cmd)
+{
+    if (unhandledCommands.insert({reqNetFn, cmd}).second)
+    {
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "addFilter: added command to filter",
+            phosphor::logging::entry("netFn = %d", reqNetFn),
+            phosphor::logging::entry("cmd = %d", cmd));
+    }
+}
+
+/**
+ * @brief Ipmb channel
+ */
+void IpmbChannel::ipmbResponseSend(std::shared_ptr<std::vector<uint8_t>> buffer,
+                                   size_t retriesAttempted = 0)
+{
+    boost::asio::async_write(
+        i2cMasterSocket,
+        boost::asio::buffer(buffer->data() + ipmbAddressSize,
+                            buffer->size() - ipmbAddressSize),
+        [this, buffer, retriesAttempted](const boost::system::error_code ec,
+                                         size_t bytesSent) {
+            if (ec)
+            {
+                size_t currentRetryCnt = retriesAttempted;
+
+                if (currentRetryCnt > ipmbI2cNumberOfRetries)
+                {
+                    phosphor::logging::log<phosphor::logging::level::ERR>(
+                        "ipmbResponseSend: sent to I2C failed after retries");
+                    return;
+                }
+                currentRetryCnt++;
+                ipmbResponseSend(buffer, currentRetryCnt);
+            }
+        });
+}
+
+/**
+ * @brief Ipmb Outstanding Requests
+ */
+void IpmbChannel::makeRequestInvalid(IpmbRequest &request)
+{
+    // change request state to invalid and remove it from outstanding requests
+    // list
+    request.state = ipmbRequestState::invalid;
+    outstandingRequests[request.seq] = nullptr;
+}
+
+void IpmbChannel::makeRequestValid(std::shared_ptr<IpmbRequest> request)
+{
+    // change request state to valid and add it to outstanding requests list
+    request->state = ipmbRequestState::valid;
+    outstandingRequests[request->seq] = request;
+}
+
+bool IpmbChannel::seqNumGet(uint8_t &seq)
+{
+    static uint8_t seqNum = 0;
+
+    for (int i = 0; i < ipmbMaxOutstandingRequestsCount; i++)
+    {
+        seqNum = ++seqNum & ipmbSeqMask;
+        if (seqNum == ipmbMaxOutstandingRequestsCount)
+        {
+            seqNum = 0;
+        }
+
+        if (outstandingRequests[seqNum] == nullptr)
+        {
+            seq = seqNum;
+            return true;
+        }
+    }
+
+    return false;
+}
+
+void IpmbChannel::responseMatch(std::unique_ptr<IpmbResponse> &response)
+{
+    std::shared_ptr<IpmbRequest> request = outstandingRequests[response->seq];
+
+    if (request != nullptr)
+    {
+        if (((ipmbRespNetFn(request->netFn)) == (response->netFn)) &&
+            ((request->rqLun) == (response->rqLun)) &&
+            ((request->rsLun) == (response->rsLun)) &&
+            ((request->cmd) == (response->cmd)))
+        {
+            // match, response is corresponding to previously sent request
+            request->state = ipmbRequestState::matched;
+            request->timer->cancel();
+            request->matchedResponse = std::move(response);
+        }
+    }
+}
+
+void IpmbChannel::processI2cEvent()
+{
+    std::array<uint8_t, ipmbMaxFrameLength> buffer{};
+    auto ipmbFrame = reinterpret_cast<IPMB_HEADER *>(buffer.data());
+
+    lseek(ipmbi2cSlaveFd, 0, SEEK_SET);
+    int r = read(ipmbi2cSlaveFd, buffer.data(), ipmbMaxFrameLength);
+    if ((r < ipmbMinFrameLength) || (r > ipmbMaxFrameLength))
+    {
+        goto end;
+    }
+
+    // valiate the frame
+    if (!isFrameValid(ipmbFrame, r))
+    {
+        goto end;
+    }
+
+    // copy frame to ipmib message buffer
+    if (ipmbIsResponse(ipmbFrame))
+    {
+        std::unique_ptr<IpmbResponse> ipmbMessageReceived =
+            std::make_unique<IpmbResponse>();
+
+        ipmbMessageReceived->i2cToIpmbConstruct(ipmbFrame, r);
+
+        // try to match response with outstanding request
+        responseMatch(ipmbMessageReceived);
+    }
+    else
+    {
+        // if command is blocked - respond with 'invalid command'
+        // completion code
+        if (commandFilter)
+        {
+            uint8_t netFn = ipmbNetFnGet(ipmbFrame->Header.Req.rsNetFnLUN);
+            uint8_t cmd = ipmbFrame->Header.Req.cmd;
+
+            if (commandFilter->isBlocked(netFn, cmd))
+            {
+                uint8_t seq = ipmbSeqGet(ipmbFrame->Header.Req.rqSeqLUN);
+                uint8_t lun =
+                    ipmbLunFromSeqLunGet(ipmbFrame->Header.Req.rqSeqLUN);
+                std::vector<uint8_t> data;
+
+                // prepare generic response
+                auto ipmbResponse =
+                    IpmbResponse(ipmbRqSlaveAddress, ipmbRespNetFn(netFn), lun,
+                                 ipmbBmcSlaveAddress, seq, ipmbRsLun, cmd,
+                                 ipmbIpmiInvalidCommand, data);
+
+                std::shared_ptr<std::vector<uint8_t>> buffer =
+                    std::make_shared<std::vector<uint8_t>>();
+
+                if (ipmbResponse.ipmbToi2cConstruct(*buffer) == 0)
+                {
+                    ipmbResponseSend(buffer);
+                }
+
+                goto end;
+            }
+        }
+
+        auto ipmbMessageReceived = IpmbRequest();
+
+        ipmbMessageReceived.i2cToIpmbConstruct(ipmbFrame, r);
+
+        // TODO w/a to differentiate channel origin of incoming IPMI
+        // response: extracting channel number from seq
+        ipmbMessageReceived.addChannelToSeq(getChannelType());
+
+        // send request to the client
+        ipmbMessageReceived.incomingMessageHandler();
+    }
+
+end:
+    i2cSlaveSocket.async_wait(
+        boost::asio::ip::tcp::socket::wait_error,
+        [this](const boost::system::error_code &ec) {
+            if (ec)
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "Error: processI2cEvent()");
+                return;
+            }
+
+            processI2cEvent();
+        });
+}
+
+IpmbChannel::IpmbChannel(boost::asio::io_service &io,
+                         uint8_t ipmbBmcSlaveAddress,
+                         uint8_t ipmbRqSlaveAddress, ipmbChannelType type,
+                         std::shared_ptr<IpmbCommandFilter> commandFilter) :
+    i2cSlaveSocket(io),
+    i2cMasterSocket(io), ipmbBmcSlaveAddress(ipmbBmcSlaveAddress),
+    ipmbRqSlaveAddress(ipmbRqSlaveAddress), type(type),
+    commandFilter(commandFilter)
+{
+}
+
+int IpmbChannel::ipmbChannelInit(const char *ipmbI2cSlave,
+                                 const char *ipmbI2cMaster)
+{
+    // open fd to i2c slave device
+    ipmbi2cSlaveFd = open(ipmbI2cSlave, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+    if (ipmbi2cSlaveFd < 0)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "ipmbChannelInit: error opening ipmbI2cSlave");
+        return -1;
+    }
+
+    // open fd to i2c master device
+    ipmbi2cMasterFd = open(ipmbI2cMaster, O_RDWR | O_NONBLOCK);
+    if (ipmbi2cMasterFd < 0)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "ipmbChannelInit: error opening ipmbI2cMaster");
+        close(ipmbi2cSlaveFd);
+        return -1;
+    }
+
+    // set slave address of recipient
+    if (ioctl(ipmbi2cMasterFd, I2C_SLAVE,
+              ipmbAddressTo7BitSet(ipmbRqSlaveAddress)) < 0)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "ipmbChannelInit: error setting ipmbi2cMasterFd slave address");
+        close(ipmbi2cSlaveFd);
+        close(ipmbi2cMasterFd);
+        return -1;
+    }
+
+    i2cMasterSocket.assign(ipmbi2cMasterFd);
+    i2cSlaveSocket.assign(boost::asio::ip::tcp::v4(), ipmbi2cSlaveFd);
+    i2cSlaveSocket.async_wait(
+        boost::asio::ip::tcp::socket::wait_error,
+        [this](const boost::system::error_code &ec) {
+            if (ec)
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "Error: processI2cEvent()");
+                return;
+            }
+
+            processI2cEvent();
+        });
+
+    return 0;
+}
+
+uint8_t IpmbChannel::getBmcSlaveAddress()
+{
+    return ipmbBmcSlaveAddress;
+}
+
+uint8_t IpmbChannel::getRqSlaveAddress()
+{
+    return ipmbRqSlaveAddress;
+}
+
+ipmbChannelType IpmbChannel::getChannelType()
+{
+    return type;
+}
+
+void IpmbChannel::addFilter(const uint8_t respNetFn, const uint8_t cmd)
+{
+    if (commandFilter)
+    {
+        commandFilter->addFilter(respNetFn, cmd);
+    }
+}
+
+std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
+    IpmbChannel::requestAdd(boost::asio::yield_context &yield,
+                            std::shared_ptr<IpmbRequest> request)
+{
+    makeRequestValid(request);
+
+    std::vector<uint8_t> buffer(0);
+    if (request->ipmbToi2cConstruct(buffer) != 0)
+    {
+        return returnStatus(ipmbResponseStatus::error);
+    }
+
+    for (int i = 0; i < ipmbNumberOfTries; i++)
+    {
+        boost::system::error_code ec;
+
+        for (int j = 0; j < ipmbI2cNumberOfRetries; j++)
+        {
+            boost::asio::async_write(
+                i2cMasterSocket,
+                boost::asio::buffer(buffer.data() + ipmbAddressSize,
+                                    buffer.size() - ipmbAddressSize),
+                yield[ec]);
+
+            if (ec)
+            {
+                phosphor::logging::log<phosphor::logging::level::INFO>(
+                    "requestAdd: Sent to I2C failed");
+                continue;
+            }
+            break;
+        }
+
+        request->timer->expires_after(
+            std::chrono::milliseconds(ipmbRequestRetryTimeout));
+        request->timer->async_wait(yield[ec]);
+
+        if (ec && ec != boost::asio::error::operation_aborted)
+        {
+            // unexpected error - invalidate request and return generic error
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "requestAdd: async_wait error");
+            makeRequestInvalid(*request);
+            return returnStatus(ipmbResponseStatus::error);
+        }
+
+        if (request->state == ipmbRequestState::matched)
+        {
+            // matched response, send it to client application
+            makeRequestInvalid(*request);
+            return request->returnMatchedResponse();
+        }
+    }
+
+    makeRequestInvalid(*request);
+    return returnStatus(ipmbResponseStatus::timeout);
+}
+
+static IpmbChannel *getChannel(ipmbChannelType channelType)
+{
+    auto channel =
+        std::find_if(ipmbChannels.begin(), ipmbChannels.end(),
+                     [channelType](IpmbChannel &channel) {
+                         return channel.getChannelType() == channelType;
+                     });
+    if (channel != ipmbChannels.end())
+    {
+        return &(*channel);
+    }
+
+    return nullptr;
+}
+
+static int initializeChannels()
+{
+    std::shared_ptr<IpmbCommandFilter> commandFilter =
+        std::make_shared<IpmbCommandFilter>();
+
+    for (const auto &channelConfig : ipmbChannelsConfig)
+    {
+        auto channel = ipmbChannels.emplace(ipmbChannels.end(), io,
+                                            channelConfig.ipmbBmcSlaveAddress,
+                                            channelConfig.ipmbRqSlaveAddress,
+                                            channelConfig.type, commandFilter);
+
+        if (channel->ipmbChannelInit(channelConfig.ipmbI2cSlave,
+                                     channelConfig.ipmbI2cMaster) < 0)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "initializeChannels: channel initialization failed");
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+/**
+ * @brief Dbus callbacks
+ */
+auto ipmbSendMessage = [](uint8_t seq, uint8_t netfn, uint8_t lun, uint8_t cmd,
+                          uint8_t cc, std::vector<uint8_t> &dataReceived) {
+    int64_t status = -1;
+    std::shared_ptr<std::vector<uint8_t>> buffer =
+        std::make_shared<std::vector<uint8_t>>();
+
+    if (dataReceived.size() > ipmbMaxDataSize)
+    {
+        return status;
+    }
+
+    if (netfn & ipmbNetFnResponseMask)
+    {
+        IpmbChannel *channel = getChannel(getChannelFromSeq(seq));
+        if (channel == nullptr)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "ipmbSendMessage: channel does not exist");
+            return status;
+        }
+
+        // if command is not supported, add it to filter
+        if (cc == ipmbIpmiInvalidCommand)
+        {
+            channel->addFilter(ipmbReqNetFnFromRespNetFn(netfn), cmd);
+        }
+
+        uint8_t rqSlaveAddress = channel->getRqSlaveAddress();
+        uint8_t bmcSlaveAddress = channel->getBmcSlaveAddress();
+
+        // response received
+        // dataReceived is empty after constructor invocation
+        std::unique_ptr<IpmbResponse> ipmbMessageReceived =
+            std::make_unique<IpmbResponse>(rqSlaveAddress, netfn, lun,
+                                           bmcSlaveAddress, seq, lun, cmd, cc,
+                                           dataReceived);
+
+        status = ipmbMessageReceived->ipmbToi2cConstruct(*buffer);
+        if (status != 0)
+        {
+            return status;
+        }
+
+        channel->ipmbResponseSend(buffer);
+        return status;
+    }
+
+    // we are not expecting request here
+    phosphor::logging::log<phosphor::logging::level::ERR>(
+        "ipmbSendMessage: got a request");
+    return status;
+};
+
+auto ipmbHandleRequest = [](boost::asio::yield_context yield,
+                            uint8_t reqChannel, uint8_t netfn, uint8_t lun,
+                            uint8_t cmd, std::vector<uint8_t> dataReceived) {
+    IpmbChannel *channel = getChannel(static_cast<ipmbChannelType>(reqChannel));
+    if (channel == nullptr)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "ipmbHandleRequest: requested channel does not exist");
+        return returnStatus(ipmbResponseStatus::invalid_param);
+    }
+
+    // check outstanding request list for valid sequence number
+    uint8_t seqNum = 0;
+    bool seqValid = channel->seqNumGet(seqNum);
+    if (!seqValid)
+    {
+        phosphor::logging::log<phosphor::logging::level::WARNING>(
+            "ipmbHandleRequest: cannot add more requests to the list");
+        return returnStatus(ipmbResponseStatus::busy);
+    }
+
+    uint8_t bmcSlaveAddress = channel->getBmcSlaveAddress();
+    uint8_t rqSlaveAddress = channel->getRqSlaveAddress();
+
+    // construct the request to add it to outstanding request list
+    std::shared_ptr<IpmbRequest> request = std::make_shared<IpmbRequest>(
+        rqSlaveAddress, netfn, ipmbRsLun, bmcSlaveAddress, seqNum, lun, cmd,
+        dataReceived);
+
+    if (!request->timer)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "ipmbHandleRequest: timer object does not exist");
+        return returnStatus(ipmbResponseStatus::error);
+    }
+
+    return channel->requestAdd(yield, request);
+};
+
+/**
+ * @brief Main
+ */
+int main(int argc, char *argv[])
+{
+    conn->request_name(ipmbBus);
+
+    auto server = sdbusplus::asio::object_server(conn);
+
+    std::shared_ptr<sdbusplus::asio::dbus_interface> ipmiIface =
+        server.add_interface(ipmbObj, hostIpmiIntf);
+    std::shared_ptr<sdbusplus::asio::dbus_interface> ipmbIface =
+        server.add_interface(ipmbObj, ipmbDbusIntf);
+
+    ipmiIface->register_method("sendMessage", std::move(ipmbSendMessage));
+    ipmbIface->register_method("sendRequest", std::move(ipmbHandleRequest));
+    ipmiIface->initialize();
+    ipmbIface->initialize();
+
+    if (initializeChannels() < 0)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error initializeChannels");
+        return -1;
+    }
+
+    io.run();
+    return 0;
+}
