blob: 34454b35eacc1cde61d223093b527933d6e33f8c [file] [log] [blame]
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301#include "mctp-defines.h"
Rashmica Guptaba6971b2022-12-09 16:27:38 +11002#include "base.h"
3#include "container-of.h"
4#include "libpldm/pldm.h"
5#include "libpldm/transport.h"
BonnieLo-wiwynn36402ff2023-08-16 15:38:51 +08006#include "libpldm/transport/af-mctp.h"
Andrew Jefferycc45aed2023-09-10 23:03:29 +09307#include "responder.h"
Rashmica Gupta04273e92023-06-16 16:03:37 +10008#include "socket.h"
Rashmica Guptaba6971b2022-12-09 16:27:38 +11009#include "transport.h"
10
11#include <errno.h>
Rashmica Gupta04273e92023-06-16 16:03:37 +100012#include <limits.h>
Rashmica Guptaba6971b2022-12-09 16:27:38 +110013#include <linux/mctp.h>
14#include <poll.h>
Andrew Jefferycc45aed2023-09-10 23:03:29 +093015#include <stdbool.h>
Rashmica Guptaba6971b2022-12-09 16:27:38 +110016#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
Andrew Jefferycc45aed2023-09-10 23:03:29 +093023struct pldm_responder_cookie_af_mctp {
24 struct pldm_responder_cookie req;
25 struct sockaddr_mctp smctp;
26};
27
28#define cookie_to_af_mctp(c) \
29 container_of((c), struct pldm_responder_cookie_af_mctp, req)
30
Rashmica Guptaba6971b2022-12-09 16:27:38 +110031#define AF_MCTP_NAME "AF_MCTP"
32struct pldm_transport_af_mctp {
33 struct pldm_transport transport;
34 int socket;
35 pldm_tid_t tid_eid_map[MCTP_MAX_NUM_EID];
Rashmica Gupta04273e92023-06-16 16:03:37 +100036 struct pldm_socket_sndbuf socket_send_buf;
Andrew Jefferycc45aed2023-09-10 23:03:29 +093037 bool bound;
38 struct pldm_responder_cookie cookie_jar;
Rashmica Guptaba6971b2022-12-09 16:27:38 +110039};
40
41#define transport_to_af_mctp(ptr) \
42 container_of(ptr, struct pldm_transport_af_mctp, transport)
43
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093044LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110045struct pldm_transport *
46pldm_transport_af_mctp_core(struct pldm_transport_af_mctp *ctx)
47{
48 return &ctx->transport;
49}
50
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093051LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110052int pldm_transport_af_mctp_init_pollfd(struct pldm_transport *t,
53 struct pollfd *pollfd)
54{
55 struct pldm_transport_af_mctp *ctx = transport_to_af_mctp(t);
56 pollfd->fd = ctx->socket;
57 pollfd->events = POLLIN;
58 return 0;
59}
60
61static int pldm_transport_af_mctp_get_eid(struct pldm_transport_af_mctp *ctx,
62 pldm_tid_t tid, mctp_eid_t *eid)
63{
64 int i;
65 for (i = 0; i < MCTP_MAX_NUM_EID; i++) {
66 if (ctx->tid_eid_map[i] == tid) {
67 *eid = i;
68 return 0;
69 }
70 }
71 *eid = -1;
72 return -1;
73}
74
Rashmica Gupta24576292023-07-31 14:02:41 +100075static int pldm_transport_af_mctp_get_tid(struct pldm_transport_af_mctp *ctx,
76 mctp_eid_t eid, pldm_tid_t *tid)
77{
78 if (ctx->tid_eid_map[eid] != 0) {
79 *tid = ctx->tid_eid_map[eid];
80 return 0;
81 }
82 return -1;
83}
84
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093085LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110086int pldm_transport_af_mctp_map_tid(struct pldm_transport_af_mctp *ctx,
87 pldm_tid_t tid, mctp_eid_t eid)
88{
89 ctx->tid_eid_map[eid] = tid;
90
91 return 0;
92}
93
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093094LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110095int pldm_transport_af_mctp_unmap_tid(struct pldm_transport_af_mctp *ctx,
96 __attribute__((unused)) pldm_tid_t tid,
97 mctp_eid_t eid)
98{
99 ctx->tid_eid_map[eid] = 0;
100
101 return 0;
102}
103
104static pldm_requester_rc_t pldm_transport_af_mctp_recv(struct pldm_transport *t,
Rashmica Gupta24576292023-07-31 14:02:41 +1000105 pldm_tid_t *tid,
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000106 void **pldm_msg,
107 size_t *msg_len)
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100108{
109 struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t);
Rashmica Gupta24576292023-07-31 14:02:41 +1000110 struct sockaddr_mctp addr = { 0 };
111 socklen_t addrlen = sizeof(addr);
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930112 struct pldm_msg_hdr *hdr;
Rashmica Gupta24576292023-07-31 14:02:41 +1000113 pldm_requester_rc_t res;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100114 mctp_eid_t eid = 0;
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930115 ssize_t length;
Andrew Jefferyac247372023-08-18 10:46:12 +0930116 void *msg;
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930117 int rc;
118
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930119 length = recv(af_mctp->socket, NULL, 0, MSG_PEEK | MSG_TRUNC);
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100120 if (length <= 0) {
121 return PLDM_REQUESTER_RECV_FAIL;
122 }
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930123
Andrew Jefferyac247372023-08-18 10:46:12 +0930124 msg = malloc(length);
Andrew Jeffery7caa8af2023-08-18 10:50:54 +0930125 if (!msg) {
126 return PLDM_REQUESTER_RECV_FAIL;
127 }
128
Rashmica Gupta24576292023-07-31 14:02:41 +1000129 length = recvfrom(af_mctp->socket, msg, length, MSG_TRUNC,
130 (struct sockaddr *)&addr, &addrlen);
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100131 if (length < (ssize_t)sizeof(struct pldm_msg_hdr)) {
Rashmica Gupta24576292023-07-31 14:02:41 +1000132 res = PLDM_REQUESTER_INVALID_RECV_LEN;
133 goto cleanup_msg;
134 }
135
136 eid = addr.smctp_addr.s_addr;
137 rc = pldm_transport_af_mctp_get_tid(af_mctp, eid, tid);
138 if (rc) {
139 res = PLDM_REQUESTER_RECV_FAIL;
140 goto cleanup_msg;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100141 }
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930142
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930143 hdr = msg;
144
145 if (af_mctp->bound && hdr->request) {
146 struct pldm_responder_cookie_af_mctp *cookie;
147
148 cookie = malloc(sizeof(*cookie));
149 if (!cookie) {
150 res = PLDM_REQUESTER_RECV_FAIL;
151 goto cleanup_msg;
152 }
153
154 cookie->req.tid = *tid,
155 cookie->req.instance_id = hdr->instance_id,
156 cookie->req.type = hdr->type,
157 cookie->req.command = hdr->command;
158 cookie->smctp = addr;
159
160 rc = pldm_responder_cookie_track(&af_mctp->cookie_jar,
161 &cookie->req);
162 if (rc) {
163 res = PLDM_REQUESTER_RECV_FAIL;
164 goto cleanup_msg;
165 }
166 }
167
Andrew Jefferyac247372023-08-18 10:46:12 +0930168 *pldm_msg = msg;
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000169 *msg_len = length;
170
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100171 return PLDM_REQUESTER_SUCCESS;
Rashmica Gupta24576292023-07-31 14:02:41 +1000172
173cleanup_msg:
174 free(msg);
175
176 return res;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100177}
178
179static pldm_requester_rc_t pldm_transport_af_mctp_send(struct pldm_transport *t,
180 pldm_tid_t tid,
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000181 const void *pldm_msg,
182 size_t msg_len)
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100183{
184 struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t);
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930185 const struct pldm_msg_hdr *hdr;
186 struct sockaddr_mctp addr = { 0 };
187
188 if (msg_len < (ssize_t)sizeof(struct pldm_msg_hdr)) {
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100189 return PLDM_REQUESTER_SEND_FAIL;
190 }
191
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930192 hdr = pldm_msg;
193 if (af_mctp->bound && !hdr->request) {
194 struct pldm_responder_cookie_af_mctp *cookie;
195 struct pldm_responder_cookie *req;
196
197 req = pldm_responder_cookie_untrack(&af_mctp->cookie_jar, tid,
198 hdr->instance_id, hdr->type,
199 hdr->command);
200 if (!req) {
201 return PLDM_REQUESTER_SEND_FAIL;
202 }
203
204 cookie = cookie_to_af_mctp(req);
205 addr = cookie->smctp;
206 /* Clear the TO to indicate a response */
207 addr.smctp_tag &= ~MCTP_TAG_OWNER;
208 free(cookie);
209 } else {
210 mctp_eid_t eid = 0;
211 if (pldm_transport_af_mctp_get_eid(af_mctp, tid, &eid)) {
212 return PLDM_REQUESTER_SEND_FAIL;
213 }
214
215 addr.smctp_family = AF_MCTP;
216 addr.smctp_addr.s_addr = eid;
217 addr.smctp_type = MCTP_MSG_TYPE_PLDM;
218 addr.smctp_tag = MCTP_TAG_OWNER;
219 }
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100220
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000221 if (msg_len > INT_MAX ||
Rashmica Gupta04273e92023-06-16 16:03:37 +1000222 pldm_socket_sndbuf_accomodate(&(af_mctp->socket_send_buf),
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000223 (int)msg_len)) {
Rashmica Gupta04273e92023-06-16 16:03:37 +1000224 return PLDM_REQUESTER_SEND_FAIL;
225 }
226
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000227 ssize_t rc = sendto(af_mctp->socket, pldm_msg, msg_len, 0,
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100228 (struct sockaddr *)&addr, sizeof(addr));
229 if (rc == -1) {
230 return PLDM_REQUESTER_SEND_FAIL;
231 }
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930232
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100233 return PLDM_REQUESTER_SUCCESS;
234}
235
Andrew Jeffery0a6d6822023-08-22 21:40:32 +0930236LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100237int pldm_transport_af_mctp_init(struct pldm_transport_af_mctp **ctx)
238{
239 if (!ctx || *ctx) {
240 return -EINVAL;
241 }
242
243 struct pldm_transport_af_mctp *af_mctp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930244 calloc(1, sizeof(struct pldm_transport_af_mctp));
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100245 if (!af_mctp) {
246 return -ENOMEM;
247 }
248
249 af_mctp->transport.name = AF_MCTP_NAME;
250 af_mctp->transport.version = 1;
251 af_mctp->transport.recv = pldm_transport_af_mctp_recv;
252 af_mctp->transport.send = pldm_transport_af_mctp_send;
Delphine CC Chiub4cd5172023-08-15 11:30:44 +0800253 af_mctp->transport.init_pollfd = pldm_transport_af_mctp_init_pollfd;
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930254 af_mctp->bound = false;
255 af_mctp->cookie_jar.next = NULL;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100256 af_mctp->socket = socket(AF_MCTP, SOCK_DGRAM, 0);
257 if (af_mctp->socket == -1) {
258 free(af_mctp);
259 return -1;
260 }
Rashmica Gupta04273e92023-06-16 16:03:37 +1000261
262 if (pldm_socket_sndbuf_init(&af_mctp->socket_send_buf,
263 af_mctp->socket)) {
264 close(af_mctp->socket);
265 free(af_mctp);
266 return -1;
267 }
268
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100269 *ctx = af_mctp;
270 return 0;
271}
272
Andrew Jeffery0a6d6822023-08-22 21:40:32 +0930273LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100274void pldm_transport_af_mctp_destroy(struct pldm_transport_af_mctp *ctx)
275{
276 if (!ctx) {
277 return;
278 }
279 close(ctx->socket);
280 free(ctx);
281}
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930282
Andrew Jeffery7dc429d2023-10-16 10:58:40 +1030283LIBPLDM_ABI_STABLE
Andrew Jefferycc45aed2023-09-10 23:03:29 +0930284int pldm_transport_af_mctp_bind(struct pldm_transport_af_mctp *transport,
285 const struct sockaddr_mctp *smctp, size_t len)
286{
287 struct sockaddr_mctp lsmctp = { 0 };
288 int rc;
289
290 if (!transport) {
291 return PLDM_REQUESTER_INVALID_SETUP;
292 }
293
294 if (!smctp && len) {
295 return PLDM_REQUESTER_INVALID_SETUP;
296 }
297
298 if (!smctp) {
299 lsmctp.smctp_family = AF_MCTP;
300 lsmctp.smctp_network = MCTP_NET_ANY;
301 lsmctp.smctp_addr.s_addr = MCTP_ADDR_ANY;
302 lsmctp.smctp_type = MCTP_MSG_TYPE_PLDM;
303 lsmctp.smctp_tag = MCTP_TAG_OWNER;
304 smctp = &lsmctp;
305 len = sizeof(lsmctp);
306 }
307
308 if (smctp->smctp_family != AF_MCTP ||
309 smctp->smctp_type != MCTP_MSG_TYPE_PLDM ||
310 smctp->smctp_tag != MCTP_TAG_OWNER) {
311 return PLDM_REQUESTER_INVALID_SETUP;
312 }
313
314 if (len != sizeof(*smctp)) {
315 return PLDM_REQUESTER_INVALID_SETUP;
316 }
317
318 rc = bind(transport->socket, (const struct sockaddr *)smctp,
319 sizeof(*smctp));
320 if (rc) {
321 return PLDM_REQUESTER_SETUP_FAIL;
322 }
323
324 transport->bound = true;
325
326 return PLDM_REQUESTER_SUCCESS;
327}