Added sessionId context in host-ipmid, used by GetSessionInfo

SessionId is now passed to host-ipmid context along with userid
and privilege information. This will enable certain commands to know
the current sessionid

Added option to get current session info in get session info command.

With this change, we can get the current session info by passing
sessionIndex as zero in get session info command via lan interface and
the same via host interface will return an error, beacuse no session
will be created for host interface.

Tested:

ipmitool -I lanplus -U <user> -P <password> -H <lan1_ip> raw 6 0x3d <Zero>
Response : gives currents session info

ipmitool -I lanplus -U <user> -P <password> -H <lan2_ip> raw 6 0x3d <Zero>
Response : gives currents session info

//host interface
ipmitool raw 6 0x3d 0
Response: 0xCC // invalid field in the request

//This command shows info of all sessions, which includes current
session info as well.
ipmitool -I lanplus -U <user> -P <password> -H <lan1_ip> session info all
session handle                : 129
slot count                    : 45
active sessions               : 1
user id                       : 1
privilege level               : ADMINISTRATOR
session type                  : IPMIv1.5
channel number                : 0x03
console ip                    : 0.0.0.0
console mac                   : 00:00:00:00:00:00
console port                  : 52670

session handle                : 0
slot count                    : 45
active sessions               : 1

//This command shows info of all sessions, which includes current
session info as well.
ipmitool -I lanplus -U <user> -P <password> -H <lan2_ip> session info all
session handle                : 0
slot count                    : 45
active sessions               : 1

session handle                : 1
slot count                    : 45
active sessions               : 1
user id                       : 1
privilege level               : ADMINISTRATOR
session type                  : IPMIv1.5
channel number                : 0x01
console ip                    : 0.0.0.0
console mac                   : 00:00:00:00:00:00
console port                  : 57622

//host interface
ipmitool session info all
session handle                : 0
slot count                    : 45
active sessions               : 0

session handle                : 0
slot count                    : 45
active sessions               : 0

Tested other postive and negative test cases for get session info
command in Lan1, Lan2 and host interfaces. All are working fine.

Signed-off-by: Rajashekar Gade Reddy <raja.sekhar.reddy.gade@linux.intel.com>
Change-Id: I9fb1ef12693e4c0da3661ffdf21eec248b48b5b4
diff --git a/apphandler.cpp b/apphandler.cpp
index 8f11a8c..43cddd7 100644
--- a/apphandler.cpp
+++ b/apphandler.cpp
@@ -974,6 +974,7 @@
  * This function validates the request data and retrive request session id,
  * session handle.
  *
+ * @param[in] ctx - context of current session.
  * @param[in] sessionIndex - request session index
  * @param[in] payload - input payload
  * @param[in] reqSessionId - unpacked session Id will be asigned
@@ -982,20 +983,43 @@
  * @return success completion code if request data is valid
  * else return the correcponding error completion code.
  **/
