blob: ea798635741ce4b132c0c9fd867f295f122a003b [file] [log] [blame]
Patrick Williams691668f2023-11-01 08:19:10 -05001/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
Rashmica Guptaba6971b2022-12-09 16:27:38 +11002#include "container-of.h"
Andrew Jefferyb0c1d202023-11-07 22:08:44 +10303#include "mctp-defines.h"
Andrew Jefferycc45aed2023-09-10 23:03:29 +09304#include "responder.h"
Rashmica Gupta04273e92023-06-16 16:03:37 +10005#include "socket.h"
Rashmica Guptaba6971b2022-12-09 16:27:38 +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/af-mctp.h>
12
Rashmica Guptaba6971b2022-12-09 16:27:38 +110013#include <errno.h>
Rashmica Gupta04273e92023-06-16 16:03:37 +100014#include <limits.h>
Rashmica Guptaba6971b2022-12-09 16:27:38 +110015#include <linux/mctp.h>
16#include <poll.h>
Andrew Jefferycc45aed2023-09-10 23:03:29 +093017#include <stdbool.h>
Rashmica Guptaba6971b2022-12-09 16:27:38 +110018#include <stdlib.h>
19#include <string.h>
20#include <sys/socket.h>
21#include <sys/types.h>
22#include <sys/un.h>
23#include <unistd.h>
24
Andrew Jefferycc45aed2023-09-10 23:03:29 +093025struct pldm_responder_cookie_af_mctp {
26 struct pldm_responder_cookie req;
27 struct sockaddr_mctp smctp;
28};
29
30#define cookie_to_af_mctp(c) \
31 container_of((c), struct pldm_responder_cookie_af_mctp, req)
32
Rashmica Guptaba6971b2022-12-09 16:27:38 +110033#define AF_MCTP_NAME "AF_MCTP"
34struct pldm_transport_af_mctp {
35 struct pldm_transport transport;
36 int socket;
37 pldm_tid_t tid_eid_map[MCTP_MAX_NUM_EID];
Rashmica Gupta04273e92023-06-16 16:03:37 +100038 struct pldm_socket_sndbuf socket_send_buf;
Andrew Jefferycc45aed2023-09-10 23:03:29 +093039 bool bound;
40 struct pldm_responder_cookie cookie_jar;
Rashmica Guptaba6971b2022-12-09 16:27:38 +110041};
42
43#define transport_to_af_mctp(ptr) \
44 container_of(ptr, struct pldm_transport_af_mctp, transport)
45
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093046LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110047struct pldm_transport *
48pldm_transport_af_mctp_core(struct pldm_transport_af_mctp *ctx)
49{
50 return &ctx->transport;
51}
52
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093053LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110054int pldm_transport_af_mctp_init_pollfd(struct pldm_transport *t,
55 struct pollfd *pollfd)
56{
57 struct pldm_transport_af_mctp *ctx = transport_to_af_mctp(t);
58 pollfd->fd = ctx->socket;
59 pollfd->events = POLLIN;
60 return 0;
61}
62
63static int pldm_transport_af_mctp_get_eid(struct pldm_transport_af_mctp *ctx,
64 pldm_tid_t tid, mctp_eid_t *eid)
65{
66 int i;
67 for (i = 0; i < MCTP_MAX_NUM_EID; i++) {
68 if (ctx->tid_eid_map[i] == tid) {
69 *eid = i;
70 return 0;
71 }
72 }
73 *eid = -1;
74 return -1;
75}
76
Rashmica Gupta24576292023-07-31 14:02:41 +100077static int pldm_transport_af_mctp_get_tid(struct pldm_transport_af_mctp *ctx,
78 mctp_eid_t eid, pldm_tid_t *tid)
79{
80 if (ctx->tid_eid_map[eid] != 0) {
81 *tid = ctx->tid_eid_map[eid];
82 return 0;
83 }
84 return -1;
85}
86
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093087LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110088int pldm_transport_af_mctp_map_tid(struct pldm_transport_af_mctp *ctx,
89 pldm_tid_t tid, mctp_eid_t eid)
90{
91 ctx->tid_eid_map[eid] = tid;
92
93 return 0;
94}
95
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093096LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110097int pldm_transport_af_mctp_unmap_tid(struct pldm_transport_af_mctp *ctx,
98 __attribute__((unused)) pldm_tid_t tid,
99 mctp_eid_t eid)
100{
101 ctx->tid_eid_map[eid] = 0;
102
103 return 0;
104}
105
106static pldm_requester_rc_t pldm_transport_af_mctp_recv(struct pldm_transport *t,
Rashmica Gupta24576292023-07-31 14:02:41 +1000107 pldm_tid_t *tid,
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000108 void **pldm_msg,
109 size_t *msg_len)
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100110{
111 struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t);
Rashmica Gupta24576292023-07-31 14:02:41 +1000112 struct sockaddr_mctp addr = { 0 };
113 socklen_t addrlen = sizeof(addr);
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930114 struct pldm_msg_hdr *hdr;
Rashmica Gupta24576292023-07-31 14:02:41 +1000115 pldm_requester_rc_t res;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100116 mctp_eid_t eid = 0;
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930117 ssize_t length;
Andrew Jefferyac247372023-08-18 10:46:12 +0930118 void *msg;
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930119 int rc;
120
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930121 length = recv(af_mctp->socket, NULL, 0, MSG_PEEK | MSG_TRUNC);
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100122 if (length <= 0) {
123 return PLDM_REQUESTER_RECV_FAIL;
124 }
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930125
Andrew Jefferyac247372023-08-18 10:46:12 +0930126 msg = malloc(length);
Andrew Jeffery7caa8af2023-08-18 10:50:54 +0930127 if (!msg) {
128 return PLDM_REQUESTER_RECV_FAIL;
129 }
130
Rashmica Gupta24576292023-07-31 14:02:41 +1000131 length = recvfrom(af_mctp->socket, msg, length, MSG_TRUNC,
132 (struct sockaddr *)&addr, &addrlen);
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100133 if (length < (ssize_t)sizeof(struct pldm_msg_hdr)) {
Rashmica Gupta24576292023-07-31 14:02:41 +1000134 res = PLDM_REQUESTER_INVALID_RECV_LEN;
135 goto cleanup_msg;
136 }
137
138 eid = addr.smctp_addr.s_addr;
139 rc = pldm_transport_af_mctp_get_tid(af_mctp, eid, tid);
140 if (rc) {
141 res = PLDM_REQUESTER_RECV_FAIL;
142 goto cleanup_msg;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100143 }
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930144
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930145 hdr = msg;
146
147 if (af_mctp->bound && hdr->request) {
148 struct pldm_responder_cookie_af_mctp *cookie;
149
150 cookie = malloc(sizeof(*cookie));
151 if (!cookie) {
152 res = PLDM_REQUESTER_RECV_FAIL;
153 goto cleanup_msg;
154 }
155
156 cookie->req.tid = *tid,
157 cookie->req.instance_id = hdr->instance_id,
158 cookie->req.type = hdr->type,
159 cookie->req.command = hdr->command;
160 cookie->smctp = addr;
161
162 rc = pldm_responder_cookie_track(&af_mctp->cookie_jar,
163 &cookie->req);
164 if (rc) {
165 res = PLDM_REQUESTER_RECV_FAIL;
166 goto cleanup_msg;
167 }
168 }
169
Andrew Jefferyac247372023-08-18 10:46:12 +0930170 *pldm_msg = msg;
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000171 *msg_len = length;
172
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100173 return PLDM_REQUESTER_SUCCESS;
Rashmica Gupta24576292023-07-31 14:02:41 +1000174
175cleanup_msg:
176 free(msg);
177
178 return res;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100179}
180
181static pldm_requester_rc_t pldm_transport_af_mctp_send(struct pldm_transport *t,
182 pldm_tid_t tid,
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000183 const void *pldm_msg,
184 size_t msg_len)
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100185{
186 struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t);
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930187 const struct pldm_msg_hdr *hdr;
188 struct sockaddr_mctp addr = { 0 };
189
190 if (msg_len < (ssize_t)sizeof(struct pldm_msg_hdr)) {
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100191 return PLDM_REQUESTER_SEND_FAIL;
192 }
193
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930194 hdr = pldm_msg;
195 if (af_mctp->bound && !hdr->request) {
196 struct pldm_responder_cookie_af_mctp *cookie;
197 struct pldm_responder_cookie *req;
198
199 req = pldm_responder_cookie_untrack(&af_mctp->cookie_jar, tid,
200 hdr->instance_id, hdr->type,
201 hdr->command);
202 if (!req) {
203 return PLDM_REQUESTER_SEND_FAIL;
204 }
205
206 cookie = cookie_to_af_mctp(req);
207 addr = cookie->smctp;
208 /* Clear the TO to indicate a response */
209 addr.smctp_tag &= ~MCTP_TAG_OWNER;
210 free(cookie);
211 } else {
212 mctp_eid_t eid = 0;
213 if (pldm_transport_af_mctp_get_eid(af_mctp, tid, &eid)) {
214 return PLDM_REQUESTER_SEND_FAIL;
215 }
216
217 addr.smctp_family = AF_MCTP;
218 addr.smctp_addr.s_addr = eid;
219 addr.smctp_type = MCTP_MSG_TYPE_PLDM;
220 addr.smctp_tag = MCTP_TAG_OWNER;
221 }
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100222
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000223 if (msg_len > INT_MAX ||
Rashmica Gupta04273e92023-06-16 16:03:37 +1000224 pldm_socket_sndbuf_accomodate(&(af_mctp->socket_send_buf),
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000225 (int)msg_len)) {
Rashmica Gupta04273e92023-06-16 16:03:37 +1000226 return PLDM_REQUESTER_SEND_FAIL;
227 }
228
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000229 ssize_t rc = sendto(af_mctp->socket, pldm_msg, msg_len, 0,
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100230 (struct sockaddr *)&addr, sizeof(addr));
231 if (rc == -1) {
232 return PLDM_REQUESTER_SEND_FAIL;
233 }
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930234
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100235 return PLDM_REQUESTER_SUCCESS;
236}
237
Andrew Jeffery0a6d6822023-08-22 21:40:32 +0930238LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100239int pldm_transport_af_mctp_init(struct pldm_transport_af_mctp **ctx)
240{
241 if (!ctx || *ctx) {
242 return -EINVAL;
243 }
244
245 struct pldm_transport_af_mctp *af_mctp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930246 calloc(1, sizeof(struct pldm_transport_af_mctp));
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100247 if (!af_mctp) {
248 return -ENOMEM;
249 }
250
251 af_mctp->transport.name = AF_MCTP_NAME;
252 af_mctp->transport.version = 1;
253 af_mctp->transport.recv = pldm_transport_af_mctp_recv;
254 af_mctp->transport.send = pldm_transport_af_mctp_send;
Delphine CC Chiub4cd5172023-08-15 11:30:44 +0800255 af_mctp->transport.init_pollfd = pldm_transport_af_mctp_init_pollfd;
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930256 af_mctp->bound = false;
257 af_mctp->cookie_jar.next = NULL;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100258 af_mctp->socket = socket(AF_MCTP, SOCK_DGRAM, 0);
259 if (af_mctp->socket == -1) {
260 free(af_mctp);
261 return -1;
262 }
Rashmica Gupta04273e92023-06-16 16:03:37 +1000263
264 if (pldm_socket_sndbuf_init(&af_mctp->socket_send_buf,
265 af_mctp->socket)) {
266 close(af_mctp->socket);
267 free(af_mctp);
268 return -1;
269 }
270
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100271 *ctx = af_mctp;
272 return 0;
273}
274
Andrew Jeffery0a6d6822023-08-22 21:40:32 +0930275LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100276void pldm_transport_af_mctp_destroy(struct pldm_transport_af_mctp *ctx)
277{
278 if (!ctx) {
279 return;
280 }
281 close(ctx->socket);
282 free(ctx);
283}
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930284
Andrew Jeffery7dc429d2023-10-16 10:58:40 +1030285LIBPLDM_ABI_STABLE
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930286int pldm_transport_af_mctp_bind(struct pldm_transport_af_mctp *transport,
287 const struct sockaddr_mctp *smctp, size_t len)
288{
289 struct sockaddr_mctp lsmctp = { 0 };
290 int rc;
291
292 if (!transport) {
293 return PLDM_REQUESTER_INVALID_SETUP;
294 }
295
296 if (!smctp && len) {
297 return PLDM_REQUESTER_INVALID_SETUP;
298 }
299
300 if (!smctp) {
301 lsmctp.smctp_family = AF_MCTP;
302 lsmctp.smctp_network = MCTP_NET_ANY;
303 lsmctp.smctp_addr.s_addr = MCTP_ADDR_ANY;
304 lsmctp.smctp_type = MCTP_MSG_TYPE_PLDM;
305 lsmctp.smctp_tag = MCTP_TAG_OWNER;
306 smctp = &lsmctp;
307 len = sizeof(lsmctp);
308 }
309
310 if (smctp->smctp_family != AF_MCTP ||
311 smctp->smctp_type != MCTP_MSG_TYPE_PLDM ||
312 smctp->smctp_tag != MCTP_TAG_OWNER) {
313 return PLDM_REQUESTER_INVALID_SETUP;
314 }
315
316 if (len != sizeof(*smctp)) {
317 return PLDM_REQUESTER_INVALID_SETUP;
318 }
319
320 rc = bind(transport->socket, (const struct sockaddr *)smctp,
321 sizeof(*smctp));
322 if (rc) {
323 return PLDM_REQUESTER_SETUP_FAIL;
324 }
325
326 transport->bound = true;
327
328 return PLDM_REQUESTER_SUCCESS;
329}