blob: 21d2c725825ab6a97bc43309ec0ff82ac5ad0ace [file] [log] [blame]
Rashmica Guptaba6971b2022-12-09 16:27:38 +11001#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"
19struct 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
28struct pldm_transport *
29pldm_transport_af_mctp_core(struct pldm_transport_af_mctp *ctx)
30{
31 return &ctx->transport;
32}
33
34int 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
43static 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
57int 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
65int 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
74static 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
100static 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
125int 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
150void 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}