blob: ace29699c90e1776c590bbd9d943bf5f8dc8ce23 [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"
Rashmica Gupta04273e92023-06-16 16:03:37 +10007#include "socket.h"
Rashmica Guptaba6971b2022-12-09 16:27:38 +11008#include "transport.h"
9
10#include <errno.h>
Rashmica Gupta04273e92023-06-16 16:03:37 +100011#include <limits.h>
Rashmica Guptaba6971b2022-12-09 16:27:38 +110012#include <linux/mctp.h>
13#include <poll.h>
14#include <stdlib.h>
15#include <string.h>
16#include <sys/socket.h>
17#include <sys/types.h>
18#include <sys/un.h>
19#include <unistd.h>
20
21#define AF_MCTP_NAME "AF_MCTP"
22struct pldm_transport_af_mctp {
23 struct pldm_transport transport;
24 int socket;
25 pldm_tid_t tid_eid_map[MCTP_MAX_NUM_EID];
Rashmica Gupta04273e92023-06-16 16:03:37 +100026 struct pldm_socket_sndbuf socket_send_buf;
Rashmica Guptaba6971b2022-12-09 16:27:38 +110027};
28
29#define transport_to_af_mctp(ptr) \
30 container_of(ptr, struct pldm_transport_af_mctp, transport)
31
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093032LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110033struct pldm_transport *
34pldm_transport_af_mctp_core(struct pldm_transport_af_mctp *ctx)
35{
36 return &ctx->transport;
37}
38
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093039LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110040int pldm_transport_af_mctp_init_pollfd(struct pldm_transport *t,
41 struct pollfd *pollfd)
42{
43 struct pldm_transport_af_mctp *ctx = transport_to_af_mctp(t);
44 pollfd->fd = ctx->socket;
45 pollfd->events = POLLIN;
46 return 0;
47}
48
49static int pldm_transport_af_mctp_get_eid(struct pldm_transport_af_mctp *ctx,
50 pldm_tid_t tid, mctp_eid_t *eid)
51{
52 int i;
53 for (i = 0; i < MCTP_MAX_NUM_EID; i++) {
54 if (ctx->tid_eid_map[i] == tid) {
55 *eid = i;
56 return 0;
57 }
58 }
59 *eid = -1;
60 return -1;
61}
62
Rashmica Gupta24576292023-07-31 14:02:41 +100063static int pldm_transport_af_mctp_get_tid(struct pldm_transport_af_mctp *ctx,
64 mctp_eid_t eid, pldm_tid_t *tid)
65{
66 if (ctx->tid_eid_map[eid] != 0) {
67 *tid = ctx->tid_eid_map[eid];
68 return 0;
69 }
70 return -1;
71}
72
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093073LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110074int pldm_transport_af_mctp_map_tid(struct pldm_transport_af_mctp *ctx,
75 pldm_tid_t tid, mctp_eid_t eid)
76{
77 ctx->tid_eid_map[eid] = tid;
78
79 return 0;
80}
81
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093082LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +110083int pldm_transport_af_mctp_unmap_tid(struct pldm_transport_af_mctp *ctx,
84 __attribute__((unused)) pldm_tid_t tid,
85 mctp_eid_t eid)
86{
87 ctx->tid_eid_map[eid] = 0;
88
89 return 0;
90}
91
92static pldm_requester_rc_t pldm_transport_af_mctp_recv(struct pldm_transport *t,
Rashmica Gupta24576292023-07-31 14:02:41 +100093 pldm_tid_t *tid,
Rashmica Guptaf1ebde42023-07-31 14:17:57 +100094 void **pldm_msg,
95 size_t *msg_len)
Rashmica Guptaba6971b2022-12-09 16:27:38 +110096{
97 struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t);
Rashmica Gupta24576292023-07-31 14:02:41 +100098 struct sockaddr_mctp addr = { 0 };
99 socklen_t addrlen = sizeof(addr);
100 pldm_requester_rc_t res;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100101 mctp_eid_t eid = 0;
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930102 ssize_t length;
Andrew Jefferyac247372023-08-18 10:46:12 +0930103 void *msg;
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930104 int rc;
105
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930106 length = recv(af_mctp->socket, NULL, 0, MSG_PEEK | MSG_TRUNC);
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100107 if (length <= 0) {
108 return PLDM_REQUESTER_RECV_FAIL;
109 }
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930110
Andrew Jefferyac247372023-08-18 10:46:12 +0930111 msg = malloc(length);
Andrew Jeffery7caa8af2023-08-18 10:50:54 +0930112 if (!msg) {
113 return PLDM_REQUESTER_RECV_FAIL;
114 }
115
Rashmica Gupta24576292023-07-31 14:02:41 +1000116 length = recvfrom(af_mctp->socket, msg, length, MSG_TRUNC,
117 (struct sockaddr *)&addr, &addrlen);
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100118 if (length < (ssize_t)sizeof(struct pldm_msg_hdr)) {
Rashmica Gupta24576292023-07-31 14:02:41 +1000119 res = PLDM_REQUESTER_INVALID_RECV_LEN;
120 goto cleanup_msg;
121 }
122
123 eid = addr.smctp_addr.s_addr;
124 rc = pldm_transport_af_mctp_get_tid(af_mctp, eid, tid);
125 if (rc) {
126 res = PLDM_REQUESTER_RECV_FAIL;
127 goto cleanup_msg;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100128 }
Andrew Jeffery2a6a3422023-08-18 09:53:21 +0930129
Andrew Jefferyac247372023-08-18 10:46:12 +0930130 *pldm_msg = msg;
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000131 *msg_len = length;
132
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100133 return PLDM_REQUESTER_SUCCESS;
Rashmica Gupta24576292023-07-31 14:02:41 +1000134
135cleanup_msg:
136 free(msg);
137
138 return res;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100139}
140
141static pldm_requester_rc_t pldm_transport_af_mctp_send(struct pldm_transport *t,
142 pldm_tid_t tid,
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000143 const void *pldm_msg,
144 size_t msg_len)
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100145{
146 struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t);
147 mctp_eid_t eid = 0;
148 if (pldm_transport_af_mctp_get_eid(af_mctp, tid, &eid)) {
149 return PLDM_REQUESTER_SEND_FAIL;
150 }
151
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930152 struct sockaddr_mctp addr = { 0 };
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100153 addr.smctp_family = AF_MCTP;
154 addr.smctp_addr.s_addr = eid;
155 addr.smctp_type = MCTP_MSG_TYPE_PLDM;
156 addr.smctp_tag = MCTP_TAG_OWNER;
157
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000158 if (msg_len > INT_MAX ||
Rashmica Gupta04273e92023-06-16 16:03:37 +1000159 pldm_socket_sndbuf_accomodate(&(af_mctp->socket_send_buf),
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000160 (int)msg_len)) {
Rashmica Gupta04273e92023-06-16 16:03:37 +1000161 return PLDM_REQUESTER_SEND_FAIL;
162 }
163
Rashmica Guptaf1ebde42023-07-31 14:17:57 +1000164 ssize_t rc = sendto(af_mctp->socket, pldm_msg, msg_len, 0,
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100165 (struct sockaddr *)&addr, sizeof(addr));
166 if (rc == -1) {
167 return PLDM_REQUESTER_SEND_FAIL;
168 }
169 return PLDM_REQUESTER_SUCCESS;
170}
171
Andrew Jeffery0a6d6822023-08-22 21:40:32 +0930172LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100173int pldm_transport_af_mctp_init(struct pldm_transport_af_mctp **ctx)
174{
175 if (!ctx || *ctx) {
176 return -EINVAL;
177 }
178
179 struct pldm_transport_af_mctp *af_mctp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930180 calloc(1, sizeof(struct pldm_transport_af_mctp));
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100181 if (!af_mctp) {
182 return -ENOMEM;
183 }
184
185 af_mctp->transport.name = AF_MCTP_NAME;
186 af_mctp->transport.version = 1;
187 af_mctp->transport.recv = pldm_transport_af_mctp_recv;
188 af_mctp->transport.send = pldm_transport_af_mctp_send;
Delphine CC Chiub4cd5172023-08-15 11:30:44 +0800189 af_mctp->transport.init_pollfd = pldm_transport_af_mctp_init_pollfd;
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100190 af_mctp->socket = socket(AF_MCTP, SOCK_DGRAM, 0);
191 if (af_mctp->socket == -1) {
192 free(af_mctp);
193 return -1;
194 }
Rashmica Gupta04273e92023-06-16 16:03:37 +1000195
196 if (pldm_socket_sndbuf_init(&af_mctp->socket_send_buf,
197 af_mctp->socket)) {
198 close(af_mctp->socket);
199 free(af_mctp);
200 return -1;
201 }
202
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100203 *ctx = af_mctp;
204 return 0;
205}
206
Andrew Jeffery0a6d6822023-08-22 21:40:32 +0930207LIBPLDM_ABI_STABLE
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100208void pldm_transport_af_mctp_destroy(struct pldm_transport_af_mctp *ctx)
209{
210 if (!ctx) {
211 return;
212 }
213 close(ctx->socket);
214 free(ctx);
215}