summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0007-Adding-support-for-GetSessionInfo-command.patch
blob: bbbe6ae4ff81fab1159343d7cce9ac9330c28c65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
From b05fb3231810865ef1b6e627bb0452ae7a6c61f8 Mon Sep 17 00:00:00 2001
From: ssekar <suryakanth.sekar@linux.intel.com>
Date: Wed, 12 Dec 2018 16:04:15 +0530
Subject: [PATCH 1/2] Adding support for GetSessionInfo command

Description: user can get all session info (remote ip,port,
session id, priv, etc) using this command.

Verification :we can get all active and non active session
info by session handle  session id.
Updated the Remote IP addr and Port update for sessioninfo.
Unit testing are done.

Change-Id: I662ef2b9f0c1d6bda331eb6481d7b9f34534541b
Signed-off-by: ssekar <suryakanth.sekar@linux.intel.com>
---
 comm_module.cpp          |   8 +++
 command/session_cmds.cpp | 147 +++++++++++++++++++++++++++++++++++++++
 command/session_cmds.hpp |  55 +++++++++++++++
 message_handler.cpp      |   1 +
 sessions_manager.cpp     |  55 +++++++++++++++
 sessions_manager.hpp     |   7 ++
 socket_channel.hpp       |  17 +++++
 7 files changed, 290 insertions(+)

diff --git a/comm_module.cpp b/comm_module.cpp
index acc9089..7a1a17d 100644
--- a/comm_module.cpp
+++ b/comm_module.cpp
@@ -53,6 +53,14 @@ void sessionSetupCommands()
          &closeSession,
          session::Privilege::CALLBACK,
          false},
+        // Session Info Command
+        {
+            {
+                (static_cast<uint32_t>(message::PayloadType::IPMI) << 16) |
+                static_cast<uint16_t>(command::NetFns::APP) | 0x3D
+            },
+            &getSessionInfo, session::Privilege::USER, false
+        },
     };
 
     for (auto& iter : commands)
diff --git a/command/session_cmds.cpp b/command/session_cmds.cpp
index 8606ce5..4beeb6e 100644
--- a/command/session_cmds.cpp
+++ b/command/session_cmds.cpp
@@ -8,6 +8,14 @@
 namespace command
 {
 
+// Defined as per IPMI sepcification
+static constexpr uint8_t searchCurrentSession = 0x00;
+static constexpr uint8_t searchSessionByHandle = 0xFE;
+static constexpr uint8_t searchSessionByID = 0xFF;
+
+static constexpr uint8_t ipmi15VerSession = 0x00;
+static constexpr uint8_t ipmi20VerSession = 0x01;
+
 std::vector<uint8_t>
     setSessionPrivilegeLevel(const std::vector<uint8_t>& inPayload,
                              const message::Handler& handler)
@@ -92,4 +100,143 @@ std::vector<uint8_t> closeSession(const std::vector<uint8_t>& inPayload,
     return outPayload;
 }
 
+std::vector<uint8_t> getSessionInfo(const std::vector<uint8_t>& inPayload,
+                                    const message::Handler& handler)
+
+{
+    std::vector<uint8_t> outPayload(sizeof(GetSessionInfoResponse));
+    auto request =
+        reinterpret_cast<const GetSessionInfoRequest*>(inPayload.data());
+    auto response =
+        reinterpret_cast<GetSessionInfoResponse*>(outPayload.data());
+    uint32_t reqSessionID = handler.sessionID;
+    response->completionCode = IPMI_CC_OK;
+    if (inPayload.size() == 1 && request->sessionIndex != 0)
+    {
+        if (request->sessionIndex <= session::MAX_SESSION_COUNT)
+        {
+            reqSessionID = std::get<session::Manager&>(singletonPool)
+                               .getSessionIDbyHandle(request->sessionIndex);
+        }
+        else
+        {
+            response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
+            outPayload.resize(sizeof(response->completionCode));
+            return std::move(outPayload);
+        }
+    }
+
+    // Here we look for session info according to session index parameter
+    switch (request->sessionIndex)
+    {
+        // Look for current active session which this cmd is received over
+        case searchCurrentSession:
+            // Request data should only contain session index byte
+            if (inPayload.size() != 1)
+            {
+                response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
+                outPayload.resize(sizeof(response->completionCode));
+                return std::move(outPayload);
+            }
+            // To look for current active session which the command came over,
+            // the session ID cannot be 0.
+            if (0 == reqSessionID)
+            {
+                response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
+                outPayload.resize(sizeof(response->completionCode));
+                return std::move(outPayload);
+            }
+            break;
+        case searchSessionByHandle:
+            // Request data should only contain session index byte and Session
+            // handle
+            if (inPayload.size() != 2)
+            {
+                response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
+                outPayload.resize(sizeof(response->completionCode));
+                return std::move(outPayload);
+            }
+
+            // Retrieve session id based on session handle
+            if (request->sessionHandle <= session::MAX_SESSION_COUNT)
+            {
+                reqSessionID =
+                    std::get<session::Manager&>(singletonPool)
+                        .getSessionIDbyHandle(request->sessionHandle);
+            }
+            else
+            {
+                response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
+                outPayload.resize(sizeof(response->completionCode));
+                return std::move(outPayload);
+            }
+            break;
+        case searchSessionByID:
+            // Request data should only contain session index byte and Session
+            // handle
+            if (inPayload.size() != sizeof(GetSessionInfoRequest))
+            {
+                response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
+                outPayload.resize(sizeof(response->completionCode));
+                return std::move(outPayload);
+            }
+            reqSessionID = endian::from_ipmi(request->sessionID);
+
+            break;
+        default:
+            if (inPayload.size() != 1)
+            {
+                response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
+                outPayload.resize(sizeof(response->completionCode));
+                return std::move(outPayload);
+            }
+    }
+
+    response->totalSessionCount = session::MAX_SESSION_COUNT;
+    response->activeSessioncount =
+        std::get<session::Manager&>(singletonPool).getNoOfActiveSession();
+    response->sessionHandle = 0;
+    if (reqSessionID != 0)
+    {
+
+        std::shared_ptr<session::Session> sessionInfo;
+        try
+        {
+            sessionInfo = std::get<session::Manager&>(singletonPool)
+                              .getSession(reqSessionID);
+        }
+        catch (std::exception& e)
+        {
+            response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
+            outPayload.resize(sizeof(response->completionCode));
+            return std::move(outPayload);
+        }
+        response->sessionHandle = std::get<session::Manager&>(singletonPool)
+                                      .getSessionHandle(reqSessionID);
+        uint8_t userId = ipmi::ipmiUserGetUserId(sessionInfo->userName);
+        if (userId == ipmi::invalidUserId)
+        {
+            response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
+            outPayload.resize(sizeof(response->completionCode));
+            return std::move(outPayload);
+        }
+        response->userID = userId; // userId;
+        response->privLevel = static_cast<uint8_t>(sessionInfo->curPrivLevel);
+        response->chanNum = sessionInfo->chNum; // byte7 3:0
+        response->ipmiVer = ipmi20VerSession;   // byte7 7:4
+        response->remoteIpAddr =
+            sessionInfo->channelPtr->getRemoteAddressInbytes();
+        response->remotePort =
+            sessionInfo->channelPtr->getPort(); // remoteSessionPort;
+
+        std::cerr << "\nSessionInfo:" << (int)reqSessionID;
+        // TODO: Filling the Remote MACAddress
+    }
+    else
+    {
+        outPayload.resize(4);
+    }
+    return std::move(outPayload);
+}
+
 } // namespace command
