blob: 5297947c5557e8a8c143a25e03993635610f9892 [file] [log] [blame]
Rashmica Guptac1b66f42022-12-09 16:24:45 +11001#include "libpldm/requester/pldm.h"
Andrew Jeffery9c766792022-08-10 23:12:49 +09302#include "base.h"
Rashmica Guptac1b66f42022-12-09 16:24:45 +11003#include "libpldm/transport.h"
Andrew Jeffery9c766792022-08-10 23:12:49 +09304
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05305#include <bits/types/struct_iovec.h>
Andrew Jeffery4e1ba8a2023-06-29 10:48:33 +09306#include <fcntl.h>
Rashmica Guptac1b66f42022-12-09 16:24:45 +11007#include <stdbool.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +09308#include <stdlib.h>
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05309#include <string.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +093010#include <sys/socket.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +093011#include <sys/un.h>
12#include <unistd.h>
13
Rashmica Guptac1b66f42022-12-09 16:24:45 +110014/* Temporary for old api */
15#include "libpldm/transport/mctp-demux.h"
16extern int
17pldm_transport_mctp_demux_get_socket_fd(struct pldm_transport_mctp_demux *ctx);
18extern struct pldm_transport_mctp_demux *
19pldm_transport_mctp_demux_init_with_fd(int mctp_fd);
20
21/* --- old APIS written in terms of the new API -- */
22/*
23 * pldm_open returns the file descriptor to the MCTP socket, which needs to
24 * persist over api calls (so a consumer can poll it for incoming messages).
25 * So we need a global variable to store the transport struct
26 */
27static struct pldm_transport_mctp_demux *open_transport;
Andrew Jeffery9c766792022-08-10 23:12:49 +093028
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093029LIBPLDM_ABI_STABLE
Andrew Jeffery319304f2023-04-05 13:53:18 +093030pldm_requester_rc_t pldm_open(void)
Andrew Jeffery9c766792022-08-10 23:12:49 +093031{
Andrew Jeffery4e1ba8a2023-06-29 10:48:33 +093032 int fd = PLDM_REQUESTER_OPEN_FAIL;
Andrew Jeffery9c766792022-08-10 23:12:49 +093033
Rashmica Guptac1b66f42022-12-09 16:24:45 +110034 if (open_transport) {
Rashmica Gupta39f88322023-05-12 15:54:12 +100035 fd = pldm_transport_mctp_demux_get_socket_fd(open_transport);
Andrew Jeffery4e1ba8a2023-06-29 10:48:33 +093036
37 /* If someone has externally issued close() on fd then we need to start again. Use
38 * `fcntl(..., F_GETFD)` to test whether fd is valid. */
39 if (fd < 0 || fcntl(fd, F_GETFD) < 0) {
40 pldm_close();
41 }
Andrew Jeffery9c766792022-08-10 23:12:49 +093042 }
43
Andrew Jeffery4e1ba8a2023-06-29 10:48:33 +093044 /* We retest open_transport as it may have been set to NULL by pldm_close() above. */
45 if (!open_transport) {
46 struct pldm_transport_mctp_demux *demux = NULL;
47
48 if (pldm_transport_mctp_demux_init(&demux) < 0) {
49 return PLDM_REQUESTER_OPEN_FAIL;
50 }
51
52 open_transport = demux;
53
54 fd = pldm_transport_mctp_demux_get_socket_fd(open_transport);
Andrew Jeffery9c766792022-08-10 23:12:49 +093055 }
Rashmica Guptac1b66f42022-12-09 16:24:45 +110056
Andrew Jeffery9c766792022-08-10 23:12:49 +093057 return fd;
58}
59
Rashmica Guptac1b66f42022-12-09 16:24:45 +110060/* This macro does the setup and teardown required for the old API to use the
61 * new API. Since the setup/teardown logic is the same for all four send/recv
62 * functions, it makes sense to only define it once. */
Rashmica Gupta0411b712023-05-30 16:43:08 +100063#define PLDM_REQ_FN(eid, fd, fn, rc, ...) \
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093064 do { \
65 struct pldm_transport_mctp_demux *demux; \
66 bool using_open_transport = false; \
Rashmica Guptad10c6b02023-07-24 13:09:48 +100067 pldm_tid_t tid = eid; \
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093068 struct pldm_transport *ctx; \
Rashmica Guptac1b66f42022-12-09 16:24:45 +110069 /* The fd can be for a socket we opened or one the consumer \
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093070 * opened. */ \
71 if (open_transport && \
72 mctp_fd == pldm_transport_mctp_demux_get_socket_fd( \
73 open_transport)) { \
74 using_open_transport = true; \
75 demux = open_transport; \
76 } else { \
77 demux = pldm_transport_mctp_demux_init_with_fd(fd); \
78 if (!demux) { \
79 rc = PLDM_REQUESTER_OPEN_FAIL; \
80 goto transport_out; \
81 } \
82 } \
83 ctx = pldm_transport_mctp_demux_core(demux); \
84 rc = pldm_transport_mctp_demux_map_tid(demux, tid, eid); \
85 if (rc) { \
86 rc = PLDM_REQUESTER_OPEN_FAIL; \
87 goto transport_out; \
88 } \
89 rc = fn(ctx, tid, __VA_ARGS__); \
90 transport_out: \
91 if (!using_open_transport) { \
92 pldm_transport_mctp_demux_destroy(demux); \
93 } \
Rashmica Gupta0411b712023-05-30 16:43:08 +100094 break; \
Rashmica Guptac1b66f42022-12-09 16:24:45 +110095 } while (0)
Andrew Jeffery9c766792022-08-10 23:12:49 +093096
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093097LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093098pldm_requester_rc_t pldm_recv_any(mctp_eid_t eid, int mctp_fd,
99 uint8_t **pldm_resp_msg, size_t *resp_msg_len)
100{
Rashmica Gupta0411b712023-05-30 16:43:08 +1000101 pldm_requester_rc_t rc = 0;
Rashmica Gupta24576292023-07-31 14:02:41 +1000102
103 struct pldm_transport_mctp_demux *demux;
104 bool using_open_transport = false;
105 pldm_tid_t tid = eid;
106 struct pldm_transport *ctx;
107 /* The fd can be for a socket we opened or one the consumer
108 * opened. */
109 if (open_transport &&
110 mctp_fd ==
111 pldm_transport_mctp_demux_get_socket_fd(open_transport)) {
112 using_open_transport = true;
113 demux = open_transport;
114 } else {
115 demux = pldm_transport_mctp_demux_init_with_fd(mctp_fd);
116 if (!demux) {
117 rc = PLDM_REQUESTER_OPEN_FAIL;
118 goto transport_out;
119 }
120 }
121 ctx = pldm_transport_mctp_demux_core(demux);
122 rc = pldm_transport_mctp_demux_map_tid(demux, tid, eid);
123 if (rc) {
124 rc = PLDM_REQUESTER_OPEN_FAIL;
125 goto transport_out;
126 }
127 /* TODO this is the only change, can we work this into the macro? */
128 rc = pldm_transport_recv_msg(ctx, &tid, (void **)pldm_resp_msg,
129 resp_msg_len);
130
Rashmica Gupta0411b712023-05-30 16:43:08 +1000131 struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)(*pldm_resp_msg);
132 if (rc != PLDM_REQUESTER_SUCCESS) {
133 return rc;
134 }
135 if (hdr && (hdr->request || hdr->datagram)) {
136 free(*pldm_resp_msg);
137 *pldm_resp_msg = NULL;
138 return PLDM_REQUESTER_NOT_RESP_MSG;
139 }
140 uint8_t pldm_cc = 0;
141 if (*resp_msg_len < (sizeof(struct pldm_msg_hdr) + sizeof(pldm_cc))) {
142 free(*pldm_resp_msg);
143 *pldm_resp_msg = NULL;
144 return PLDM_REQUESTER_RESP_MSG_TOO_SMALL;
145 }
Rashmica Gupta24576292023-07-31 14:02:41 +1000146
147transport_out:
148 if (!using_open_transport) {
149 pldm_transport_mctp_demux_destroy(demux);
150 }
151
Rashmica Gupta0411b712023-05-30 16:43:08 +1000152 return rc;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930153}
154
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930155LIBPLDM_ABI_STABLE
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100156pldm_requester_rc_t pldm_recv(mctp_eid_t eid, int mctp_fd,
157 __attribute__((unused)) uint8_t instance_id,
Andrew Jeffery9c766792022-08-10 23:12:49 +0930158 uint8_t **pldm_resp_msg, size_t *resp_msg_len)
159{
160 pldm_requester_rc_t rc =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930161 pldm_recv_any(eid, mctp_fd, pldm_resp_msg, resp_msg_len);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930162 struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)(*pldm_resp_msg);
Rashmica Guptaa3035932023-06-17 12:52:51 +1000163 if (rc == PLDM_REQUESTER_SUCCESS && hdr &&
164 hdr->instance_id != instance_id) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930165 free(*pldm_resp_msg);
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100166 *pldm_resp_msg = NULL;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930167 return PLDM_REQUESTER_INSTANCE_ID_MISMATCH;
168 }
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100169 return rc;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930170}
171
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930172LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930173pldm_requester_rc_t pldm_send_recv(mctp_eid_t eid, int mctp_fd,
174 const uint8_t *pldm_req_msg,
175 size_t req_msg_len, uint8_t **pldm_resp_msg,
176 size_t *resp_msg_len)
177{
Rashmica Gupta0411b712023-05-30 16:43:08 +1000178 pldm_requester_rc_t rc = 0;
179 struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)pldm_req_msg;
180 if (hdr && !hdr->request) {
181 return PLDM_REQUESTER_NOT_REQ_MSG;
182 }
183 PLDM_REQ_FN(eid, mctp_fd, pldm_transport_send_recv_msg, rc,
184 pldm_req_msg, req_msg_len, (void **)pldm_resp_msg,
185 resp_msg_len);
186 if (rc != PLDM_REQUESTER_SUCCESS) {
187 return rc;
188 }
Thu Nguyen43a79852023-07-17 16:22:11 +0700189 hdr = (struct pldm_msg_hdr *)(*pldm_resp_msg);
Rashmica Gupta0411b712023-05-30 16:43:08 +1000190 if (hdr && (hdr->request || hdr->datagram)) {
191 free(*pldm_resp_msg);
192 *pldm_resp_msg = NULL;
193 return PLDM_REQUESTER_NOT_RESP_MSG;
194 }
195 return rc;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930196}
197
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930198LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930199pldm_requester_rc_t pldm_send(mctp_eid_t eid, int mctp_fd,
200 const uint8_t *pldm_req_msg, size_t req_msg_len)
201{
Rashmica Gupta0411b712023-05-30 16:43:08 +1000202 pldm_requester_rc_t rc = 0;
203 struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)pldm_req_msg;
204 if (!hdr->request) {
205 return PLDM_REQUESTER_NOT_REQ_MSG;
206 }
207 PLDM_REQ_FN(eid, mctp_fd, pldm_transport_send_msg, rc,
208 (void *)pldm_req_msg, req_msg_len);
209 return rc;
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100210}
Andrew Jeffery9c766792022-08-10 23:12:49 +0930211
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100212/* Adding this here for completeness in the case we can't smoothly
213 * transition apps over to the new api */
Andrew Jeffery986df2a2023-06-29 11:15:22 +0930214LIBPLDM_ABI_TESTING
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930215void pldm_close(void)
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100216{
217 if (open_transport) {
218 pldm_transport_mctp_demux_destroy(open_transport);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930219 }
Rashmica Guptac1b66f42022-12-09 16:24:45 +1100220 open_transport = NULL;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930221}