1 #include "libpldm/requester/pldm.h" 2 #include "base.h" 3 #include "libpldm/transport.h" 4 5 #include <bits/types/struct_iovec.h> 6 #include <stdbool.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <sys/socket.h> 10 #include <sys/un.h> 11 #include <unistd.h> 12 13 /* Temporary for old api */ 14 #include "libpldm/transport/mctp-demux.h" 15 extern int 16 pldm_transport_mctp_demux_get_socket_fd(struct pldm_transport_mctp_demux *ctx); 17 extern struct pldm_transport_mctp_demux * 18 pldm_transport_mctp_demux_init_with_fd(int mctp_fd); 19 20 /* --- old APIS written in terms of the new API -- */ 21 /* 22 * pldm_open returns the file descriptor to the MCTP socket, which needs to 23 * persist over api calls (so a consumer can poll it for incoming messages). 24 * So we need a global variable to store the transport struct 25 */ 26 static struct pldm_transport_mctp_demux *open_transport; 27 28 pldm_requester_rc_t pldm_open(void) 29 { 30 int fd; 31 int rc; 32 33 if (open_transport) { 34 return -1; 35 } 36 37 struct pldm_transport_mctp_demux *demux = NULL; 38 rc = pldm_transport_mctp_demux_init(&demux); 39 if (rc) { 40 return rc; 41 } 42 43 fd = pldm_transport_mctp_demux_get_socket_fd(demux); 44 45 open_transport = demux; 46 47 return fd; 48 } 49 50 /* This macro does the setup and teardown required for the old API to use the 51 * new API. Since the setup/teardown logic is the same for all four send/recv 52 * functions, it makes sense to only define it once. */ 53 #define PLDM_REQ_FN(eid, fd, fn, ...) \ 54 do { \ 55 struct pldm_transport_mctp_demux *demux; \ 56 bool using_open_transport = false; \ 57 pldm_requester_rc_t rc; \ 58 pldm_tid_t tid = 1; \ 59 struct pldm_transport *ctx; \ 60 /* The fd can be for a socket we opened or one the consumer \ 61 * opened. */ \ 62 if (open_transport && \ 63 mctp_fd == pldm_transport_mctp_demux_get_socket_fd( \ 64 open_transport)) { \ 65 using_open_transport = true; \ 66 demux = open_transport; \ 67 } else { \ 68 demux = pldm_transport_mctp_demux_init_with_fd(fd); \ 69 if (!demux) { \ 70 rc = PLDM_REQUESTER_OPEN_FAIL; \ 71 goto transport_out; \ 72 } \ 73 } \ 74 ctx = pldm_transport_mctp_demux_core(demux); \ 75 rc = pldm_transport_mctp_demux_map_tid(demux, tid, eid); \ 76 if (rc) { \ 77 rc = PLDM_REQUESTER_OPEN_FAIL; \ 78 goto transport_out; \ 79 } \ 80 rc = fn(ctx, tid, __VA_ARGS__); \ 81 transport_out: \ 82 if (!using_open_transport) { \ 83 pldm_transport_mctp_demux_destroy(demux); \ 84 } \ 85 return rc; \ 86 } while (0) 87 88 pldm_requester_rc_t pldm_recv_any(mctp_eid_t eid, int mctp_fd, 89 uint8_t **pldm_resp_msg, size_t *resp_msg_len) 90 { 91 PLDM_REQ_FN(eid, mctp_fd, pldm_transport_recv_msg, 92 (void **)pldm_resp_msg, resp_msg_len); 93 } 94 95 pldm_requester_rc_t pldm_recv(mctp_eid_t eid, int mctp_fd, 96 __attribute__((unused)) uint8_t instance_id, 97 uint8_t **pldm_resp_msg, size_t *resp_msg_len) 98 { 99 pldm_requester_rc_t rc = 100 pldm_recv_any(eid, mctp_fd, pldm_resp_msg, resp_msg_len); 101 struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)(*pldm_resp_msg); 102 if (hdr->instance_id != instance_id) { 103 free(*pldm_resp_msg); 104 *pldm_resp_msg = NULL; 105 return PLDM_REQUESTER_INSTANCE_ID_MISMATCH; 106 } 107 return rc; 108 } 109 110 pldm_requester_rc_t pldm_send_recv(mctp_eid_t eid, int mctp_fd, 111 const uint8_t *pldm_req_msg, 112 size_t req_msg_len, uint8_t **pldm_resp_msg, 113 size_t *resp_msg_len) 114 { 115 PLDM_REQ_FN(eid, mctp_fd, pldm_transport_send_recv_msg, pldm_req_msg, 116 req_msg_len, (void **)pldm_resp_msg, resp_msg_len); 117 } 118 119 pldm_requester_rc_t pldm_send(mctp_eid_t eid, int mctp_fd, 120 const uint8_t *pldm_req_msg, size_t req_msg_len) 121 { 122 PLDM_REQ_FN(eid, mctp_fd, pldm_transport_send_msg, (void *)pldm_req_msg, 123 req_msg_len); 124 } 125 126 /* Adding this here for completeness in the case we can't smoothly 127 * transition apps over to the new api */ 128 void pldm_close() 129 { 130 if (open_transport) { 131 pldm_transport_mctp_demux_destroy(open_transport); 132 } 133 open_transport = NULL; 134 } 135