diff --git a/command/session_cmds.hpp b/command/session_cmds.hpp
index 9737fdb..741de23 100644
--- a/command/session_cmds.hpp
+++ b/command/session_cmds.hpp
@@ -116,4 +116,59 @@ struct CloseSessionResponse
 std::vector<uint8_t> closeSession(const std::vector<uint8_t>& inPayload,
                                   const message::Handler& handler);
 
+/**
+ * @struct GetSessionInfoRequest
+ *
+ * IPMI Request data for getSession info command
+ */
+struct GetSessionInfoRequest
+{
+    uint8_t sessionIndex;
+    union
+    {
+        uint8_t sessionHandle;
+        uint32_t sessionID;
+    };
+} __attribute__((packed));
+
+/**
+ * @struct getSessionInfoResponse
+ *
+ * IPMI Response data for getSession info command
+ */
+struct GetSessionInfoResponse
+{
+    uint8_t completionCode;
+    uint8_t sessionHandle;
+    uint8_t totalSessionCount;
+    uint8_t activeSessioncount;
+    uint8_t userID;
+    uint8_t privLevel;
+#if BYTE_ORDER == LITTLE_ENDIAN
+    uint8_t chanNum : 4;
+    uint8_t ipmiVer : 4;
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+    uint8_t ipmiVer : 4;
+    uint8_t chanNum : 4;
+#endif
+    uint32_t remoteIpAddr; // for channel private data
+    uint8_t remoteMACAddr[6];
+    uint16_t remotePort;
+} __attribute__((packed));
+
+/**
+ * @brief GetSessionInfo Command
+ *
+ * This command is used to  get the session information based on
+ * session handle or session ID. Retreive all session information.
+
+ * @param[in] inPayload - Request Data for the command
+ * @param[in] handler - Reference to the Message Handler
+ *
+ * @return Response data for the command
+ */
+std::vector<uint8_t> getSessionInfo(const std::vector<uint8_t>& inPayload,
+                                    const message::Handler& handler);
+
 } // namespace command
