1 #include "config.h" 2 #include "mctp-defines.h" 3 #include "base.h" 4 #include "container-of.h" 5 #include "libpldm/pldm.h" 6 #include "libpldm/transport.h" 7 #include "transport.h" 8 9 #include <errno.h> 10 #include <linux/mctp.h> 11 #include <poll.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <sys/socket.h> 15 #include <sys/types.h> 16 #include <sys/un.h> 17 #include <unistd.h> 18 19 #define AF_MCTP_NAME "AF_MCTP" 20 struct pldm_transport_af_mctp { 21 struct pldm_transport transport; 22 int socket; 23 pldm_tid_t tid_eid_map[MCTP_MAX_NUM_EID]; 24 }; 25 26 #define transport_to_af_mctp(ptr) \ 27 container_of(ptr, struct pldm_transport_af_mctp, transport) 28 29 LIBPLDM_ABI_TESTING 30 struct pldm_transport * 31 pldm_transport_af_mctp_core(struct pldm_transport_af_mctp *ctx) 32 { 33 return &ctx->transport; 34 } 35 36 LIBPLDM_ABI_TESTING 37 int pldm_transport_af_mctp_init_pollfd(struct pldm_transport *t, 38 struct pollfd *pollfd) 39 { 40 struct pldm_transport_af_mctp *ctx = transport_to_af_mctp(t); 41 pollfd->fd = ctx->socket; 42 pollfd->events = POLLIN; 43 return 0; 44 } 45 46 static int pldm_transport_af_mctp_get_eid(struct pldm_transport_af_mctp *ctx, 47 pldm_tid_t tid, mctp_eid_t *eid) 48 { 49 int i; 50 for (i = 0; i < MCTP_MAX_NUM_EID; i++) { 51 if (ctx->tid_eid_map[i] == tid) { 52 *eid = i; 53 return 0; 54 } 55 } 56 *eid = -1; 57 return -1; 58 } 59 60 LIBPLDM_ABI_TESTING 61 int pldm_transport_af_mctp_map_tid(struct pldm_transport_af_mctp *ctx, 62 pldm_tid_t tid, mctp_eid_t eid) 63 { 64 ctx->tid_eid_map[eid] = tid; 65 66 return 0; 67 } 68 69 LIBPLDM_ABI_TESTING 70 int pldm_transport_af_mctp_unmap_tid(struct pldm_transport_af_mctp *ctx, 71 __attribute__((unused)) pldm_tid_t tid, 72 mctp_eid_t eid) 73 { 74 ctx->tid_eid_map[eid] = 0; 75 76 return 0; 77 } 78 79 static pldm_requester_rc_t pldm_transport_af_mctp_recv(struct pldm_transport *t, 80 pldm_tid_t tid, 81 void **pldm_resp_msg, 82 size_t *resp_msg_len) 83 { 84 struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t); 85 mctp_eid_t eid = 0; 86 int rc = pldm_transport_af_mctp_get_eid(af_mctp, tid, &eid); 87 if (rc) { 88 return PLDM_REQUESTER_RECV_FAIL; 89 } 90 91 ssize_t length = recv(af_mctp->socket, NULL, 0, MSG_PEEK | MSG_TRUNC); 92 if (length <= 0) { 93 return PLDM_REQUESTER_RECV_FAIL; 94 } 95 *pldm_resp_msg = malloc(length); 96 length = recv(af_mctp->socket, *pldm_resp_msg, length, MSG_TRUNC); 97 if (length < (ssize_t)sizeof(struct pldm_msg_hdr)) { 98 free(*pldm_resp_msg); 99 return PLDM_REQUESTER_INVALID_RECV_LEN; 100 } 101 *resp_msg_len = length; 102 return PLDM_REQUESTER_SUCCESS; 103 } 104 105 static pldm_requester_rc_t pldm_transport_af_mctp_send(struct pldm_transport *t, 106 pldm_tid_t tid, 107 const void *pldm_req_msg, 108 size_t req_msg_len) 109 { 110 struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t); 111 mctp_eid_t eid = 0; 112 if (pldm_transport_af_mctp_get_eid(af_mctp, tid, &eid)) { 113 return PLDM_REQUESTER_SEND_FAIL; 114 } 115 116 struct sockaddr_mctp addr = { 0 }; 117 addr.smctp_family = AF_MCTP; 118 addr.smctp_addr.s_addr = eid; 119 addr.smctp_type = MCTP_MSG_TYPE_PLDM; 120 addr.smctp_tag = MCTP_TAG_OWNER; 121 122 ssize_t rc = sendto(af_mctp->socket, pldm_req_msg, req_msg_len, 0, 123 (struct sockaddr *)&addr, sizeof(addr)); 124 if (rc == -1) { 125 return PLDM_REQUESTER_SEND_FAIL; 126 } 127 return PLDM_REQUESTER_SUCCESS; 128 } 129 130 LIBPLDM_ABI_TESTING 131 int pldm_transport_af_mctp_init(struct pldm_transport_af_mctp **ctx) 132 { 133 if (!ctx || *ctx) { 134 return -EINVAL; 135 } 136 137 struct pldm_transport_af_mctp *af_mctp = 138 calloc(1, sizeof(struct pldm_transport_af_mctp)); 139 if (!af_mctp) { 140 return -ENOMEM; 141 } 142 143 af_mctp->transport.name = AF_MCTP_NAME; 144 af_mctp->transport.version = 1; 145 af_mctp->transport.recv = pldm_transport_af_mctp_recv; 146 af_mctp->transport.send = pldm_transport_af_mctp_send; 147 af_mctp->socket = socket(AF_MCTP, SOCK_DGRAM, 0); 148 if (af_mctp->socket == -1) { 149 free(af_mctp); 150 return -1; 151 } 152 *ctx = af_mctp; 153 return 0; 154 } 155 156 LIBPLDM_ABI_TESTING 157 void pldm_transport_af_mctp_destroy(struct pldm_transport_af_mctp *ctx) 158 { 159 if (!ctx) { 160 return; 161 } 162 close(ctx->socket); 163 free(ctx); 164 } 165