xref: /openbmc/libpldm/src/requester/pldm.c (revision 860a43d996dacf98a94d62fdc7b8484ce04bde23)
1691668feSPatrick Williams /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2*860a43d9SAndrew Jeffery #include "compiler.h"
3b0c1d20aSAndrew Jeffery #include <libpldm/base.h>
4d12dd36eSAndrew Jeffery #include <libpldm/pldm.h>
5b0c1d20aSAndrew Jeffery #include <libpldm/transport.h>
69c766792SAndrew Jeffery 
79a8e4975SManojkiran Eda #include <bits/types/struct_iovec.h>
84e1ba8a7SAndrew Jeffery #include <fcntl.h>
9c1b66f42SRashmica Gupta #include <stdbool.h>
109c766792SAndrew Jeffery #include <stdlib.h>
119a8e4975SManojkiran Eda #include <string.h>
129c766792SAndrew Jeffery #include <sys/socket.h>
139c766792SAndrew Jeffery #include <sys/un.h>
149c766792SAndrew Jeffery #include <unistd.h>
159c766792SAndrew Jeffery 
16c1b66f42SRashmica Gupta /* Temporary for old api */
17efb40069SAndrew Jeffery #include <libpldm/transport/mctp-demux.h>
18c1b66f42SRashmica Gupta extern int
19c1b66f42SRashmica Gupta pldm_transport_mctp_demux_get_socket_fd(struct pldm_transport_mctp_demux *ctx);
20c1b66f42SRashmica Gupta extern struct pldm_transport_mctp_demux *
21c1b66f42SRashmica Gupta pldm_transport_mctp_demux_init_with_fd(int mctp_fd);
22c1b66f42SRashmica Gupta 
23c1b66f42SRashmica Gupta /* ---  old APIS written in terms of the new API -- */
24c1b66f42SRashmica Gupta /*
25c1b66f42SRashmica Gupta  * pldm_open returns the file descriptor to the MCTP socket, which needs to
26c1b66f42SRashmica Gupta  * persist over api calls (so a consumer can poll it for incoming messages).
27c1b66f42SRashmica Gupta  * So we need a global variable to store the transport struct
28c1b66f42SRashmica Gupta  */
29c1b66f42SRashmica Gupta static struct pldm_transport_mctp_demux *open_transport;
309c766792SAndrew Jeffery 
310a6d6821SAndrew Jeffery LIBPLDM_ABI_DEPRECATED
pldm_open(void)32319304fdSAndrew Jeffery pldm_requester_rc_t pldm_open(void)
339c766792SAndrew Jeffery {
344e1ba8a7SAndrew Jeffery 	int fd = PLDM_REQUESTER_OPEN_FAIL;
359c766792SAndrew Jeffery 
36c1b66f42SRashmica Gupta 	if (open_transport) {
3739f88325SRashmica Gupta 		fd = pldm_transport_mctp_demux_get_socket_fd(open_transport);
384e1ba8a7SAndrew Jeffery 
394e1ba8a7SAndrew Jeffery 		/* If someone has externally issued close() on fd then we need to start again. Use
404e1ba8a7SAndrew Jeffery 		 * `fcntl(..., F_GETFD)` to test whether fd is valid. */
414e1ba8a7SAndrew Jeffery 		if (fd < 0 || fcntl(fd, F_GETFD) < 0) {
424e1ba8a7SAndrew Jeffery 			pldm_close();
434e1ba8a7SAndrew Jeffery 		}
449c766792SAndrew Jeffery 	}
459c766792SAndrew Jeffery 
464e1ba8a7SAndrew Jeffery 	/* We retest open_transport as it may have been set to NULL by pldm_close() above. */
474e1ba8a7SAndrew Jeffery 	if (!open_transport) {
48c1b66f42SRashmica Gupta 		struct pldm_transport_mctp_demux *demux = NULL;
49c1b66f42SRashmica Gupta 
504e1ba8a7SAndrew Jeffery 		if (pldm_transport_mctp_demux_init(&demux) < 0) {
514e1ba8a7SAndrew Jeffery 			return PLDM_REQUESTER_OPEN_FAIL;
524e1ba8a7SAndrew Jeffery 		}
53c1b66f42SRashmica Gupta 
54c1b66f42SRashmica Gupta 		open_transport = demux;
559c766792SAndrew Jeffery 
564e1ba8a7SAndrew Jeffery 		fd = pldm_transport_mctp_demux_get_socket_fd(open_transport);
574e1ba8a7SAndrew Jeffery 	}
584e1ba8a7SAndrew Jeffery 
599c766792SAndrew Jeffery 	return fd;
609c766792SAndrew Jeffery }
619c766792SAndrew Jeffery 
62c1b66f42SRashmica Gupta /* This macro does the setup and teardown required for the old API to use the
63c1b66f42SRashmica Gupta  * new API. Since the setup/teardown logic is the same for all four send/recv
64c1b66f42SRashmica Gupta  * functions, it makes sense to only define it once. */
650411b712SRashmica Gupta #define PLDM_REQ_FN(eid, fd, fn, rc, ...)                                        \
66c1b66f42SRashmica Gupta 	do {                                                                     \
67c1b66f42SRashmica Gupta 		struct pldm_transport_mctp_demux *demux;                         \
68c1b66f42SRashmica Gupta 		bool using_open_transport = false;                               \
69d10c6b0cSRashmica Gupta 		pldm_tid_t tid = eid;                                            \
70c1b66f42SRashmica Gupta 		struct pldm_transport *ctx;                                      \
71c1b66f42SRashmica Gupta 		/* The fd can be for a socket we opened or one the consumer    \
72c1b66f42SRashmica Gupta 		 * opened. */ \
73c1b66f42SRashmica Gupta 		if (open_transport &&                                            \
74c1b66f42SRashmica Gupta 		    mctp_fd == pldm_transport_mctp_demux_get_socket_fd(          \
75c1b66f42SRashmica Gupta 				       open_transport)) {                        \
76c1b66f42SRashmica Gupta 			using_open_transport = true;                             \
77c1b66f42SRashmica Gupta 			demux = open_transport;                                  \
78c1b66f42SRashmica Gupta 		} else {                                                         \
79c1b66f42SRashmica Gupta 			demux = pldm_transport_mctp_demux_init_with_fd(fd);      \
80c1b66f42SRashmica Gupta 			if (!demux) {                                            \
81c1b66f42SRashmica Gupta 				rc = PLDM_REQUESTER_OPEN_FAIL;                   \
82c1b66f42SRashmica Gupta 				goto transport_out;                              \
83c1b66f42SRashmica Gupta 			}                                                        \
84c1b66f42SRashmica Gupta 		}                                                                \
85c1b66f42SRashmica Gupta 		ctx = pldm_transport_mctp_demux_core(demux);                     \
86c1b66f42SRashmica Gupta 		rc = pldm_transport_mctp_demux_map_tid(demux, tid, eid);         \
87c1b66f42SRashmica Gupta 		if (rc) {                                                        \
88c1b66f42SRashmica Gupta 			rc = PLDM_REQUESTER_OPEN_FAIL;                           \
89c1b66f42SRashmica Gupta 			goto transport_out;                                      \
90c1b66f42SRashmica Gupta 		}                                                                \
91c1b66f42SRashmica Gupta 		rc = fn(ctx, tid, __VA_ARGS__);                                  \
92c1b66f42SRashmica Gupta 	transport_out:                                                           \
93c1b66f42SRashmica Gupta 		if (!using_open_transport) {                                     \
94c1b66f42SRashmica Gupta 			pldm_transport_mctp_demux_destroy(demux);                \
95c1b66f42SRashmica Gupta 		}                                                                \
960411b712SRashmica Gupta 		break;                                                           \
97c1b66f42SRashmica Gupta 	} while (0)
989c766792SAndrew Jeffery 
990a6d6821SAndrew Jeffery LIBPLDM_ABI_DEPRECATED
pldm_recv_any(mctp_eid_t eid,int mctp_fd,uint8_t ** pldm_resp_msg,size_t * resp_msg_len)1009c766792SAndrew Jeffery pldm_requester_rc_t pldm_recv_any(mctp_eid_t eid, int mctp_fd,
1019c766792SAndrew Jeffery 				  uint8_t **pldm_resp_msg, size_t *resp_msg_len)
1029c766792SAndrew Jeffery {
1030411b712SRashmica Gupta 	pldm_requester_rc_t rc = 0;
10424576290SRashmica Gupta 
10524576290SRashmica Gupta 	struct pldm_transport_mctp_demux *demux;
10624576290SRashmica Gupta 	bool using_open_transport = false;
10724576290SRashmica Gupta 	pldm_tid_t tid = eid;
10824576290SRashmica Gupta 	struct pldm_transport *ctx;
10924576290SRashmica Gupta 	/* The fd can be for a socket we opened or one the consumer
11024576290SRashmica Gupta 	 * opened. */
11124576290SRashmica Gupta 	if (open_transport &&
11224576290SRashmica Gupta 	    mctp_fd ==
11324576290SRashmica Gupta 		    pldm_transport_mctp_demux_get_socket_fd(open_transport)) {
11424576290SRashmica Gupta 		using_open_transport = true;
11524576290SRashmica Gupta 		demux = open_transport;
11624576290SRashmica Gupta 	} else {
11724576290SRashmica Gupta 		demux = pldm_transport_mctp_demux_init_with_fd(mctp_fd);
11824576290SRashmica Gupta 		if (!demux) {
11924576290SRashmica Gupta 			rc = PLDM_REQUESTER_OPEN_FAIL;
12024576290SRashmica Gupta 			goto transport_out;
12124576290SRashmica Gupta 		}
12224576290SRashmica Gupta 	}
12324576290SRashmica Gupta 	ctx = pldm_transport_mctp_demux_core(demux);
12424576290SRashmica Gupta 	rc = pldm_transport_mctp_demux_map_tid(demux, tid, eid);
12524576290SRashmica Gupta 	if (rc) {
12624576290SRashmica Gupta 		rc = PLDM_REQUESTER_OPEN_FAIL;
12724576290SRashmica Gupta 		goto transport_out;
12824576290SRashmica Gupta 	}
12924576290SRashmica Gupta 	/* TODO this is the only change, can we work this into the macro? */
13024576290SRashmica Gupta 	rc = pldm_transport_recv_msg(ctx, &tid, (void **)pldm_resp_msg,
13124576290SRashmica Gupta 				     resp_msg_len);
13224576290SRashmica Gupta 
1330411b712SRashmica Gupta 	struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)(*pldm_resp_msg);
1340411b712SRashmica Gupta 	if (rc != PLDM_REQUESTER_SUCCESS) {
1350411b712SRashmica Gupta 		return rc;
1360411b712SRashmica Gupta 	}
1370411b712SRashmica Gupta 	if (hdr && (hdr->request || hdr->datagram)) {
1380411b712SRashmica Gupta 		free(*pldm_resp_msg);
1390411b712SRashmica Gupta 		*pldm_resp_msg = NULL;
1400411b712SRashmica Gupta 		return PLDM_REQUESTER_NOT_RESP_MSG;
1410411b712SRashmica Gupta 	}
1420411b712SRashmica Gupta 	uint8_t pldm_cc = 0;
1430411b712SRashmica Gupta 	if (*resp_msg_len < (sizeof(struct pldm_msg_hdr) + sizeof(pldm_cc))) {
1440411b712SRashmica Gupta 		free(*pldm_resp_msg);
1450411b712SRashmica Gupta 		*pldm_resp_msg = NULL;
1460411b712SRashmica Gupta 		return PLDM_REQUESTER_RESP_MSG_TOO_SMALL;
1470411b712SRashmica Gupta 	}
14824576290SRashmica Gupta 
14924576290SRashmica Gupta transport_out:
15024576290SRashmica Gupta 	if (!using_open_transport) {
15124576290SRashmica Gupta 		pldm_transport_mctp_demux_destroy(demux);
15224576290SRashmica Gupta 	}
15324576290SRashmica Gupta 
1540411b712SRashmica Gupta 	return rc;
1559c766792SAndrew Jeffery }
1569c766792SAndrew Jeffery 
1570a6d6821SAndrew Jeffery LIBPLDM_ABI_DEPRECATED
pldm_recv(mctp_eid_t eid,int mctp_fd,LIBPLDM_CC_UNUSED uint8_t instance_id,uint8_t ** pldm_resp_msg,size_t * resp_msg_len)158c1b66f42SRashmica Gupta pldm_requester_rc_t pldm_recv(mctp_eid_t eid, int mctp_fd,
159*860a43d9SAndrew Jeffery 			      LIBPLDM_CC_UNUSED uint8_t instance_id,
1609c766792SAndrew Jeffery 			      uint8_t **pldm_resp_msg, size_t *resp_msg_len)
1619c766792SAndrew Jeffery {
1629c766792SAndrew Jeffery 	pldm_requester_rc_t rc =
1639c766792SAndrew Jeffery 		pldm_recv_any(eid, mctp_fd, pldm_resp_msg, resp_msg_len);
1649c766792SAndrew Jeffery 	struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)(*pldm_resp_msg);
165a3035938SRashmica Gupta 	if (rc == PLDM_REQUESTER_SUCCESS && hdr &&
166a3035938SRashmica Gupta 	    hdr->instance_id != instance_id) {
1679c766792SAndrew Jeffery 		free(*pldm_resp_msg);
168c1b66f42SRashmica Gupta 		*pldm_resp_msg = NULL;
1699c766792SAndrew Jeffery 		return PLDM_REQUESTER_INSTANCE_ID_MISMATCH;
1709c766792SAndrew Jeffery 	}
171c1b66f42SRashmica Gupta 	return rc;
1729c766792SAndrew Jeffery }
1739c766792SAndrew Jeffery 
1740a6d6821SAndrew Jeffery LIBPLDM_ABI_DEPRECATED
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)1759c766792SAndrew Jeffery pldm_requester_rc_t pldm_send_recv(mctp_eid_t eid, int mctp_fd,
1769c766792SAndrew Jeffery 				   const uint8_t *pldm_req_msg,
1779c766792SAndrew Jeffery 				   size_t req_msg_len, uint8_t **pldm_resp_msg,
1789c766792SAndrew Jeffery 				   size_t *resp_msg_len)
1799c766792SAndrew Jeffery {
1800411b712SRashmica Gupta 	pldm_requester_rc_t rc = 0;
1810411b712SRashmica Gupta 	struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)pldm_req_msg;
1820411b712SRashmica Gupta 	if (hdr && !hdr->request) {
1830411b712SRashmica Gupta 		return PLDM_REQUESTER_NOT_REQ_MSG;
1840411b712SRashmica Gupta 	}
1850411b712SRashmica Gupta 	PLDM_REQ_FN(eid, mctp_fd, pldm_transport_send_recv_msg, rc,
1860411b712SRashmica Gupta 		    pldm_req_msg, req_msg_len, (void **)pldm_resp_msg,
1870411b712SRashmica Gupta 		    resp_msg_len);
1880411b712SRashmica Gupta 	if (rc != PLDM_REQUESTER_SUCCESS) {
1890411b712SRashmica Gupta 		return rc;
1900411b712SRashmica Gupta 	}
19143a7985dSThu Nguyen 	hdr = (struct pldm_msg_hdr *)(*pldm_resp_msg);
1920411b712SRashmica Gupta 	if (hdr && (hdr->request || hdr->datagram)) {
1930411b712SRashmica Gupta 		free(*pldm_resp_msg);
1940411b712SRashmica Gupta 		*pldm_resp_msg = NULL;
1950411b712SRashmica Gupta 		return PLDM_REQUESTER_NOT_RESP_MSG;
1960411b712SRashmica Gupta 	}
1970411b712SRashmica Gupta 	return rc;
1989c766792SAndrew Jeffery }
1999c766792SAndrew Jeffery 
2000a6d6821SAndrew Jeffery LIBPLDM_ABI_DEPRECATED
pldm_send(mctp_eid_t eid,int mctp_fd,const uint8_t * pldm_req_msg,size_t req_msg_len)2019c766792SAndrew Jeffery pldm_requester_rc_t pldm_send(mctp_eid_t eid, int mctp_fd,
2029c766792SAndrew Jeffery 			      const uint8_t *pldm_req_msg, size_t req_msg_len)
2039c766792SAndrew Jeffery {
2040411b712SRashmica Gupta 	pldm_requester_rc_t rc = 0;
2050411b712SRashmica Gupta 	struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)pldm_req_msg;
2060411b712SRashmica Gupta 	if (!hdr->request) {
2070411b712SRashmica Gupta 		return PLDM_REQUESTER_NOT_REQ_MSG;
2080411b712SRashmica Gupta 	}
2090411b712SRashmica Gupta 	PLDM_REQ_FN(eid, mctp_fd, pldm_transport_send_msg, rc,
2100411b712SRashmica Gupta 		    (void *)pldm_req_msg, req_msg_len);
2110411b712SRashmica Gupta 	return rc;
2129c766792SAndrew Jeffery }
213c1b66f42SRashmica Gupta 
214c1b66f42SRashmica Gupta /* Adding this here for completeness in the case we can't smoothly
215c1b66f42SRashmica Gupta  * transition apps over to the new api */
2160a6d6821SAndrew Jeffery LIBPLDM_ABI_DEPRECATED
pldm_close(void)21737dd6a3dSAndrew Jeffery void pldm_close(void)
218c1b66f42SRashmica Gupta {
219c1b66f42SRashmica Gupta 	if (open_transport) {
220c1b66f42SRashmica Gupta 		pldm_transport_mctp_demux_destroy(open_transport);
221c1b66f42SRashmica Gupta 	}
222c1b66f42SRashmica Gupta 	open_transport = NULL;
2239c766792SAndrew Jeffery }
224