blob: e02bb57dd7fed3bbf9c09adf0725c4c6514eaaa7 [file] [log] [blame]
Jinu Joy Thomasf666db12019-05-29 05:22:31 -05001#include "libpldmresponder/base.hpp"
2#include "libpldmresponder/bios.hpp"
3#include "libpldmresponder/utils.hpp"
4#include "registration.hpp"
5
6#include <err.h>
7#include <poll.h>
8#include <stdlib.h>
9#include <sys/socket.h>
10#include <sys/types.h>
11#include <sys/un.h>
12#include <unistd.h>
13
14#include <cstdio>
15#include <cstring>
16#include <iomanip>
17#include <iterator>
18#include <phosphor-logging/log.hpp>
19#include <sstream>
20#include <vector>
21
22#include "libpldm/base.h"
23#include "libpldm/bios.h"
24
25#ifdef OEM_IBM
26#include "libpldmresponder/file_io.hpp"
27#endif
28
29constexpr uint8_t MCTP_MSG_TYPE_PLDM = 1;
30
31using namespace phosphor::logging;
32using namespace pldm;
33
34static Response processRxMsg(const std::vector<uint8_t>& requestMsg)
35{
36
37 Response response;
38 uint8_t eid = requestMsg[0];
39 uint8_t type = requestMsg[1];
40 pldm_header_info hdrFields{};
41 auto hdr = reinterpret_cast<const pldm_msg_hdr*>(
42 requestMsg.data() + sizeof(eid) + sizeof(type));
43 if (PLDM_SUCCESS != unpack_pldm_header(hdr, &hdrFields))
44 {
45 log<level::ERR>("Empty PLDM request header");
46 }
47 else if (PLDM_RESPONSE != hdrFields.msg_type)
48 {
49 auto request = reinterpret_cast<const pldm_msg*>(hdr);
50 size_t requestLen = requestMsg.size() - sizeof(struct pldm_msg_hdr) -
51 sizeof(eid) - sizeof(type);
52 response = pldm::responder::invokeHandler(
53 hdrFields.pldm_type, hdrFields.command, request, requestLen);
54 if (response.empty())
55 {
56 uint8_t completion_code = PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
57 response.resize(sizeof(pldm_msg_hdr));
58 auto responseHdr = reinterpret_cast<pldm_msg_hdr*>(response.data());
59 pldm_header_info header{};
60 header.msg_type = PLDM_RESPONSE;
61 header.instance = hdrFields.instance;
62 header.pldm_type = hdrFields.pldm_type;
63 header.command = hdrFields.command;
64 auto result = pack_pldm_header(&header, responseHdr);
65 if (PLDM_SUCCESS != result)
66 {
67 log<level::ERR>("Failed adding response header");
68 }
69 response.insert(response.end(), completion_code);
70 }
71 response.insert(response.begin(), type);
72 response.insert(response.begin(), eid);
73 }
74 return response;
75}
76
77void printBuffer(const std::vector<uint8_t>& buffer)
78{
79 std::ostringstream tempStream;
80 tempStream << "Buffer Data: ";
81 if (!buffer.empty())
82 {
83 for (int byte : buffer)
84 {
85 tempStream << std::setfill('0') << std::setw(2) << std::hex << byte
86 << " ";
87 }
88 }
89 log<level::INFO>(tempStream.str().c_str());
90}
91
92int main(int argc, char** argv)
93{
94
95 pldm::responder::base::registerHandlers();
96 pldm::responder::bios::registerHandlers();
97
98#ifdef OEM_IBM
99 pldm::responder::oem_ibm::registerHandlers();
100#endif
101
102 /* Create local socket. */
103 int returnCode = 0;
104 int sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
105 if (-1 == sockfd)
106 {
107 returnCode = -errno;
108 log<level::ERR>("Failed to create the socket",
109 entry("RC=%d", returnCode));
110 exit(EXIT_FAILURE);
111 }
112
113 responder::utils::CustomFD socketFd(sockfd);
114
115 struct sockaddr_un addr
116 {
117 };
118 addr.sun_family = AF_UNIX;
119 const char path[] = "\0mctp-mux";
120 memcpy(addr.sun_path, path, sizeof(path) - 1);
121 int result = connect(socketFd(), reinterpret_cast<struct sockaddr*>(&addr),
122 sizeof(path) + sizeof(addr.sun_family) - 1);
123 if (-1 == result)
124 {
125 returnCode = -errno;
126 log<level::ERR>("Failed to connect to the socket",
127 entry("RC=%d", returnCode));
128 exit(EXIT_FAILURE);
129 }
130
131 result = write(socketFd(), &MCTP_MSG_TYPE_PLDM, sizeof(MCTP_MSG_TYPE_PLDM));
132 if (-1 == result)
133 {
134 returnCode = -errno;
135 log<level::ERR>("Failed to send message type as pldm to mctp",
136 entry("RC=%d", returnCode));
137 exit(EXIT_FAILURE);
138 }
139
140 do
141 {
142 ssize_t peekedLength =
143 recv(socketFd(), nullptr, 0, MSG_PEEK | MSG_TRUNC);
144 if (0 == peekedLength)
145 {
146 log<level::ERR>("Socket has been closed");
147 exit(EXIT_FAILURE);
148 }
149 else if (peekedLength <= -1)
150 {
151 returnCode = -errno;
152 log<level::ERR>("recv system call failed",
153 entry("RC=%d", returnCode));
154 exit(EXIT_FAILURE);
155 }
156 else
157 {
158 std::vector<uint8_t> requestMsg(peekedLength);
159 auto recvDataLength = recv(
160 sockfd, static_cast<void*>(requestMsg.data()), peekedLength, 0);
161 if (recvDataLength == peekedLength)
162 {
163#ifdef VERBOSE
164 log<level::INFO>("Received Msg ",
165 entry("LENGTH=%zu", recvDataLength),
166 entry("EID=0x%02x", requestMsg[0]),
167 entry("TYPE=0x%02x", requestMsg[1]));
168 printBuffer(requestMsg);
169#endif
170 if (MCTP_MSG_TYPE_PLDM != requestMsg[1])
171 {
172 // Skip this message and continue.
173 log<level::ERR>("Encountered Non-PLDM type message",
174 entry("TYPE=0x%02x", requestMsg[1]));
175 }
176 else
177 {
178 // process message and send response
179 auto response = processRxMsg(requestMsg);
180 if (!response.empty())
181 {
182#ifdef VERBOSE
183 log<level::INFO>("Sending Msg ");
184 printBuffer(response);
185#endif
186 result = sendto(socketFd(), response.data(),
187 response.size(), 0, nullptr, 0);
188 if (-1 == result)
189 {
190 returnCode = -errno;
191 log<level::ERR>("sendto system call failed",
192 entry("RC=%d", returnCode));
193 exit(EXIT_FAILURE);
194 }
195 }
196 }
197 }
198 else
199 {
200 log<level::ERR>("Failure to read peeked length packet",
201 entry("PEEKED_LENGTH=%zu", peekedLength),
202 entry("READ_LENGTH=%zu", recvDataLength));
203 exit(EXIT_FAILURE);
204 }
205 }
206 } while (true);
207
208 result = shutdown(sockfd, SHUT_RDWR);
209 if (-1 == result)
210 {
211 returnCode = -errno;
212 log<level::ERR>("Failed to shutdown the socket",
213 entry("RC=%d", returnCode));
214 exit(EXIT_FAILURE);
215 }
216 exit(EXIT_FAILURE);
217}