-uint8_t getSessionInfoRequestData(const uint8_t sessionIndex,
+uint8_t getSessionInfoRequestData(const ipmi::Context::ptr ctx,
+                                  const uint8_t sessionIndex,
                                   ipmi::message::Payload& payload,
                                   uint32_t& reqSessionId,
                                   uint8_t& reqSessionHandle)
 {
-    if (sessionIndex == session::sessionZero ||
-        ((sessionIndex > session::maxSessionCountPerChannel) &&
-         (sessionIndex < session::searchSessionByHandle)))
+    if ((sessionIndex > session::maxSessionCountPerChannel) &&
+        (sessionIndex < session::searchSessionByHandle))
     {
         return ipmi::ccInvalidFieldRequest;
     }
 
     switch (sessionIndex)
     {
+        case session::searchCurrentSession:
+
+            ipmi::ChannelInfo chInfo;
+            ipmi::getChannelInfo(ctx->channel, chInfo);
+
+            if (static_cast<ipmi::EChannelMediumType>(chInfo.mediumType) !=
+                ipmi::EChannelMediumType::lan8032)
+            {
+                return ipmi::ccInvalidFieldRequest;
+            }
+
+            if (!payload.fullyUnpacked())
+            {
+                return ipmi::ccReqDataLenInvalid;
+            }
+            // Check if current sessionId is 0, sessionId 0 is reserved.
+            if (ctx->sessionId == session::sessionZero)
+            {
+                return session::ccInvalidSessionId;
+            }
+            reqSessionId = ctx->sessionId;
+            break;
+
         case session::searchSessionByHandle:
 
             if ((payload.unpack(reqSessionHandle)) ||
@@ -1120,7 +1144,8 @@
                              std::array<uint8_t, macAddrLen>, // mac address
                              uint16_t                         // remote port
                              >>>
-    ipmiAppGetSessionInfo(uint8_t sessionIndex, ipmi::message::Payload& payload)
+    ipmiAppGetSessionInfo(ipmi::Context::ptr ctx, uint8_t sessionIndex,
+                          ipmi::message::Payload& payload)
 {
     uint32_t reqSessionId = 0;
     uint8_t reqSessionHandle = session::defaultSessionHandle;
@@ -1128,7 +1153,7 @@
     uint8_t state = 0xFF;
 
     uint8_t completionCode = getSessionInfoRequestData(
-        sessionIndex, payload, reqSessionId, reqSessionHandle);
+        ctx, sessionIndex, payload, reqSessionId, reqSessionHandle);
 
     if (completionCode)
     {
diff --git a/include/ipmid/message.hpp b/include/ipmid/message.hpp
index 0dc7ca8..c828e3c 100644
--- a/include/ipmid/message.hpp
+++ b/include/ipmid/message.hpp
@@ -42,11 +42,11 @@
     Context& operator=(Context&&) = delete;
 
     Context(std::shared_ptr<sdbusplus::asio::connection> bus, NetFn netFn,
-            Cmd cmd, int channel, int userId, Privilege priv, int rqSA,
-            boost::asio::yield_context& yield) :
+            Cmd cmd, int channel, int userId, uint32_t sessionId,
+            Privilege priv, int rqSA, boost::asio::yield_context& yield) :
         bus(bus),
-        netFn(netFn), cmd(cmd), channel(channel), userId(userId), priv(priv),
-        rqSA(rqSA), yield(yield)
+        netFn(netFn), cmd(cmd), channel(channel), userId(userId),
+        sessionId(sessionId), priv(priv), rqSA(rqSA), yield(yield)
     {
     }
 
@@ -56,6 +56,7 @@
     Cmd cmd;
     int channel;
     int userId;
+    uint32_t sessionId;
     Privilege priv;
     // srcAddr is only set on IPMB requests because
     // Platform Event Message needs it to determine the incoming format
diff --git a/include/ipmid/sessiondef.hpp b/include/ipmid/sessiondef.hpp
index 7802fb9..ac63f8f 100644
--- a/include/ipmid/sessiondef.hpp
+++ b/include/ipmid/sessiondef.hpp
@@ -32,6 +32,7 @@
 static constexpr uint8_t maxNetworkInstanceSupported = 4;
 static constexpr uint8_t ccInvalidSessionId = 0x87;
 static constexpr uint8_t ccInvalidSessionHandle = 0x88;
+static constexpr uint8_t searchCurrentSession = 0;
 static constexpr uint8_t searchSessionByHandle = 0xFE;
 static constexpr uint8_t searchSessionById = 0xFF;
 // MSB BIT 7 BIT 6 assigned for netipmid instance in session handle.
diff --git a/ipmid-new.cpp b/ipmid-new.cpp
index f210c5d..03b6b8a 100644
--- a/ipmid-new.cpp
+++ b/ipmid-new.cpp
@@ -477,6 +477,7 @@
     Privilege privilege = Privilege::None;
     int rqSA = 0;
     uint8_t userId = 0; // undefined user
+    uint32_t sessionId = 0;
 
     // figure out what channel the request came in on
     uint8_t channel = channelFromMessage(m);
@@ -489,15 +490,19 @@
         return dbusResponse(ipmi::ccDestinationUnavailable);
     }
 
-    // session-based channels are required to provide userId/privilege
+    // session-based channels are required to provide userId, privilege and
+    // sessionId
     if (getChannelSessionSupport(channel) != EChannelSessSupported::none)
     {
         try
         {
             Value requestPriv = options.at("privilege");
             Value requestUserId = options.at("userId");
+            Value requestSessionId = options.at("currentSessionId");
             privilege = static_cast<Privilege>(std::get<int>(requestPriv));
             userId = static_cast<uint8_t>(std::get<int>(requestUserId));
+            sessionId =
+                static_cast<uint32_t>(std::get<uint32_t>(requestSessionId));
         }
         catch (const std::exception& e)
         {
@@ -533,11 +538,13 @@
     log<level::DEBUG>("Set up ipmi context", entry("SENDER=%s", sender.c_str()),
                       entry("NETFN=0x%X", netFn), entry("CMD=0x%X", cmd),
                       entry("CHANNEL=%u", channel), entry("USERID=%u", userId),
+                      entry("SESSIONID=0x%X", sessionId),
                       entry("PRIVILEGE=%u", static_cast<uint8_t>(privilege)),
                       entry("RQSA=%x", rqSA));
 
-    auto ctx = std::make_shared<ipmi::Context>(getSdBus(), netFn, cmd, channel,
-                                               userId, privilege, rqSA, yield);
+    auto ctx =
+        std::make_shared<ipmi::Context>(getSdBus(), netFn, cmd, channel, userId,
+                                        sessionId, privilege, rqSA, yield);
     auto request = std::make_shared<ipmi::message::Request>(
         ctx, std::forward<std::vector<uint8_t>>(data));
     message::Response::ptr response = executeIpmiCommand(request);
@@ -750,7 +757,7 @@
         m.read(seq, netFn, lun, cmd, data);
         std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
         auto ctx = std::make_shared<ipmi::Context>(
-            bus, netFn, cmd, 0, 0, ipmi::Privilege::Admin, 0, yield);
+            bus, netFn, cmd, 0, 0, 0, ipmi::Privilege::Admin, 0, yield);
         auto request = std::make_shared<ipmi::message::Request>(
             ctx, std::forward<std::vector<uint8_t>>(data));
         ipmi::message::Response::ptr response =