blob: a4f7cbedb0f34a254ea7e0feeb877b756bb79b2b [file] [log] [blame]
Patrick Williams691668f2023-11-01 08:19:10 -05001/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
Andrew Jeffery860a43d2024-08-23 01:21:58 +00002#include "compiler.h"
Rashmica Guptac1b66f42022-12-09 16:24:45 +11003#include "container-of.h"
Andrew Jefferyb0c1d202023-11-07 22:08:44 +10304#include "mctp-defines.h"
Rashmica Gupta04273e92023-06-16 16:03:37 +10005#include "socket.h"
Rashmica Guptac1b66f42022-12-09 16:24:45 +11006#include "transport.h"
7
Andrew Jefferyb0c1d202023-11-07 22:08:44 +10308#include <libpldm/base.h>
9#include <libpldm/pldm.h>
10#include <libpldm/transport.h>
11#include <libpldm/transport/mctp-demux.h>
12
Rashmica Guptac1b66f42022-12-09 16:24:45 +110013#include <errno.h>
Rashmica Gupta04273e92023-06-16 16:03:37 +100014#include <limits.h>
Rashmica Guptac1b66f42022-12-09 16:24:45 +110015#include <poll.h>
16#include <stdlib.h>
17#include <string.h>
18#include <sys/socket.h>
19#include <sys/types.h>
20#include <sys/un.h>
21#include <unistd.h>
22
23#define MCTP_DEMUX_NAME "libmctp-demux-daemon"
24const uint8_t mctp_msg_type = MCTP_MSG_TYPE_PLDM;
25
26struct pldm_transport_mctp_demux {
27 struct pldm_transport transport;
28 int socket;
29 /* In the future this probably needs to move to a tid-eid-uuid/network
30 * id mapping for multi mctp networks */
31 pldm_tid_t tid_eid_map[MCTP_MAX_NUM_EID];
Rashmica Gupta04273e92023-06-16 16:03:37 +100032 struct pldm_socket_sndbuf socket_send_buf;
Rashmica Guptac1b66f42022-12-09 16:24:45 +110033};
34
35#define transport_to_demux(ptr) \
36 container_of(ptr, struct pldm_transport_mctp_demux, transport)
37
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093038LIBPLDM_ABI_STABLE
Rashmica Guptac1b66f42022-12-09 16:24:45 +110039struct pldm_transport *
40pldm_transport_mctp_demux_core(struct pldm_transport_mctp_demux *ctx)
41{
42 return &ctx->transport;
43}
44
45static pldm_requester_rc_t pldm_transport_mctp_demux_open(void)
46{
47 int fd = -1;
48 ssize_t rc = -1;
49
50 fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
51 if (fd == -1) {
52 return fd;
53 }
54
55 const char path[] = "\0mctp-mux";
56 struct sockaddr_un addr;
57 addr.sun_family = AF_UNIX;
58 memcpy(addr.sun_path, path, sizeof(path) - 1);
59 rc = connect(fd, (struct sockaddr *)&addr,
60 sizeof(path) + sizeof(addr.sun_family) - 1);
61 if (rc == -1) {
62 return PLDM_REQUESTER_OPEN_FAIL;
63 }
64 rc = write(fd, &mctp_msg_type, sizeof(mctp_msg_type));
65 if (rc == -1) {
66 return PLDM_REQUESTER_OPEN_FAIL;
67 }
68
69 return fd;
70}
71
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093072LIBPLDM_ABI_STABLE
Rashmica Guptac1b66f42022-12-09 16:24:45 +110073int pldm_transport_mctp_demux_init_pollfd(struct pldm_transport *t,
74 struct pollfd *pollfd)
75{
76 struct pldm_transport_mctp_demux *ctx = transport_to_demux(t);
77 pollfd->fd = ctx->socket;
78 pollfd->events = POLLIN;
79 return 0;
80}
81
82static int
83pldm_transport_mctp_demux_get_eid(struct pldm_transport_mctp_demux *ctx,
84 pldm_tid_t tid, mctp_eid_t *eid)
85{
86 int i;
87 for (i = 0; i < MCTP_MAX_NUM_EID; i++) {
88 if (ctx->tid_eid_map[i] == tid) {
89 *eid = i;
90 return 0;
91 }
92 }
93 *eid = -1;
94 return -1;
95}
96
Rashmica Gupta24576292023-07-31 14:02:41 +100097static int
98pldm_transport_mctp_demux_get_tid(struct pldm_transport_mctp_demux *ctx,
99 mctp_eid_t eid, pldm_tid_t *tid)
100{
101 /* mapping exists */
102 if (ctx->tid_eid_map[eid] != 0) {
103 *tid = ctx->tid_eid_map[eid];
104 return 0;
105 }
106 return -1;
107}
108
Andrew Jeffery0a6d6822023-08-22 21:40:32 +0930109LIBPLDM_ABI_STABLE
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100110int pldm_transport_mctp_demux_map_tid(struct pldm_transport_mctp_demux *ctx,
111 pldm_tid_t tid, mctp_eid_t eid)
112{
113 ctx->tid_eid_map[eid] = tid;
114
115 return 0;
116}
117
Andrew Jeffery0a6d6822023-08-22 21:40:32 +0930118LIBPLDM_ABI_STABLE
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100119int pldm_transport_mctp_demux_unmap_tid(struct pldm_transport_mctp_demux *ctx,
Andrew Jeffery860a43d2024-08-23 01:21:58 +0000120 LIBPLDM_CC_UNUSED pldm_tid_t tid,
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100121 mctp_eid_t eid)
122{
123 ctx->tid_eid_map[eid] = 0;
124
125 return 0;
126}
127
128static pldm_requester_rc_t
Rashmica Gupta24576292023-07-31 14:02:41 +1000129pldm_transport_mctp_demux_recv(struct pldm_transport *t, pldm_tid_t *tid,
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000130 void **pldm_msg, size_t *msg_len)
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100131{
132 struct pldm_transport_mctp_demux *demux = transport_to_demux(t);
Andrew Jefferyef293fc2023-08-18 12:14:23 +0930133 size_t mctp_prefix_len = 2;
134 struct msghdr msg = { 0 };
Andrew Jeffery27f041c2023-08-18 12:19:15 +0930135 pldm_requester_rc_t res;
Andrew Jefferyef293fc2023-08-18 12:14:23 +0930136 uint8_t mctp_prefix[2];
137 struct iovec iov[2];
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100138 mctp_eid_t eid = 0;
Andrew Jefferyef293fc2023-08-18 12:14:23 +0930139 ssize_t min_len;
140 size_t pldm_len;
141 ssize_t length;
142 ssize_t bytes;
143 uint8_t *buf;
144 int rc;
145
Andrew Jefferyef293fc2023-08-18 12:14:23 +0930146 min_len = sizeof(eid) + sizeof(mctp_msg_type) +
147 sizeof(struct pldm_msg_hdr);
148 length = recv(demux->socket, NULL, 0, MSG_PEEK | MSG_TRUNC);
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100149 if (length <= 0) {
150 return PLDM_REQUESTER_RECV_FAIL;
151 }
Andrew Jefferyef293fc2023-08-18 12:14:23 +0930152
153 buf = malloc(length);
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100154 if (buf == NULL) {
155 return PLDM_REQUESTER_RECV_FAIL;
156 }
Andrew Jefferyef293fc2023-08-18 12:14:23 +0930157
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100158 if (length < min_len) {
159 /* read and discard */
160 recv(demux->socket, buf, length, 0);
Andrew Jeffery27f041c2023-08-18 12:19:15 +0930161 res = PLDM_REQUESTER_INVALID_RECV_LEN;
162 goto cleanup_buf;
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100163 }
Andrew Jefferyef293fc2023-08-18 12:14:23 +0930164
165 pldm_len = length - mctp_prefix_len;
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100166 iov[0].iov_len = mctp_prefix_len;
167 iov[0].iov_base = mctp_prefix;
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100168 iov[1].iov_len = pldm_len;
Andrew Jefferya8532b52023-06-05 11:58:55 +0930169 iov[1].iov_base = buf;
Andrew Jefferyef293fc2023-08-18 12:14:23 +0930170
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100171 msg.msg_iov = iov;
172 msg.msg_iovlen = sizeof(iov) / sizeof(iov[0]);
Andrew Jefferyef293fc2023-08-18 12:14:23 +0930173
174 bytes = recvmsg(demux->socket, &msg, 0);
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100175 if (length != bytes) {
Andrew Jeffery27f041c2023-08-18 12:19:15 +0930176 res = PLDM_REQUESTER_INVALID_RECV_LEN;
177 goto cleanup_buf;
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100178 }
Andrew Jefferyef293fc2023-08-18 12:14:23 +0930179
Rashmica Gupta24576292023-07-31 14:02:41 +1000180 if (mctp_prefix[1] != mctp_msg_type) {
Andrew Jeffery27f041c2023-08-18 12:19:15 +0930181 res = PLDM_REQUESTER_NOT_PLDM_MSG;
182 goto cleanup_buf;
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100183 }
Andrew Jefferyef293fc2023-08-18 12:14:23 +0930184
Rashmica Gupta24576292023-07-31 14:02:41 +1000185 eid = mctp_prefix[0];
186 rc = pldm_transport_mctp_demux_get_tid(demux, eid, tid);
187 if (rc) {
188 res = PLDM_REQUESTER_RECV_FAIL;
189 goto cleanup_buf;
190 }
191
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000192 *pldm_msg = buf;
193 *msg_len = pldm_len;
Andrew Jefferyef293fc2023-08-18 12:14:23 +0930194
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100195 return PLDM_REQUESTER_SUCCESS;
Andrew Jeffery27f041c2023-08-18 12:19:15 +0930196
197cleanup_buf:
198 free(buf);
199
200 return res;
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100201}
202
203static pldm_requester_rc_t
204pldm_transport_mctp_demux_send(struct pldm_transport *t, pldm_tid_t tid,
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000205 const void *pldm_msg, size_t msg_len)
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100206{
207 struct pldm_transport_mctp_demux *demux = transport_to_demux(t);
208 mctp_eid_t eid = 0;
209 if (pldm_transport_mctp_demux_get_eid(demux, tid, &eid)) {
210 return PLDM_REQUESTER_SEND_FAIL;
211 }
212
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930213 uint8_t hdr[2] = { eid, mctp_msg_type };
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100214
215 struct iovec iov[2];
216 iov[0].iov_base = hdr;
217 iov[0].iov_len = sizeof(hdr);
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000218 iov[1].iov_base = (uint8_t *)pldm_msg;
219 iov[1].iov_len = msg_len;
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100220
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930221 struct msghdr msg = { 0 };
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100222 msg.msg_iov = iov;
223 msg.msg_iovlen = sizeof(iov) / sizeof(iov[0]);
224
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000225 if (msg_len > INT_MAX ||
Rashmica Gupta04273e92023-06-16 16:03:37 +1000226 pldm_socket_sndbuf_accomodate(&(demux->socket_send_buf),
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000227 (int)msg_len)) {
Rashmica Gupta04273e92023-06-16 16:03:37 +1000228 return PLDM_REQUESTER_SEND_FAIL;
229 }
230
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100231 ssize_t rc = sendmsg(demux->socket, &msg, 0);
232 if (rc == -1) {
233 return PLDM_REQUESTER_SEND_FAIL;
234 }
235 return PLDM_REQUESTER_SUCCESS;
236}
237
Andrew Jeffery0a6d6822023-08-22 21:40:32 +0930238LIBPLDM_ABI_STABLE
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100239int pldm_transport_mctp_demux_init(struct pldm_transport_mctp_demux **ctx)
240{
241 if (!ctx || *ctx) {
242 return -EINVAL;
243 }
244
245 struct pldm_transport_mctp_demux *demux =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930246 calloc(1, sizeof(struct pldm_transport_mctp_demux));
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100247 if (!demux) {
248 return -ENOMEM;
249 }
250
251 demux->transport.name = MCTP_DEMUX_NAME;
252 demux->transport.version = 1;
253 demux->transport.recv = pldm_transport_mctp_demux_recv;
254 demux->transport.send = pldm_transport_mctp_demux_send;
255 demux->transport.init_pollfd = pldm_transport_mctp_demux_init_pollfd;
256 demux->socket = pldm_transport_mctp_demux_open();
257 if (demux->socket == -1) {
258 free(demux);
259 return -1;
260 }
Rashmica Gupta04273e92023-06-16 16:03:37 +1000261
262 if (pldm_socket_sndbuf_init(&demux->socket_send_buf, demux->socket)) {
263 close(demux->socket);
264 free(demux);
265 return -1;
266 }
267
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100268 *ctx = demux;
269 return 0;
270}
271
Andrew Jeffery0a6d6822023-08-22 21:40:32 +0930272LIBPLDM_ABI_STABLE
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100273void pldm_transport_mctp_demux_destroy(struct pldm_transport_mctp_demux *ctx)
274{
275 if (!ctx) {
276 return;
277 }
278 close(ctx->socket);
279 free(ctx);
280}
281
282/* Temporary for old API */
283struct pldm_transport_mctp_demux *
284pldm_transport_mctp_demux_init_with_fd(int mctp_fd)
285{
286 struct pldm_transport_mctp_demux *demux =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930287 calloc(1, sizeof(struct pldm_transport_mctp_demux));
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100288 if (!demux) {
289 return NULL;
290 }
291
292 demux->transport.name = MCTP_DEMUX_NAME;
293 demux->transport.version = 1;
294 demux->transport.recv = pldm_transport_mctp_demux_recv;
295 demux->transport.send = pldm_transport_mctp_demux_send;
296 demux->transport.init_pollfd = pldm_transport_mctp_demux_init_pollfd;
297 /* dup is so we can call pldm_transport_mctp_demux_destroy which closes
298 * the socket, without closing the fd that is being used by the consumer
299 */
300 demux->socket = dup(mctp_fd);
301 if (demux->socket == -1) {
302 free(demux);
303 return NULL;
304 }
Rashmica Gupta04273e92023-06-16 16:03:37 +1000305
306 if (pldm_socket_sndbuf_init(&demux->socket_send_buf, demux->socket)) {
307 close(demux->socket);
308 free(demux);
309 return NULL;
310 }
311
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100312 return demux;
313}
314
315int pldm_transport_mctp_demux_get_socket_fd(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930316 struct pldm_transport_mctp_demux *ctx)
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100317{
Andrew Jefferya4da6852023-06-29 10:47:24 +0930318 if (ctx) {
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100319 return ctx->socket;
320 }
Andrew Jefferya4da6852023-06-29 10:47:24 +0930321
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100322 return -1;
323}