blob: a66e79d01442b1b2b8b2a35672e05c058e860080 [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 Guptaba6971b2022-12-09 16:27:38 +11003#include "container-of.h"
Andrew Jefferyb0c1d202023-11-07 22:08:44 +10304#include "mctp-defines.h"
Andrew Jefferycc45aed2023-09-10 23:03:29 +09305#include "responder.h"
Rashmica Gupta04273e92023-06-16 16:03:37 +10006#include "socket.h"
Rashmica Guptaba6971b2022-12-09 16:27:38 +11007#include "transport.h"
8
Andrew Jefferyb0c1d202023-11-07 22:08:44 +10309#include <libpldm/base.h>
10#include <libpldm/pldm.h>
11#include <libpldm/transport.h>
12#include <libpldm/transport/af-mctp.h>
13
Rashmica Guptaba6971b2022-12-09 16:27:38 +110014#include <errno.h>
Rashmica Gupta04273e92023-06-16 16:03:37 +100015#include <limits.h>
Rashmica Guptaba6971b2022-12-09 16:27:38 +110016#include <linux/mctp.h>
17#include <poll.h>
Andrew Jefferycc45aed2023-09-10 23:03:29 +093018#include <stdbool.h>
Rashmica Guptaba6971b2022-12-09 16:27:38 +110019#include <stdlib.h>
20#include <string.h>
21#include <sys/socket.h>
22#include <sys/types.h>
23#include <sys/un.h>
24#include <unistd.h>
25
Andrew Jefferycc45aed2023-09-10 23:03:29 +093026struct pldm_responder_cookie_af_mctp {
27 struct pldm_responder_cookie req;
28 struct sockaddr_mctp smctp;
29};
30
31#define cookie_to_af_mctp(c) \
32 container_of((c), struct pldm_responder_cookie_af_mctp, req)
33
Rashmica Guptaba6971b2022-12-09 16:27:38 +110034#define AF_MCTP_NAME "AF_MCTP"
35struct pldm_transport_af_mctp {
36 struct pldm_transport transport;
37 int socket;
38 pldm_tid_t tid_eid_map[MCTP_MAX_NUM_EID];
Rashmica Gupta04273e92023-06-16 16:03:37 +100039 struct pldm_socket_sndbuf socket_send_buf;
Andrew Jefferycc45aed2023-09-10 23:03:29 +093040 bool bound;
41 struct pldm_responder_cookie cookie_jar;
Rashmica Guptaba6971b2022-12-09 16:27:38 +110042};
43
44#define transport_to_af_mctp(ptr) \
45 container_of(ptr, struct pldm_transport_af_mctp, transport)
46
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093047LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110048struct pldm_transport *
49pldm_transport_af_mctp_core(struct pldm_transport_af_mctp *ctx)
50{
51 return &ctx->transport;
52}
53
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093054LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110055int pldm_transport_af_mctp_init_pollfd(struct pldm_transport *t,
56 struct pollfd *pollfd)
57{
58 struct pldm_transport_af_mctp *ctx = transport_to_af_mctp(t);
59 pollfd->fd = ctx->socket;
60 pollfd->events = POLLIN;
61 return 0;
62}
63
64static int pldm_transport_af_mctp_get_eid(struct pldm_transport_af_mctp *ctx,
65 pldm_tid_t tid, mctp_eid_t *eid)
66{
67 int i;
68 for (i = 0; i < MCTP_MAX_NUM_EID; i++) {
69 if (ctx->tid_eid_map[i] == tid) {
70 *eid = i;
71 return 0;
72 }
73 }
74 *eid = -1;
75 return -1;
76}
77
Rashmica Gupta24576292023-07-31 14:02:41 +100078static int pldm_transport_af_mctp_get_tid(struct pldm_transport_af_mctp *ctx,
79 mctp_eid_t eid, pldm_tid_t *tid)
80{
81 if (ctx->tid_eid_map[eid] != 0) {
82 *tid = ctx->tid_eid_map[eid];
83 return 0;
84 }
85 return -1;
86}
87
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093088LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110089int pldm_transport_af_mctp_map_tid(struct pldm_transport_af_mctp *ctx,
90 pldm_tid_t tid, mctp_eid_t eid)
91{
92 ctx->tid_eid_map[eid] = tid;
93
94 return 0;
95}
96
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093097LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110098int pldm_transport_af_mctp_unmap_tid(struct pldm_transport_af_mctp *ctx,
Andrew Jeffery860a43d2024-08-23 01:21:58 +000099 LIBPLDM_CC_UNUSED pldm_tid_t tid,
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100100 mctp_eid_t eid)
101{
102 ctx->tid_eid_map[eid] = 0;
103
104 return 0;
105}
106
107static pldm_requester_rc_t pldm_transport_af_mctp_recv(struct pldm_transport *t,
Rashmica Gupta24576292023-07-31 14:02:41 +1000108 pldm_tid_t *tid,
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000109 void **pldm_msg,
110 size_t *msg_len)
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100111{
112 struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t);
Rashmica Gupta24576292023-07-31 14:02:41 +1000113 struct sockaddr_mctp addr = { 0 };
114 socklen_t addrlen = sizeof(addr);
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930115 struct pldm_msg_hdr *hdr;
Rashmica Gupta24576292023-07-31 14:02:41 +1000116 pldm_requester_rc_t res;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100117 mctp_eid_t eid = 0;
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930118 ssize_t length;
Andrew Jefferyac247372023-08-18 10:46:12 +0930119 void *msg;
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930120 int rc;
121
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930122 length = recv(af_mctp->socket, NULL, 0, MSG_PEEK | MSG_TRUNC);
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100123 if (length <= 0) {
124 return PLDM_REQUESTER_RECV_FAIL;
125 }
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930126
Andrew Jefferyac247372023-08-18 10:46:12 +0930127 msg = malloc(length);
Andrew Jeffery7caa8af2023-08-18 10:50:54 +0930128 if (!msg) {
129 return PLDM_REQUESTER_RECV_FAIL;
130 }
131
Rashmica Gupta24576292023-07-31 14:02:41 +1000132 length = recvfrom(af_mctp->socket, msg, length, MSG_TRUNC,
133 (struct sockaddr *)&addr, &addrlen);
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100134 if (length < (ssize_t)sizeof(struct pldm_msg_hdr)) {
Rashmica Gupta24576292023-07-31 14:02:41 +1000135 res = PLDM_REQUESTER_INVALID_RECV_LEN;
136 goto cleanup_msg;
137 }
138
139 eid = addr.smctp_addr.s_addr;
140 rc = pldm_transport_af_mctp_get_tid(af_mctp, eid, tid);
141 if (rc) {
142 res = PLDM_REQUESTER_RECV_FAIL;
143 goto cleanup_msg;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100144 }
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930145
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930146 hdr = msg;
147
148 if (af_mctp->bound && hdr->request) {
149 struct pldm_responder_cookie_af_mctp *cookie;
150
151 cookie = malloc(sizeof(*cookie));
152 if (!cookie) {
153 res = PLDM_REQUESTER_RECV_FAIL;
154 goto cleanup_msg;
155 }
156
157 cookie->req.tid = *tid,
158 cookie->req.instance_id = hdr->instance_id,
159 cookie->req.type = hdr->type,
160 cookie->req.command = hdr->command;
161 cookie->smctp = addr;
162
163 rc = pldm_responder_cookie_track(&af_mctp->cookie_jar,
164 &cookie->req);
165 if (rc) {
166 res = PLDM_REQUESTER_RECV_FAIL;
167 goto cleanup_msg;
168 }
169 }
170
Andrew Jefferyac247372023-08-18 10:46:12 +0930171 *pldm_msg = msg;
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000172 *msg_len = length;
173
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100174 return PLDM_REQUESTER_SUCCESS;
Rashmica Gupta24576292023-07-31 14:02:41 +1000175
176cleanup_msg:
177 free(msg);
178
179 return res;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100180}
181
182static pldm_requester_rc_t pldm_transport_af_mctp_send(struct pldm_transport *t,
183 pldm_tid_t tid,
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000184 const void *pldm_msg,
185 size_t msg_len)
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100186{
187 struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t);
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930188 const struct pldm_msg_hdr *hdr;
189 struct sockaddr_mctp addr = { 0 };
190
191 if (msg_len < (ssize_t)sizeof(struct pldm_msg_hdr)) {
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100192 return PLDM_REQUESTER_SEND_FAIL;
193 }
194
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930195 hdr = pldm_msg;
196 if (af_mctp->bound && !hdr->request) {
197 struct pldm_responder_cookie_af_mctp *cookie;
198 struct pldm_responder_cookie *req;
199
200 req = pldm_responder_cookie_untrack(&af_mctp->cookie_jar, tid,
201 hdr->instance_id, hdr->type,
202 hdr->command);
203 if (!req) {
204 return PLDM_REQUESTER_SEND_FAIL;
205 }
206
207 cookie = cookie_to_af_mctp(req);
208 addr = cookie->smctp;
209 /* Clear the TO to indicate a response */
210 addr.smctp_tag &= ~MCTP_TAG_OWNER;
211 free(cookie);
212 } else {
213 mctp_eid_t eid = 0;
214 if (pldm_transport_af_mctp_get_eid(af_mctp, tid, &eid)) {
215 return PLDM_REQUESTER_SEND_FAIL;
216 }
217
218 addr.smctp_family = AF_MCTP;
219 addr.smctp_addr.s_addr = eid;
220 addr.smctp_type = MCTP_MSG_TYPE_PLDM;
221 addr.smctp_tag = MCTP_TAG_OWNER;
222 }
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100223
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000224 if (msg_len > INT_MAX ||
Rashmica Gupta04273e92023-06-16 16:03:37 +1000225 pldm_socket_sndbuf_accomodate(&(af_mctp->socket_send_buf),
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000226 (int)msg_len)) {
Rashmica Gupta04273e92023-06-16 16:03:37 +1000227 return PLDM_REQUESTER_SEND_FAIL;
228 }
229
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000230 ssize_t rc = sendto(af_mctp->socket, pldm_msg, msg_len, 0,
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100231 (struct sockaddr *)&addr, sizeof(addr));
232 if (rc == -1) {
233 return PLDM_REQUESTER_SEND_FAIL;
234 }
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930235
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100236 return PLDM_REQUESTER_SUCCESS;
237}
238
Andrew Jeffery0a6d6822023-08-22 21:40:32 +0930239LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100240int pldm_transport_af_mctp_init(struct pldm_transport_af_mctp **ctx)
241{
242 if (!ctx || *ctx) {
243 return -EINVAL;
244 }
245
246 struct pldm_transport_af_mctp *af_mctp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930247 calloc(1, sizeof(struct pldm_transport_af_mctp));
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100248 if (!af_mctp) {
249 return -ENOMEM;
250 }
251
252 af_mctp->transport.name = AF_MCTP_NAME;
253 af_mctp->transport.version = 1;
254 af_mctp->transport.recv = pldm_transport_af_mctp_recv;
255 af_mctp->transport.send = pldm_transport_af_mctp_send;
Delphine CC Chiub4cd5172023-08-15 11:30:44 +0800256 af_mctp->transport.init_pollfd = pldm_transport_af_mctp_init_pollfd;
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930257 af_mctp->bound = false;
258 af_mctp->cookie_jar.next = NULL;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100259 af_mctp->socket = socket(AF_MCTP, SOCK_DGRAM, 0);
260 if (af_mctp->socket == -1) {
261 free(af_mctp);
262 return -1;
263 }
Rashmica Gupta04273e92023-06-16 16:03:37 +1000264
265 if (pldm_socket_sndbuf_init(&af_mctp->socket_send_buf,
266 af_mctp->socket)) {
267 close(af_mctp->socket);
268 free(af_mctp);
269 return -1;
270 }
271
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100272 *ctx = af_mctp;
273 return 0;
274}
275
Andrew Jeffery0a6d6822023-08-22 21:40:32 +0930276LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100277void pldm_transport_af_mctp_destroy(struct pldm_transport_af_mctp *ctx)
278{
279 if (!ctx) {
280 return;
281 }
282 close(ctx->socket);
283 free(ctx);
284}
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930285
Andrew Jeffery7dc429d2023-10-16 10:58:40 +1030286LIBPLDM_ABI_STABLE
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930287int pldm_transport_af_mctp_bind(struct pldm_transport_af_mctp *transport,
288 const struct sockaddr_mctp *smctp, size_t len)
289{
290 struct sockaddr_mctp lsmctp = { 0 };
291 int rc;
292
293 if (!transport) {
294 return PLDM_REQUESTER_INVALID_SETUP;
295 }
296
297 if (!smctp && len) {
298 return PLDM_REQUESTER_INVALID_SETUP;
299 }
300
301 if (!smctp) {
302 lsmctp.smctp_family = AF_MCTP;
303 lsmctp.smctp_network = MCTP_NET_ANY;
304 lsmctp.smctp_addr.s_addr = MCTP_ADDR_ANY;
305 lsmctp.smctp_type = MCTP_MSG_TYPE_PLDM;
306 lsmctp.smctp_tag = MCTP_TAG_OWNER;
307 smctp = &lsmctp;
308 len = sizeof(lsmctp);
309 }
310
311 if (smctp->smctp_family != AF_MCTP ||
312 smctp->smctp_type != MCTP_MSG_TYPE_PLDM ||
313 smctp->smctp_tag != MCTP_TAG_OWNER) {
314 return PLDM_REQUESTER_INVALID_SETUP;
315 }
316
317 if (len != sizeof(*smctp)) {
318 return PLDM_REQUESTER_INVALID_SETUP;
319 }
320
321 rc = bind(transport->socket, (const struct sockaddr *)smctp,
322 sizeof(*smctp));
323 if (rc) {
324 return PLDM_REQUESTER_SETUP_FAIL;
325 }
326
327 transport->bound = true;
328
329 return PLDM_REQUESTER_SUCCESS;
330}