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