blob: bf024b8d4704ccd63d829be6128de863a01b96d2 [file] [log] [blame]
Patrick Williams691668f2023-11-01 08:19:10 -05001/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09302#include "mctp-defines.h"
Rashmica Guptaba6971b2022-12-09 16:27:38 +11003#include "base.h"
4#include "container-of.h"
5#include "libpldm/pldm.h"
6#include "libpldm/transport.h"
BonnieLo-wiwynn36402ff2023-08-16 15:38:51 +08007#include "libpldm/transport/af-mctp.h"
Andrew Jefferycc45aed2023-09-10 23:03:29 +09308#include "responder.h"
Rashmica Gupta04273e92023-06-16 16:03:37 +10009#include "socket.h"
Rashmica Guptaba6971b2022-12-09 16:27:38 +110010#include "transport.h"
11
12#include <errno.h>
Rashmica Gupta04273e92023-06-16 16:03:37 +100013#include <limits.h>
Rashmica Guptaba6971b2022-12-09 16:27:38 +110014#include <linux/mctp.h>
15#include <poll.h>
Andrew Jefferycc45aed2023-09-10 23:03:29 +093016#include <stdbool.h>
Rashmica Guptaba6971b2022-12-09 16:27:38 +110017#include <stdlib.h>
18#include <string.h>
19#include <sys/socket.h>
20#include <sys/types.h>
21#include <sys/un.h>
22#include <unistd.h>
23
Andrew Jefferycc45aed2023-09-10 23:03:29 +093024struct pldm_responder_cookie_af_mctp {
25 struct pldm_responder_cookie req;
26 struct sockaddr_mctp smctp;
27};
28
29#define cookie_to_af_mctp(c) \
30 container_of((c), struct pldm_responder_cookie_af_mctp, req)
31
Rashmica Guptaba6971b2022-12-09 16:27:38 +110032#define AF_MCTP_NAME "AF_MCTP"
33struct pldm_transport_af_mctp {
34 struct pldm_transport transport;
35 int socket;
36 pldm_tid_t tid_eid_map[MCTP_MAX_NUM_EID];
Rashmica Gupta04273e92023-06-16 16:03:37 +100037 struct pldm_socket_sndbuf socket_send_buf;
Andrew Jefferycc45aed2023-09-10 23:03:29 +093038 bool bound;
39 struct pldm_responder_cookie cookie_jar;
Rashmica Guptaba6971b2022-12-09 16:27:38 +110040};
41
42#define transport_to_af_mctp(ptr) \
43 container_of(ptr, struct pldm_transport_af_mctp, transport)
44
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093045LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110046struct pldm_transport *
47pldm_transport_af_mctp_core(struct pldm_transport_af_mctp *ctx)
48{
49 return &ctx->transport;
50}
51
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093052LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110053int pldm_transport_af_mctp_init_pollfd(struct pldm_transport *t,
54 struct pollfd *pollfd)
55{
56 struct pldm_transport_af_mctp *ctx = transport_to_af_mctp(t);
57 pollfd->fd = ctx->socket;
58 pollfd->events = POLLIN;
59 return 0;
60}
61
62static int pldm_transport_af_mctp_get_eid(struct pldm_transport_af_mctp *ctx,
63 pldm_tid_t tid, mctp_eid_t *eid)
64{
65 int i;
66 for (i = 0; i < MCTP_MAX_NUM_EID; i++) {
67 if (ctx->tid_eid_map[i] == tid) {
68 *eid = i;
69 return 0;
70 }
71 }
72 *eid = -1;
73 return -1;
74}
75
Rashmica Gupta24576292023-07-31 14:02:41 +100076static int pldm_transport_af_mctp_get_tid(struct pldm_transport_af_mctp *ctx,
77 mctp_eid_t eid, pldm_tid_t *tid)
78{
79 if (ctx->tid_eid_map[eid] != 0) {
80 *tid = ctx->tid_eid_map[eid];
81 return 0;
82 }
83 return -1;
84}
85
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093086LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110087int pldm_transport_af_mctp_map_tid(struct pldm_transport_af_mctp *ctx,
88 pldm_tid_t tid, mctp_eid_t eid)
89{
90 ctx->tid_eid_map[eid] = tid;
91
92 return 0;
93}
94
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093095LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110096int pldm_transport_af_mctp_unmap_tid(struct pldm_transport_af_mctp *ctx,
97 __attribute__((unused)) pldm_tid_t tid,
98 mctp_eid_t eid)
99{
100 ctx->tid_eid_map[eid] = 0;
101
102 return 0;
103}
104
105static pldm_requester_rc_t pldm_transport_af_mctp_recv(struct pldm_transport *t,
Rashmica Gupta24576292023-07-31 14:02:41 +1000106 pldm_tid_t *tid,
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000107 void **pldm_msg,
108 size_t *msg_len)
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100109{
110 struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t);
Rashmica Gupta24576292023-07-31 14:02:41 +1000111 struct sockaddr_mctp addr = { 0 };
112 socklen_t addrlen = sizeof(addr);
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930113 struct pldm_msg_hdr *hdr;
Rashmica Gupta24576292023-07-31 14:02:41 +1000114 pldm_requester_rc_t res;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100115 mctp_eid_t eid = 0;
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930116 ssize_t length;
Andrew Jefferyac247372023-08-18 10:46:12 +0930117 void *msg;
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930118 int rc;
119
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930120 length = recv(af_mctp->socket, NULL, 0, MSG_PEEK | MSG_TRUNC);
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100121 if (length <= 0) {
122 return PLDM_REQUESTER_RECV_FAIL;
123 }
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930124
Andrew Jefferyac247372023-08-18 10:46:12 +0930125 msg = malloc(length);
Andrew Jeffery7caa8af2023-08-18 10:50:54 +0930126 if (!msg) {
127 return PLDM_REQUESTER_RECV_FAIL;
128 }
129
Rashmica Gupta24576292023-07-31 14:02:41 +1000130 length = recvfrom(af_mctp->socket, msg, length, MSG_TRUNC,
131 (struct sockaddr *)&addr, &addrlen);
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100132 if (length < (ssize_t)sizeof(struct pldm_msg_hdr)) {
Rashmica Gupta24576292023-07-31 14:02:41 +1000133 res = PLDM_REQUESTER_INVALID_RECV_LEN;
134 goto cleanup_msg;
135 }
136
137 eid = addr.smctp_addr.s_addr;
138 rc = pldm_transport_af_mctp_get_tid(af_mctp, eid, tid);
139 if (rc) {
140 res = PLDM_REQUESTER_RECV_FAIL;
141 goto cleanup_msg;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100142 }
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930143
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930144 hdr = msg;
145
146 if (af_mctp->bound && hdr->request) {
147 struct pldm_responder_cookie_af_mctp *cookie;
148
149 cookie = malloc(sizeof(*cookie));
150 if (!cookie) {
151 res = PLDM_REQUESTER_RECV_FAIL;
152 goto cleanup_msg;
153 }
154
155 cookie->req.tid = *tid,
156 cookie->req.instance_id = hdr->instance_id,
157 cookie->req.type = hdr->type,
158 cookie->req.command = hdr->command;
159 cookie->smctp = addr;
160
161 rc = pldm_responder_cookie_track(&af_mctp->cookie_jar,
162 &cookie->req);
163 if (rc) {
164 res = PLDM_REQUESTER_RECV_FAIL;
165 goto cleanup_msg;
166 }
167 }
168
Andrew Jefferyac247372023-08-18 10:46:12 +0930169 *pldm_msg = msg;
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000170 *msg_len = length;
171
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100172 return PLDM_REQUESTER_SUCCESS;
Rashmica Gupta24576292023-07-31 14:02:41 +1000173
174cleanup_msg:
175 free(msg);
176
177 return res;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100178}
179
180static pldm_requester_rc_t pldm_transport_af_mctp_send(struct pldm_transport *t,
181 pldm_tid_t tid,
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000182 const void *pldm_msg,
183 size_t msg_len)
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100184{
185 struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t);
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930186 const struct pldm_msg_hdr *hdr;
187 struct sockaddr_mctp addr = { 0 };
188
189 if (msg_len < (ssize_t)sizeof(struct pldm_msg_hdr)) {
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100190 return PLDM_REQUESTER_SEND_FAIL;
191 }
192
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930193 hdr = pldm_msg;
194 if (af_mctp->bound && !hdr->request) {
195 struct pldm_responder_cookie_af_mctp *cookie;
196 struct pldm_responder_cookie *req;
197
198 req = pldm_responder_cookie_untrack(&af_mctp->cookie_jar, tid,
199 hdr->instance_id, hdr->type,
200 hdr->command);
201 if (!req) {
202 return PLDM_REQUESTER_SEND_FAIL;
203 }
204
205 cookie = cookie_to_af_mctp(req);
206 addr = cookie->smctp;
207 /* Clear the TO to indicate a response */
208 addr.smctp_tag &= ~MCTP_TAG_OWNER;
209 free(cookie);
210 } else {
211 mctp_eid_t eid = 0;
212 if (pldm_transport_af_mctp_get_eid(af_mctp, tid, &eid)) {
213 return PLDM_REQUESTER_SEND_FAIL;
214 }
215
216 addr.smctp_family = AF_MCTP;
217 addr.smctp_addr.s_addr = eid;
218 addr.smctp_type = MCTP_MSG_TYPE_PLDM;
219 addr.smctp_tag = MCTP_TAG_OWNER;
220 }
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100221
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000222 if (msg_len > INT_MAX ||
Rashmica Gupta04273e92023-06-16 16:03:37 +1000223 pldm_socket_sndbuf_accomodate(&(af_mctp->socket_send_buf),
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000224 (int)msg_len)) {
Rashmica Gupta04273e92023-06-16 16:03:37 +1000225 return PLDM_REQUESTER_SEND_FAIL;
226 }
227
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000228 ssize_t rc = sendto(af_mctp->socket, pldm_msg, msg_len, 0,
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100229 (struct sockaddr *)&addr, sizeof(addr));
230 if (rc == -1) {
231 return PLDM_REQUESTER_SEND_FAIL;
232 }
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930233
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100234 return PLDM_REQUESTER_SUCCESS;
235}
236
Andrew Jeffery0a6d6822023-08-22 21:40:32 +0930237LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100238int pldm_transport_af_mctp_init(struct pldm_transport_af_mctp **ctx)
239{
240 if (!ctx || *ctx) {
241 return -EINVAL;
242 }
243
244 struct pldm_transport_af_mctp *af_mctp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930245 calloc(1, sizeof(struct pldm_transport_af_mctp));
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100246 if (!af_mctp) {
247 return -ENOMEM;
248 }
249
250 af_mctp->transport.name = AF_MCTP_NAME;
251 af_mctp->transport.version = 1;
252 af_mctp->transport.recv = pldm_transport_af_mctp_recv;
253 af_mctp->transport.send = pldm_transport_af_mctp_send;
Delphine CC Chiub4cd5172023-08-15 11:30:44 +0800254 af_mctp->transport.init_pollfd = pldm_transport_af_mctp_init_pollfd;
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930255 af_mctp->bound = false;
256 af_mctp->cookie_jar.next = NULL;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100257 af_mctp->socket = socket(AF_MCTP, SOCK_DGRAM, 0);
258 if (af_mctp->socket == -1) {
259 free(af_mctp);
260 return -1;
261 }
Rashmica Gupta04273e92023-06-16 16:03:37 +1000262
263 if (pldm_socket_sndbuf_init(&af_mctp->socket_send_buf,
264 af_mctp->socket)) {
265 close(af_mctp->socket);
266 free(af_mctp);
267 return -1;
268 }
269
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100270 *ctx = af_mctp;
271 return 0;
272}
273
Andrew Jeffery0a6d6822023-08-22 21:40:32 +0930274LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100275void pldm_transport_af_mctp_destroy(struct pldm_transport_af_mctp *ctx)
276{
277 if (!ctx) {
278 return;
279 }
280 close(ctx->socket);
281 free(ctx);
282}
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930283
Andrew Jeffery7dc429d2023-10-16 10:58:40 +1030284LIBPLDM_ABI_STABLE
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930285int pldm_transport_af_mctp_bind(struct pldm_transport_af_mctp *transport,
286 const struct sockaddr_mctp *smctp, size_t len)
287{
288 struct sockaddr_mctp lsmctp = { 0 };
289 int rc;
290
291 if (!transport) {
292 return PLDM_REQUESTER_INVALID_SETUP;
293 }
294
295 if (!smctp && len) {
296 return PLDM_REQUESTER_INVALID_SETUP;
297 }
298
299 if (!smctp) {
300 lsmctp.smctp_family = AF_MCTP;
301 lsmctp.smctp_network = MCTP_NET_ANY;
302 lsmctp.smctp_addr.s_addr = MCTP_ADDR_ANY;
303 lsmctp.smctp_type = MCTP_MSG_TYPE_PLDM;
304 lsmctp.smctp_tag = MCTP_TAG_OWNER;
305 smctp = &lsmctp;
306 len = sizeof(lsmctp);
307 }
308
309 if (smctp->smctp_family != AF_MCTP ||
310 smctp->smctp_type != MCTP_MSG_TYPE_PLDM ||
311 smctp->smctp_tag != MCTP_TAG_OWNER) {
312 return PLDM_REQUESTER_INVALID_SETUP;
313 }
314
315 if (len != sizeof(*smctp)) {
316 return PLDM_REQUESTER_INVALID_SETUP;
317 }
318
319 rc = bind(transport->socket, (const struct sockaddr *)smctp,
320 sizeof(*smctp));
321 if (rc) {
322 return PLDM_REQUESTER_SETUP_FAIL;
323 }
324
325 transport->bound = true;
326
327 return PLDM_REQUESTER_SUCCESS;
328}