1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ 2 #include "container-of.h" 3 #include "mctp-defines.h" 4 #include "socket.h" 5 #include "transport.h" 6 7 #include <libpldm/base.h> 8 #include <libpldm/pldm.h> 9 #include <libpldm/transport.h> 10 #include <libpldm/transport/mctp-demux.h> 11 12 #include <errno.h> 13 #include <limits.h> 14 #include <poll.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <sys/socket.h> 18 #include <sys/types.h> 19 #include <sys/un.h> 20 #include <unistd.h> 21 22 #define MCTP_DEMUX_NAME "libmctp-demux-daemon" 23 const uint8_t mctp_msg_type = MCTP_MSG_TYPE_PLDM; 24 25 struct pldm_transport_mctp_demux { 26 struct pldm_transport transport; 27 int socket; 28 /* In the future this probably needs to move to a tid-eid-uuid/network 29 * id mapping for multi mctp networks */ 30 pldm_tid_t tid_eid_map[MCTP_MAX_NUM_EID]; 31 struct pldm_socket_sndbuf socket_send_buf; 32 }; 33 34 #define transport_to_demux(ptr) \ 35 container_of(ptr, struct pldm_transport_mctp_demux, transport) 36 37 LIBPLDM_ABI_STABLE 38 struct pldm_transport * 39 pldm_transport_mctp_demux_core(struct pldm_transport_mctp_demux *ctx) 40 { 41 return &ctx->transport; 42 } 43 44 static pldm_requester_rc_t pldm_transport_mctp_demux_open(void) 45 { 46 int fd = -1; 47 ssize_t rc = -1; 48 49 fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); 50 if (fd == -1) { 51 return fd; 52 } 53 54 const char path[] = "\0mctp-mux"; 55 struct sockaddr_un addr; 56 addr.sun_family = AF_UNIX; 57 memcpy(addr.sun_path, path, sizeof(path) - 1); 58 rc = connect(fd, (struct sockaddr *)&addr, 59 sizeof(path) + sizeof(addr.sun_family) - 1); 60 if (rc == -1) { 61 return PLDM_REQUESTER_OPEN_FAIL; 62 } 63 rc = write(fd, &mctp_msg_type, sizeof(mctp_msg_type)); 64 if (rc == -1) { 65 return PLDM_REQUESTER_OPEN_FAIL; 66 } 67 68 return fd; 69 } 70 71 LIBPLDM_ABI_STABLE 72 int pldm_transport_mctp_demux_init_pollfd(struct pldm_transport *t, 73 struct pollfd *pollfd) 74 { 75 struct pldm_transport_mctp_demux *ctx = transport_to_demux(t); 76 pollfd->fd = ctx->socket; 77 pollfd->events = POLLIN; 78 return 0; 79 } 80 81 static int 82 pldm_transport_mctp_demux_get_eid(struct pldm_transport_mctp_demux *ctx, 83 pldm_tid_t tid, mctp_eid_t *eid) 84 { 85 int i; 86 for (i = 0; i < MCTP_MAX_NUM_EID; i++) { 87 if (ctx->tid_eid_map[i] == tid) { 88 *eid = i; 89 return 0; 90 } 91 } 92 *eid = -1; 93 return -1; 94 } 95 96 static int 97 pldm_transport_mctp_demux_get_tid(struct pldm_transport_mctp_demux *ctx, 98 mctp_eid_t eid, pldm_tid_t *tid) 99 { 100 /* mapping exists */ 101 if (ctx->tid_eid_map[eid] != 0) { 102 *tid = ctx->tid_eid_map[eid]; 103 return 0; 104 } 105 return -1; 106 } 107 108 LIBPLDM_ABI_STABLE 109 int pldm_transport_mctp_demux_map_tid(struct pldm_transport_mctp_demux *ctx, 110 pldm_tid_t tid, mctp_eid_t eid) 111 { 112 ctx->tid_eid_map[eid] = tid; 113 114 return 0; 115 } 116 117 LIBPLDM_ABI_STABLE 118 int pldm_transport_mctp_demux_unmap_tid(struct pldm_transport_mctp_demux *ctx, 119 __attribute__((unused)) pldm_tid_t tid, 120 mctp_eid_t eid) 121 { 122 ctx->tid_eid_map[eid] = 0; 123 124 return 0; 125 } 126 127 static pldm_requester_rc_t 128 pldm_transport_mctp_demux_recv(struct pldm_transport *t, pldm_tid_t *tid, 129 void **pldm_msg, size_t *msg_len) 130 { 131 struct pldm_transport_mctp_demux *demux = transport_to_demux(t); 132 size_t mctp_prefix_len = 2; 133 struct msghdr msg = { 0 }; 134 pldm_requester_rc_t res; 135 uint8_t mctp_prefix[2]; 136 struct iovec iov[2]; 137 mctp_eid_t eid = 0; 138 ssize_t min_len; 139 size_t pldm_len; 140 ssize_t length; 141 ssize_t bytes; 142 uint8_t *buf; 143 int rc; 144 145 min_len = sizeof(eid) + sizeof(mctp_msg_type) + 146 sizeof(struct pldm_msg_hdr); 147 length = recv(demux->socket, NULL, 0, MSG_PEEK | MSG_TRUNC); 148 if (length <= 0) { 149 return PLDM_REQUESTER_RECV_FAIL; 150 } 151 152 buf = malloc(length); 153 if (buf == NULL) { 154 return PLDM_REQUESTER_RECV_FAIL; 155 } 156 157 if (length < min_len) { 158 /* read and discard */ 159 recv(demux->socket, buf, length, 0); 160 res = PLDM_REQUESTER_INVALID_RECV_LEN; 161 goto cleanup_buf; 162 } 163 164 pldm_len = length - mctp_prefix_len; 165 iov[0].iov_len = mctp_prefix_len; 166 iov[0].iov_base = mctp_prefix; 167 iov[1].iov_len = pldm_len; 168 iov[1].iov_base = buf; 169 170 msg.msg_iov = iov; 171 msg.msg_iovlen = sizeof(iov) / sizeof(iov[0]); 172 173 bytes = recvmsg(demux->socket, &msg, 0); 174 if (length != bytes) { 175 res = PLDM_REQUESTER_INVALID_RECV_LEN; 176 goto cleanup_buf; 177 } 178 179 if (mctp_prefix[1] != mctp_msg_type) { 180 res = PLDM_REQUESTER_NOT_PLDM_MSG; 181 goto cleanup_buf; 182 } 183 184 eid = mctp_prefix[0]; 185 rc = pldm_transport_mctp_demux_get_tid(demux, eid, tid); 186 if (rc) { 187 res = PLDM_REQUESTER_RECV_FAIL; 188 goto cleanup_buf; 189 } 190 191 *pldm_msg = buf; 192 *msg_len = pldm_len; 193 194 return PLDM_REQUESTER_SUCCESS; 195 196 cleanup_buf: 197 free(buf); 198 199 return res; 200 } 201 202 static pldm_requester_rc_t 203 pldm_transport_mctp_demux_send(struct pldm_transport *t, pldm_tid_t tid, 204 const void *pldm_msg, size_t msg_len) 205 { 206 struct pldm_transport_mctp_demux *demux = transport_to_demux(t); 207 mctp_eid_t eid = 0; 208 if (pldm_transport_mctp_demux_get_eid(demux, tid, &eid)) { 209 return PLDM_REQUESTER_SEND_FAIL; 210 } 211 212 uint8_t hdr[2] = { eid, mctp_msg_type }; 213 214 struct iovec iov[2]; 215 iov[0].iov_base = hdr; 216 iov[0].iov_len = sizeof(hdr); 217 iov[1].iov_base = (uint8_t *)pldm_msg; 218 iov[1].iov_len = msg_len; 219 220 struct msghdr msg = { 0 }; 221 msg.msg_iov = iov; 222 msg.msg_iovlen = sizeof(iov) / sizeof(iov[0]); 223 224 if (msg_len > INT_MAX || 225 pldm_socket_sndbuf_accomodate(&(demux->socket_send_buf), 226 (int)msg_len)) { 227 return PLDM_REQUESTER_SEND_FAIL; 228 } 229 230 ssize_t rc = sendmsg(demux->socket, &msg, 0); 231 if (rc == -1) { 232 return PLDM_REQUESTER_SEND_FAIL; 233 } 234 return PLDM_REQUESTER_SUCCESS; 235 } 236 237 LIBPLDM_ABI_STABLE 238 int pldm_transport_mctp_demux_init(struct pldm_transport_mctp_demux **ctx) 239 { 240 if (!ctx || *ctx) { 241 return -EINVAL; 242 } 243 244 struct pldm_transport_mctp_demux *demux = 245 calloc(1, sizeof(struct pldm_transport_mctp_demux)); 246 if (!demux) { 247 return -ENOMEM; 248 } 249 250 demux->transport.name = MCTP_DEMUX_NAME; 251 demux->transport.version = 1; 252 demux->transport.recv = pldm_transport_mctp_demux_recv; 253 demux->transport.send = pldm_transport_mctp_demux_send; 254 demux->transport.init_pollfd = pldm_transport_mctp_demux_init_pollfd; 255 demux->socket = pldm_transport_mctp_demux_open(); 256 if (demux->socket == -1) { 257 free(demux); 258 return -1; 259 } 260 261 if (pldm_socket_sndbuf_init(&demux->socket_send_buf, demux->socket)) { 262 close(demux->socket); 263 free(demux); 264 return -1; 265 } 266 267 *ctx = demux; 268 return 0; 269 } 270 271 LIBPLDM_ABI_STABLE 272 void pldm_transport_mctp_demux_destroy(struct pldm_transport_mctp_demux *ctx) 273 { 274 if (!ctx) { 275 return; 276 } 277 close(ctx->socket); 278 free(ctx); 279 } 280 281 /* Temporary for old API */ 282 struct pldm_transport_mctp_demux * 283 pldm_transport_mctp_demux_init_with_fd(int mctp_fd) 284 { 285 struct pldm_transport_mctp_demux *demux = 286 calloc(1, sizeof(struct pldm_transport_mctp_demux)); 287 if (!demux) { 288 return NULL; 289 } 290 291 demux->transport.name = MCTP_DEMUX_NAME; 292 demux->transport.version = 1; 293 demux->transport.recv = pldm_transport_mctp_demux_recv; 294 demux->transport.send = pldm_transport_mctp_demux_send; 295 demux->transport.init_pollfd = pldm_transport_mctp_demux_init_pollfd; 296 /* dup is so we can call pldm_transport_mctp_demux_destroy which closes 297 * the socket, without closing the fd that is being used by the consumer 298 */ 299 demux->socket = dup(mctp_fd); 300 if (demux->socket == -1) { 301 free(demux); 302 return NULL; 303 } 304 305 if (pldm_socket_sndbuf_init(&demux->socket_send_buf, demux->socket)) { 306 close(demux->socket); 307 free(demux); 308 return NULL; 309 } 310 311 return demux; 312 } 313 314 int pldm_transport_mctp_demux_get_socket_fd( 315 struct pldm_transport_mctp_demux *ctx) 316 { 317 if (ctx) { 318 return ctx->socket; 319 } 320 321 return -1; 322 } 323