diff --git a/message_handler.cpp b/message_handler.cpp
index e2aafb3..b335236 100644
--- a/message_handler.cpp
+++ b/message_handler.cpp
@@ -43,6 +43,7 @@ bool Handler::receive()
     sessionID = inMessage->bmcSessionID;
     inMessage->rcSessionID = session->getRCSessionID();
     session->updateLastTransactionTime();
+    session->channelPtr = channel;
 
     return true;
 }
diff --git a/sessions_manager.cpp b/sessions_manager.cpp
index 95a8a15..9f3210b 100644
--- a/sessions_manager.cpp
+++ b/sessions_manager.cpp
@@ -88,6 +88,9 @@ std::shared_ptr<Session>
         }
         sessionID = session->getBMCSessionID();
         sessionsMap.emplace(sessionID, session);
+        storeSessionHandle(sessionID);
+
+
         return session;
     }
 
@@ -149,12 +152,15 @@ std::shared_ptr<Session> Manager::getSession(SessionID sessionID,
 
 void Manager::cleanStaleEntries()
 {
+    uint8_t sessionIndex = 0;
     for (auto iter = sessionsMap.begin(); iter != sessionsMap.end();)
     {
         auto session = iter->second;
         if ((session->getBMCSessionID() != SESSION_ZERO) &&
             !(session->isSessionActive()))
         {
+            sessionIndex = getSessionHandle(session->getBMCSessionID());
+            sessionHandleMap[sessionIndex] = 0;
             iter = sessionsMap.erase(iter);
         }
         else
@@ -164,4 +170,53 @@ void Manager::cleanStaleEntries()
     }
 }
 
+uint8_t Manager::storeSessionHandle(SessionID bmcSessionID)
+{
+    // Zero handler is reserved for invalid session.
+    //index starts with 1, for direct usage. Index 0 reserved
+    for (uint8_t i = 1; i <= MAX_SESSION_COUNT; i++)
+    {
+        if (sessionHandleMap[i] == 0)
+        {
+            sessionHandleMap[i] = bmcSessionID;
+            break;
+        }
+    }
+    return 0;
+}
+
+uint32_t Manager::getSessionIDbyHandle(uint8_t sessionHandle) const
+{
+    if (sessionHandle <= MAX_SESSION_COUNT)
+    {
+        return sessionHandleMap[sessionHandle];
+    }
+    return 0;
+}
+
+uint8_t Manager::getSessionHandle(SessionID bmcSessionID) const
+{
+
+    for (uint8_t i = 1; i <= MAX_SESSION_COUNT; i++)
+    {
+        if (sessionHandleMap[i] == bmcSessionID)
+        {
+            return i;
+        }
+    }
+    return 0;
+}
+uint8_t Manager::getNoOfActiveSession() const
+{
+    uint8_t count = 0;
+    for (const auto& it : sessionsMap)
+    {
+        const auto& session = it.second;
+        if (session->state == State::ACTIVE)
+        {
+            count++;
+        }
+    }
+    return count;
+}
 } // namespace session
diff --git a/sessions_manager.hpp b/sessions_manager.hpp
index 9fd38b1..f6ed1c3 100644
--- a/sessions_manager.hpp
+++ b/sessions_manager.hpp
@@ -82,8 +82,15 @@ class Manager
     std::shared_ptr<Session>
         getSession(SessionID sessionID,
                    RetrieveOption option = RetrieveOption::BMC_SESSION_ID);
+    uint8_t getNoOfActiveSession() const;
+    uint8_t getSessionHandle(SessionID bmcSessionID) const;
+    uint8_t storeSessionHandle(SessionID bmcSessionID);
+    uint32_t getSessionIDbyHandle(uint8_t sessionHandle) const;
 
   private:
+    //+1 for session, as 0 is reserved for sessionless command
+    std::array<uint32_t, MAX_SESSION_COUNT + 1> sessionHandleMap;
+
     /**
      * @brief Session Manager keeps the session objects as a sorted
      *        associative container with Session ID as the unique key
diff --git a/socket_channel.hpp b/socket_channel.hpp
index ebe0c8f..349701e 100644
--- a/socket_channel.hpp
+++ b/socket_channel.hpp
@@ -64,6 +64,23 @@ class Channel
         return endpoint.port();
     }
 
+    /**
+     * @brief Return the binary representation of the remote IPv4 address
+     *
+     * getSessionInfo needs to return the remote IPv4 addresses of each session
+     *
+     * @return A uint32_t representation of the remote IPv4 address
+     */
+    std::uint32_t getRemoteAddressInbytes()
+    {
+        const boost::asio::ip::address& addr = endpoint.address();
+        if (addr.is_v4())
+        {
+            return addr.to_v4().to_uint();
+        }
+        return 0;
+    }
+
     /**
      * @brief Read the incoming packet
      *
-- 
2.17.1