-
Notifications
You must be signed in to change notification settings - Fork 8
/
pldm.c
222 lines (201 loc) · 7.37 KB
/
pldm.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
#include <libpldm/base.h>
#include <libpldm/pldm.h>
#include <libpldm/transport.h>
#include <bits/types/struct_iovec.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
/* Temporary for old api */
#include <libpldm/transport/mctp-demux.h>
extern int
pldm_transport_mctp_demux_get_socket_fd(struct pldm_transport_mctp_demux *ctx);
extern struct pldm_transport_mctp_demux *
pldm_transport_mctp_demux_init_with_fd(int mctp_fd);
/* --- old APIS written in terms of the new API -- */
/*
* pldm_open returns the file descriptor to the MCTP socket, which needs to
* persist over api calls (so a consumer can poll it for incoming messages).
* So we need a global variable to store the transport struct
*/
static struct pldm_transport_mctp_demux *open_transport;
LIBPLDM_ABI_DEPRECATED
pldm_requester_rc_t pldm_open(void)
{
int fd = PLDM_REQUESTER_OPEN_FAIL;
if (open_transport) {
fd = pldm_transport_mctp_demux_get_socket_fd(open_transport);
/* If someone has externally issued close() on fd then we need to start again. Use
* `fcntl(..., F_GETFD)` to test whether fd is valid. */
if (fd < 0 || fcntl(fd, F_GETFD) < 0) {
pldm_close();
}
}
/* We retest open_transport as it may have been set to NULL by pldm_close() above. */
if (!open_transport) {
struct pldm_transport_mctp_demux *demux = NULL;
if (pldm_transport_mctp_demux_init(&demux) < 0) {
return PLDM_REQUESTER_OPEN_FAIL;
}
open_transport = demux;
fd = pldm_transport_mctp_demux_get_socket_fd(open_transport);
}
return fd;
}
/* This macro does the setup and teardown required for the old API to use the
* new API. Since the setup/teardown logic is the same for all four send/recv
* functions, it makes sense to only define it once. */
#define PLDM_REQ_FN(eid, fd, fn, rc, ...) \
do { \
struct pldm_transport_mctp_demux *demux; \
bool using_open_transport = false; \
pldm_tid_t tid = eid; \
struct pldm_transport *ctx; \
/* The fd can be for a socket we opened or one the consumer \
* opened. */ \
if (open_transport && \
mctp_fd == pldm_transport_mctp_demux_get_socket_fd( \
open_transport)) { \
using_open_transport = true; \
demux = open_transport; \
} else { \
demux = pldm_transport_mctp_demux_init_with_fd(fd); \
if (!demux) { \
rc = PLDM_REQUESTER_OPEN_FAIL; \
goto transport_out; \
} \
} \
ctx = pldm_transport_mctp_demux_core(demux); \
rc = pldm_transport_mctp_demux_map_tid(demux, tid, eid); \
if (rc) { \
rc = PLDM_REQUESTER_OPEN_FAIL; \
goto transport_out; \
} \
rc = fn(ctx, tid, __VA_ARGS__); \
transport_out: \
if (!using_open_transport) { \
pldm_transport_mctp_demux_destroy(demux); \
} \
break; \
} while (0)
LIBPLDM_ABI_DEPRECATED
pldm_requester_rc_t pldm_recv_any(mctp_eid_t eid, int mctp_fd,
uint8_t **pldm_resp_msg, size_t *resp_msg_len)
{
pldm_requester_rc_t rc = 0;
struct pldm_transport_mctp_demux *demux;
bool using_open_transport = false;
pldm_tid_t tid = eid;
struct pldm_transport *ctx;
/* The fd can be for a socket we opened or one the consumer
* opened. */
if (open_transport &&
mctp_fd ==
pldm_transport_mctp_demux_get_socket_fd(open_transport)) {
using_open_transport = true;
demux = open_transport;
} else {
demux = pldm_transport_mctp_demux_init_with_fd(mctp_fd);
if (!demux) {
rc = PLDM_REQUESTER_OPEN_FAIL;
goto transport_out;
}
}
ctx = pldm_transport_mctp_demux_core(demux);
rc = pldm_transport_mctp_demux_map_tid(demux, tid, eid);
if (rc) {
rc = PLDM_REQUESTER_OPEN_FAIL;
goto transport_out;
}
/* TODO this is the only change, can we work this into the macro? */
rc = pldm_transport_recv_msg(ctx, &tid, (void **)pldm_resp_msg,
resp_msg_len);
struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)(*pldm_resp_msg);
if (rc != PLDM_REQUESTER_SUCCESS) {
return rc;
}
if (hdr && (hdr->request || hdr->datagram)) {
free(*pldm_resp_msg);
*pldm_resp_msg = NULL;
return PLDM_REQUESTER_NOT_RESP_MSG;
}
uint8_t pldm_cc = 0;
if (*resp_msg_len < (sizeof(struct pldm_msg_hdr) + sizeof(pldm_cc))) {
free(*pldm_resp_msg);
*pldm_resp_msg = NULL;
return PLDM_REQUESTER_RESP_MSG_TOO_SMALL;
}
transport_out:
if (!using_open_transport) {
pldm_transport_mctp_demux_destroy(demux);
}
return rc;
}
LIBPLDM_ABI_DEPRECATED
pldm_requester_rc_t pldm_recv(mctp_eid_t eid, int mctp_fd,
__attribute__((unused)) uint8_t instance_id,
uint8_t **pldm_resp_msg, size_t *resp_msg_len)
{
pldm_requester_rc_t rc =
pldm_recv_any(eid, mctp_fd, pldm_resp_msg, resp_msg_len);
struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)(*pldm_resp_msg);
if (rc == PLDM_REQUESTER_SUCCESS && hdr &&
hdr->instance_id != instance_id) {
free(*pldm_resp_msg);
*pldm_resp_msg = NULL;
return PLDM_REQUESTER_INSTANCE_ID_MISMATCH;
}
return rc;
}
LIBPLDM_ABI_DEPRECATED
pldm_requester_rc_t pldm_send_recv(mctp_eid_t eid, int mctp_fd,
const uint8_t *pldm_req_msg,
size_t req_msg_len, uint8_t **pldm_resp_msg,
size_t *resp_msg_len)
{
pldm_requester_rc_t rc = 0;
struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)pldm_req_msg;
if (hdr && !hdr->request) {
return PLDM_REQUESTER_NOT_REQ_MSG;
}
PLDM_REQ_FN(eid, mctp_fd, pldm_transport_send_recv_msg, rc,
pldm_req_msg, req_msg_len, (void **)pldm_resp_msg,
resp_msg_len);
if (rc != PLDM_REQUESTER_SUCCESS) {
return rc;
}
hdr = (struct pldm_msg_hdr *)(*pldm_resp_msg);
if (hdr && (hdr->request || hdr->datagram)) {
free(*pldm_resp_msg);
*pldm_resp_msg = NULL;
return PLDM_REQUESTER_NOT_RESP_MSG;
}
return rc;
}
LIBPLDM_ABI_DEPRECATED
pldm_requester_rc_t pldm_send(mctp_eid_t eid, int mctp_fd,
const uint8_t *pldm_req_msg, size_t req_msg_len)
{
pldm_requester_rc_t rc = 0;
struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)pldm_req_msg;
if (!hdr->request) {
return PLDM_REQUESTER_NOT_REQ_MSG;
}
PLDM_REQ_FN(eid, mctp_fd, pldm_transport_send_msg, rc,
(void *)pldm_req_msg, req_msg_len);
return rc;
}
/* Adding this here for completeness in the case we can't smoothly
* transition apps over to the new api */
LIBPLDM_ABI_DEPRECATED
void pldm_close(void)
{
if (open_transport) {
pldm_transport_mctp_demux_destroy(open_transport);
}
open_transport = NULL;
}