blob: eed1292957b72ba704e665b18f4db630f6f6edb1 [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 }
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050071 }
72 return response;
73}
74
75void printBuffer(const std::vector<uint8_t>& buffer)
76{
77 std::ostringstream tempStream;
78 tempStream << "Buffer Data: ";
79 if (!buffer.empty())
80 {
81 for (int byte : buffer)
82 {
83 tempStream << std::setfill('0') << std::setw(2) << std::hex << byte
84 << " ";
85 }
86 }
87 log<level::INFO>(tempStream.str().c_str());
88}
89
90int main(int argc, char** argv)
91{
92
93 pldm::responder::base::registerHandlers();
94 pldm::responder::bios::registerHandlers();
95
Zahed Hossainad30c542019-07-17 10:52:13 -050096 // Outgoing message.
97 struct iovec iov[2]{};
98
99 // This structure contains the parameter information for the response
100 // message.
101 struct msghdr msg
102 {
103 };
104
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500105#ifdef OEM_IBM
106 pldm::responder::oem_ibm::registerHandlers();
107#endif
108
109 /* Create local socket. */
110 int returnCode = 0;
111 int sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
112 if (-1 == sockfd)
113 {
114 returnCode = -errno;
115 log<level::ERR>("Failed to create the socket",
116 entry("RC=%d", returnCode));
117 exit(EXIT_FAILURE);
118 }
119
120 responder::utils::CustomFD socketFd(sockfd);
121
122 struct sockaddr_un addr
123 {
124 };
125 addr.sun_family = AF_UNIX;
126 const char path[] = "\0mctp-mux";
127 memcpy(addr.sun_path, path, sizeof(path) - 1);
128 int result = connect(socketFd(), reinterpret_cast<struct sockaddr*>(&addr),
129 sizeof(path) + sizeof(addr.sun_family) - 1);
130 if (-1 == result)
131 {
132 returnCode = -errno;
133 log<level::ERR>("Failed to connect to the socket",
134 entry("RC=%d", returnCode));
135 exit(EXIT_FAILURE);
136 }
137
138 result = write(socketFd(), &MCTP_MSG_TYPE_PLDM, sizeof(MCTP_MSG_TYPE_PLDM));
139 if (-1 == result)
140 {
141 returnCode = -errno;
142 log<level::ERR>("Failed to send message type as pldm to mctp",
143 entry("RC=%d", returnCode));
144 exit(EXIT_FAILURE);
145 }
146
147 do
148 {
149 ssize_t peekedLength =
150 recv(socketFd(), nullptr, 0, MSG_PEEK | MSG_TRUNC);
151 if (0 == peekedLength)
152 {
153 log<level::ERR>("Socket has been closed");
154 exit(EXIT_FAILURE);
155 }
156 else if (peekedLength <= -1)
157 {
158 returnCode = -errno;
159 log<level::ERR>("recv system call failed",
160 entry("RC=%d", returnCode));
161 exit(EXIT_FAILURE);
162 }
163 else
164 {
165 std::vector<uint8_t> requestMsg(peekedLength);
166 auto recvDataLength = recv(
167 sockfd, static_cast<void*>(requestMsg.data()), peekedLength, 0);
168 if (recvDataLength == peekedLength)
169 {
170#ifdef VERBOSE
171 log<level::INFO>("Received Msg ",
172 entry("LENGTH=%zu", recvDataLength),
173 entry("EID=0x%02x", requestMsg[0]),
174 entry("TYPE=0x%02x", requestMsg[1]));
175 printBuffer(requestMsg);
176#endif
177 if (MCTP_MSG_TYPE_PLDM != requestMsg[1])
178 {
179 // Skip this message and continue.
180 log<level::ERR>("Encountered Non-PLDM type message",
181 entry("TYPE=0x%02x", requestMsg[1]));
182 }
183 else
184 {
185 // process message and send response
186 auto response = processRxMsg(requestMsg);
187 if (!response.empty())
188 {
189#ifdef VERBOSE
190 log<level::INFO>("Sending Msg ");
191 printBuffer(response);
192#endif
Zahed Hossainad30c542019-07-17 10:52:13 -0500193 iov[0].iov_base = &requestMsg;
194 iov[0].iov_len =
195 sizeof(requestMsg[0]) + sizeof(requestMsg[1]);
196 iov[1].iov_base = response.data();
197 iov[1].iov_len = response.size();
198
199 msg.msg_iov = iov;
200 msg.msg_iovlen = sizeof(iov) / sizeof(iov[0]);
201
202 result = sendmsg(socketFd(), &msg, 0);
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500203 if (-1 == result)
204 {
205 returnCode = -errno;
206 log<level::ERR>("sendto system call failed",
207 entry("RC=%d", returnCode));
208 exit(EXIT_FAILURE);
209 }
210 }
211 }
212 }
213 else
214 {
215 log<level::ERR>("Failure to read peeked length packet",
216 entry("PEEKED_LENGTH=%zu", peekedLength),
217 entry("READ_LENGTH=%zu", recvDataLength));
218 exit(EXIT_FAILURE);
219 }
220 }
221 } while (true);
222
223 result = shutdown(sockfd, SHUT_RDWR);
224 if (-1 == result)
225 {
226 returnCode = -errno;
227 log<level::ERR>("Failed to shutdown the socket",
228 entry("RC=%d", returnCode));
229 exit(EXIT_FAILURE);
230 }
231 exit(EXIT_FAILURE);
232}