blob: b1916dedf3bb4ccc56a427ec1749bf8da25ee8ec [file] [log] [blame]
Andrew Jeffery9c766792022-08-10 23:12:49 +09301#include "pldm.h"
2#include "base.h"
3
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05304#include <bits/types/struct_iovec.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +09305#include <stdlib.h>
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05306#include <string.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +09307#include <sys/socket.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +09308#include <sys/un.h>
9#include <unistd.h>
10
Andrew Jeffery6005f1c2023-04-05 20:02:52 +093011const uint8_t mctp_msg_type_pldm = 1;
Andrew Jeffery9c766792022-08-10 23:12:49 +093012
Andrew Jeffery319304f2023-04-05 13:53:18 +093013pldm_requester_rc_t pldm_open(void)
Andrew Jeffery9c766792022-08-10 23:12:49 +093014{
Andrew Jefferyb705fb02023-04-05 18:28:22 +093015 ssize_t rc = -1;
Andrew Jeffery9c766792022-08-10 23:12:49 +093016 int fd = -1;
Andrew Jeffery9c766792022-08-10 23:12:49 +093017
18 fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
19 if (-1 == fd) {
20 return fd;
21 }
22
23 const char path[] = "\0mctp-mux";
24 struct sockaddr_un addr;
25 addr.sun_family = AF_UNIX;
26 memcpy(addr.sun_path, path, sizeof(path) - 1);
27 rc = connect(fd, (struct sockaddr *)&addr,
28 sizeof(path) + sizeof(addr.sun_family) - 1);
29 if (-1 == rc) {
30 return PLDM_REQUESTER_OPEN_FAIL;
31 }
Andrew Jeffery6005f1c2023-04-05 20:02:52 +093032 rc = write(fd, &mctp_msg_type_pldm, sizeof(mctp_msg_type_pldm));
Andrew Jeffery9c766792022-08-10 23:12:49 +093033 if (-1 == rc) {
34 return PLDM_REQUESTER_OPEN_FAIL;
35 }
36
37 return fd;
38}
39
40/**
41 * @brief Read MCTP socket. If there's data available, return success only if
42 * data is a PLDM message.
43 *
44 * @param[in] eid - destination MCTP eid
45 * @param[in] mctp_fd - MCTP socket fd
46 * @param[out] pldm_resp_msg - *pldm_resp_msg will point to PLDM msg,
47 * this function allocates memory, caller to free(*pldm_resp_msg) on
48 * success.
49 * @param[out] resp_msg_len - caller owned pointer that will be made point to
50 * the size of the PLDM msg.
51 *
52 * @return pldm_requester_rc_t (errno may be set). failure is returned even
53 * when data was read, but wasn't a PLDM response message
54 */
55static pldm_requester_rc_t mctp_recv(mctp_eid_t eid, int mctp_fd,
56 uint8_t **pldm_resp_msg,
57 size_t *resp_msg_len)
58{
Andrew Jeffery6005f1c2023-04-05 20:02:52 +093059 ssize_t min_len = sizeof(eid) + sizeof(mctp_msg_type_pldm) +
Andrew Jeffery9c766792022-08-10 23:12:49 +093060 sizeof(struct pldm_msg_hdr);
61 ssize_t length = recv(mctp_fd, NULL, 0, MSG_PEEK | MSG_TRUNC);
62 if (length <= 0) {
63 return PLDM_REQUESTER_RECV_FAIL;
Andrew Jeffery1e0528c2023-04-05 19:54:58 +093064 }
65 if (length < min_len) {
Andrew Jeffery9c766792022-08-10 23:12:49 +093066 /* read and discard */
67 uint8_t buf[length];
68 recv(mctp_fd, buf, length, 0);
69 return PLDM_REQUESTER_INVALID_RECV_LEN;
Andrew Jeffery9c766792022-08-10 23:12:49 +093070 }
Andrew Jeffery1e0528c2023-04-05 19:54:58 +093071 struct iovec iov[2];
Andrew Jeffery6005f1c2023-04-05 20:02:52 +093072 size_t mctp_prefix_len = sizeof(eid) + sizeof(mctp_msg_type_pldm);
Andrew Jeffery1e0528c2023-04-05 19:54:58 +093073 uint8_t mctp_prefix[mctp_prefix_len];
74 size_t pldm_len = length - mctp_prefix_len;
75 iov[0].iov_len = mctp_prefix_len;
76 iov[0].iov_base = mctp_prefix;
77 *pldm_resp_msg = malloc(pldm_len);
78 iov[1].iov_len = pldm_len;
79 iov[1].iov_base = *pldm_resp_msg;
80 struct msghdr msg = {0};
81 msg.msg_iov = iov;
82 msg.msg_iovlen = sizeof(iov) / sizeof(iov[0]);
83 ssize_t bytes = recvmsg(mctp_fd, &msg, 0);
84 if (length != bytes) {
85 free(*pldm_resp_msg);
86 return PLDM_REQUESTER_INVALID_RECV_LEN;
87 }
Andrew Jeffery6005f1c2023-04-05 20:02:52 +093088 if ((mctp_prefix[0] != eid) || (mctp_prefix[1] != mctp_msg_type_pldm)) {
Andrew Jeffery1e0528c2023-04-05 19:54:58 +093089 free(*pldm_resp_msg);
90 return PLDM_REQUESTER_NOT_PLDM_MSG;
91 }
92 *resp_msg_len = pldm_len;
93 return PLDM_REQUESTER_SUCCESS;
Andrew Jeffery9c766792022-08-10 23:12:49 +093094}
95
96pldm_requester_rc_t pldm_recv_any(mctp_eid_t eid, int mctp_fd,
97 uint8_t **pldm_resp_msg, size_t *resp_msg_len)
98{
99 pldm_requester_rc_t rc =
100 mctp_recv(eid, mctp_fd, pldm_resp_msg, resp_msg_len);
101 if (rc != PLDM_REQUESTER_SUCCESS) {
102 return rc;
103 }
104
105 struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)(*pldm_resp_msg);
106 if (hdr->request != PLDM_RESPONSE) {
107 free(*pldm_resp_msg);
108 return PLDM_REQUESTER_NOT_RESP_MSG;
109 }
110
111 uint8_t pldm_rc = 0;
112 if (*resp_msg_len < (sizeof(struct pldm_msg_hdr) + sizeof(pldm_rc))) {
113 free(*pldm_resp_msg);
114 return PLDM_REQUESTER_RESP_MSG_TOO_SMALL;
115 }
116
117 return PLDM_REQUESTER_SUCCESS;
118}
119
120pldm_requester_rc_t pldm_recv(mctp_eid_t eid, int mctp_fd, uint8_t instance_id,
121 uint8_t **pldm_resp_msg, size_t *resp_msg_len)
122{
123 pldm_requester_rc_t rc =
124 pldm_recv_any(eid, mctp_fd, pldm_resp_msg, resp_msg_len);
125 if (rc != PLDM_REQUESTER_SUCCESS) {
126 return rc;
127 }
128
129 struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)(*pldm_resp_msg);
130 if (hdr->instance_id != instance_id) {
131 free(*pldm_resp_msg);
132 return PLDM_REQUESTER_INSTANCE_ID_MISMATCH;
133 }
134
135 return PLDM_REQUESTER_SUCCESS;
136}
137
138pldm_requester_rc_t pldm_send_recv(mctp_eid_t eid, int mctp_fd,
139 const uint8_t *pldm_req_msg,
140 size_t req_msg_len, uint8_t **pldm_resp_msg,
141 size_t *resp_msg_len)
142{
143 struct pldm_msg_hdr *hdr = (struct pldm_msg_hdr *)pldm_req_msg;
144 if ((hdr->request != PLDM_REQUEST) &&
145 (hdr->request != PLDM_ASYNC_REQUEST_NOTIFY)) {
146 return PLDM_REQUESTER_NOT_REQ_MSG;
147 }
148
149 pldm_requester_rc_t rc =
150 pldm_send(eid, mctp_fd, pldm_req_msg, req_msg_len);
151 if (rc != PLDM_REQUESTER_SUCCESS) {
152 return rc;
153 }
154
155 while (1) {
156 rc = pldm_recv(eid, mctp_fd, hdr->instance_id, pldm_resp_msg,
157 resp_msg_len);
158 if (rc == PLDM_REQUESTER_SUCCESS) {
159 break;
160 }
161 }
162
163 return rc;
164}
165
166pldm_requester_rc_t pldm_send(mctp_eid_t eid, int mctp_fd,
167 const uint8_t *pldm_req_msg, size_t req_msg_len)
168{
Andrew Jeffery6005f1c2023-04-05 20:02:52 +0930169 uint8_t hdr[2] = {eid, mctp_msg_type_pldm};
Andrew Jeffery9c766792022-08-10 23:12:49 +0930170
171 struct iovec iov[2];
172 iov[0].iov_base = hdr;
173 iov[0].iov_len = sizeof(hdr);
174 iov[1].iov_base = (uint8_t *)pldm_req_msg;
175 iov[1].iov_len = req_msg_len;
176
177 struct msghdr msg = {0};
178 msg.msg_iov = iov;
179 msg.msg_iovlen = sizeof(iov) / sizeof(iov[0]);
180
181 ssize_t rc = sendmsg(mctp_fd, &msg, 0);
182 if (rc == -1) {
183 return PLDM_REQUESTER_SEND_FAIL;
184 }
185 return PLDM_REQUESTER_SUCCESS;
186}