blob: c77109174cd7b9bad604492b811ded5edd73cf98 [file] [log] [blame]
Patrick Williams691668f2023-11-01 08:19:10 -05001/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
Andrew Jefferyb0c1d202023-11-07 22:08:44 +10302#include <libpldm/base.h>
3#include <libpldm/requester/pldm.h>
4#include <libpldm/transport.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +09305
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05306#include <bits/types/struct_iovec.h>
Andrew Jeffery4e1ba8a2023-06-29 10:48:33 +09307#include <fcntl.h>
Rashmica Guptac1b66f42022-12-09 16:24:45 +11008#include <stdbool.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +09309#include <stdlib.h>
Manojkiran Eda9a8e4972022-11-28 16:38:21 +053010#include <string.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +093011#include <sys/socket.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +093012#include <sys/un.h>
13#include <unistd.h>
14
Rashmica Guptac1b66f42022-12-09 16:24:45 +110015/* Temporary for old api */
16#include "libpldm/transport/mctp-demux.h"
17extern int
18pldm_transport_mctp_demux_get_socket_fd(struct pldm_transport_mctp_demux *ctx);
19extern struct pldm_transport_mctp_demux *
20pldm_transport_mctp_demux_init_with_fd(int mctp_fd);
21
22/* --- old APIS written in terms of the new API -- */
23/*
24 * pldm_open returns the file descriptor to the MCTP socket, which needs to
25 * persist over api calls (so a consumer can poll it for incoming messages).
26 * So we need a global variable to store the transport struct
27 */
28static struct pldm_transport_mctp_demux *open_transport;
Andrew Jeffery9c766792022-08-10 23:12:49 +093029
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093030LIBPLDM_ABI_DEPRECATED
Andrew Jeffery319304f2023-04-05 13:53:18 +093031pldm_requester_rc_t pldm_open(void)
Andrew Jeffery9c766792022-08-10 23:12:49 +093032{
Andrew Jeffery4e1ba8a2023-06-29 10:48:33 +093033 int fd = PLDM_REQUESTER_OPEN_FAIL;
Andrew Jeffery9c766792022-08-10 23:12:49 +093034
Rashmica Guptac1b66f42022-12-09 16:24:45 +110035 if (open_transport) {
Rashmica Gupta39f88322023-05-12 15:54:12 +100036 fd = pldm_transport_mctp_demux_get_socket_fd(open_transport);
Andrew Jeffery4e1ba8a2023-06-29 10:48:33 +093037
38 /* If someone has externally issued close() on fd then we need to start again. Use
39 * `fcntl(..., F_GETFD)` to test whether fd is valid. */
40 if (fd < 0 || fcntl(fd, F_GETFD) < 0) {
41 pldm_close();
42 }
Andrew Jeffery9c766792022-08-10 23:12:49 +093043 }
44
Andrew Jeffery4e1ba8a2023-06-29 10:48:33 +093045 /* We retest open_transport as it may have been set to NULL by pldm_close() above. */
46 if (!open_transport) {
47 struct pldm_transport_mctp_demux *demux = NULL;
48
49 if (pldm_transport_mctp_demux_init(&demux) < 0) {
50 return PLDM_REQUESTER_OPEN_FAIL;
51 }
52
53 open_transport = demux;
54
55 fd = pldm_transport_mctp_demux_get_socket_fd(open_transport);
Andrew Jeffery9c766792022-08-10 23:12:49 +093056 }
Rashmica Guptac1b66f42022-12-09 16:24:45 +110057
Andrew Jeffery9c766792022-08-10 23:12:49 +093058 return fd;
59}
60
Rashmica Guptac1b66f42022-12-09 16:24:45 +110061/* This macro does the setup and teardown required for the old API to use the
62 * new API. Since the setup/teardown logic is the same for all four send/recv
63 * functions, it makes sense to only define it once. */
Rashmica Gupta0411b712023-05-30 16:43:08 +100064#define PLDM_REQ_FN(eid, fd, fn, rc, ...) \
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093065 do { \
66 struct pldm_transport_mctp_demux *demux; \
67 bool using_open_transport = false; \
Rashmica Guptad10c6b02023-07-24 13:09:48 +100068 pldm_tid_t tid = eid; \
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093069 struct pldm_transport *ctx; \
Rashmica Guptac1b66f42022-12-09 16:24:45 +110070 /* The fd can be for a socket we opened or one the consumer \
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093071 * opened. */ \
72 if (open_transport && \
73 mctp_fd == pldm_transport_mctp_demux_get_socket_fd( \
74 open_transport)) { \
75 using_open_transport = true; \
76 demux = open_transport; \
77 } else { \
78 demux = pldm_transport_mctp_demux_init_with_fd(fd); \
79 if (!demux) { \
80 rc = PLDM_REQUESTER_OPEN_FAIL; \
81 goto transport_out; \
82 } \
83 } \
84 ctx = pldm_transport_mctp_demux_core(demux); \
85 rc = pldm_transport_mctp_demux_map_tid(demux, tid, eid); \
86 if (rc) { \
87 rc = PLDM_REQUESTER_OPEN_FAIL; \
88 goto transport_out; \
89 } \
90 rc = fn(ctx, tid, __VA_ARGS__); \
91 transport_out: \
92 if (!using_open_transport) { \
93 pldm_transport_mctp_demux_destroy(demux); \
94 } \
Rashmica Gupta0411b712023-05-30 16:43:08 +100095 break; \
Rashmica Guptac1b66f42022-12-09 16:24:45 +110096 } while (0)
Andrew Jeffery9c766792022-08-10 23:12:49 +093097
Andrew Jeffery0a6d6822023-08-22 21:40:32 +093098LIBPLDM_ABI_DEPRECATED
Andrew Jeffery9c766792022-08-10 23:12:49 +093099pldm_requester_rc_t pldm_recv_any(mctp_eid_t eid, int mctp_fd,
100 uint8_t **pldm_resp_msg, size_t *resp_msg_len)
101{
Rashmica Gupta0411b712023-05-30 16:43:08 +1000102 pldm_requester_rc_t rc = 0;
Rashmica Gupta24576292023-07-31 14:02:41 +1000103
104 struct pldm_transport_mctp_demux *demux;
105 bool using_open_transport = false;
106 pldm_tid_t tid = eid;
107 struct pldm_transport *ctx;
108 /* The fd can be for a socket we opened or one the consumer
109 * opened. */
110 if (open_transport &&
111 mctp_fd ==
112 pldm_transport_mctp_demux_get_socket_fd(open_transport)) {
113 using_open_transport = true;
114 demux = open_transport;
115 } else {
116 demux = pldm_transport_mctp_demux_init_with_fd(mctp_fd);
117 if (!demux) {
118 rc = PLDM_REQUESTER_OPEN_FAIL;
119 goto transport_out;
120 }
121 }
122 ctx = pldm_transport_mctp_demux_core(demux);
123 rc = pldm_transport_mctp_demux_map_tid(demux, tid, eid);
124 if (rc) {
125 rc = PLDM_REQUESTER_OPEN_FAIL;
126 goto transport_out;
127 }
128 /* TODO this is the only change, can we work this into the macro? */
129 rc = pldm_transport_recv_msg(ctx, &tid, (void **)pldm_resp_msg,
130 resp_msg_len);
131
Rashmica Gupta0411b712023-05-30 16:43:08 +1000132 struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)(*pldm_resp_msg);
133 if (rc != PLDM_REQUESTER_SUCCESS) {
134 return rc;
135 }
136 if (hdr && (hdr->request || hdr->datagram)) {
137 free(*pldm_resp_msg);
138 *pldm_resp_msg = NULL;
139 return PLDM_REQUESTER_NOT_RESP_MSG;
140 }
141 uint8_t pldm_cc = 0;
142 if (*resp_msg_len < (sizeof(struct pldm_msg_hdr) + sizeof(pldm_cc))) {
143 free(*pldm_resp_msg);
144 *pldm_resp_msg = NULL;
145 return PLDM_REQUESTER_RESP_MSG_TOO_SMALL;
146 }
Rashmica Gupta24576292023-07-31 14:02:41 +1000147
148transport_out:
149 if (!using_open_transport) {
150 pldm_transport_mctp_demux_destroy(demux);
151 }
152
Rashmica Gupta0411b712023-05-30 16:43:08 +1000153 return rc;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930154}
155
Andrew Jeffery0a6d6822023-08-22 21:40:32 +0930156LIBPLDM_ABI_DEPRECATED
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100157pldm_requester_rc_t pldm_recv(mctp_eid_t eid, int mctp_fd,
158 __attribute__((unused)) uint8_t instance_id,
Andrew Jeffery9c766792022-08-10 23:12:49 +0930159 uint8_t **pldm_resp_msg, size_t *resp_msg_len)
160{
161 pldm_requester_rc_t rc =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930162 pldm_recv_any(eid, mctp_fd, pldm_resp_msg, resp_msg_len);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930163 struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)(*pldm_resp_msg);
Rashmica Guptaa3035932023-06-17 12:52:51 +1000164 if (rc == PLDM_REQUESTER_SUCCESS && hdr &&
165 hdr->instance_id != instance_id) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930166 free(*pldm_resp_msg);
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100167 *pldm_resp_msg = NULL;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930168 return PLDM_REQUESTER_INSTANCE_ID_MISMATCH;
169 }
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100170 return rc;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930171}
172
Andrew Jeffery0a6d6822023-08-22 21:40:32 +0930173LIBPLDM_ABI_DEPRECATED
Andrew Jeffery9c766792022-08-10 23:12:49 +0930174pldm_requester_rc_t pldm_send_recv(mctp_eid_t eid, int mctp_fd,
175 const uint8_t *pldm_req_msg,
176 size_t req_msg_len, uint8_t **pldm_resp_msg,
177 size_t *resp_msg_len)
178{
Rashmica Gupta0411b712023-05-30 16:43:08 +1000179 pldm_requester_rc_t rc = 0;
180 struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)pldm_req_msg;
181 if (hdr && !hdr->request) {
182 return PLDM_REQUESTER_NOT_REQ_MSG;
183 }
184 PLDM_REQ_FN(eid, mctp_fd, pldm_transport_send_recv_msg, rc,
185 pldm_req_msg, req_msg_len, (void **)pldm_resp_msg,
186 resp_msg_len);
187 if (rc != PLDM_REQUESTER_SUCCESS) {
188 return rc;
189 }
Thu Nguyen43a79852023-07-17 16:22:11 +0700190 hdr = (struct pldm_msg_hdr *)(*pldm_resp_msg);
Rashmica Gupta0411b712023-05-30 16:43:08 +1000191 if (hdr && (hdr->request || hdr->datagram)) {
192 free(*pldm_resp_msg);
193 *pldm_resp_msg = NULL;
194 return PLDM_REQUESTER_NOT_RESP_MSG;
195 }
196 return rc;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930197}
198
Andrew Jeffery0a6d6822023-08-22 21:40:32 +0930199LIBPLDM_ABI_DEPRECATED
Andrew Jeffery9c766792022-08-10 23:12:49 +0930200pldm_requester_rc_t pldm_send(mctp_eid_t eid, int mctp_fd,
201 const uint8_t *pldm_req_msg, size_t req_msg_len)
202{
Rashmica Gupta0411b712023-05-30 16:43:08 +1000203 pldm_requester_rc_t rc = 0;
204 struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)pldm_req_msg;
205 if (!hdr->request) {
206 return PLDM_REQUESTER_NOT_REQ_MSG;
207 }
208 PLDM_REQ_FN(eid, mctp_fd, pldm_transport_send_msg, rc,
209 (void *)pldm_req_msg, req_msg_len);
210 return rc;
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100211}
Andrew Jeffery9c766792022-08-10 23:12:49 +0930212
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100213/* Adding this here for completeness in the case we can't smoothly
214 * transition apps over to the new api */
Andrew Jeffery0a6d6822023-08-22 21:40:32 +0930215LIBPLDM_ABI_DEPRECATED
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930216void pldm_close(void)
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100217{
218 if (open_transport) {
219 pldm_transport_mctp_demux_destroy(open_transport);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930220 }
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100221 open_transport = NULL;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930222}