requester: Add af_mctp transport

Change-Id: I97641973fb85070876c11003a9758faa707f4a46
Signed-off-by: Rashmica Gupta <rashmica@linux.ibm.com>
diff --git a/include/libpldm/meson.build b/include/libpldm/meson.build
index 39c53ea..fce591f 100644
--- a/include/libpldm/meson.build
+++ b/include/libpldm/meson.build
@@ -34,6 +34,7 @@
     )
    libpldm_transport_headers += files(
     'transport.h',
+    'transport/af-mctp.h',
     'transport/mctp-demux.h'
    )
 endif
diff --git a/include/libpldm/transport/af-mctp.h b/include/libpldm/transport/af-mctp.h
new file mode 100644
index 0000000..2b788f7
--- /dev/null
+++ b/include/libpldm/transport/af-mctp.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
+#ifndef LIBPLDM_AF_MCTP_H
+#define LIBPLDM_AF_MCTP_H
+#include "../config.h"
+#include "libpldm/base.h"
+#include "libpldm/pldm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct pldm_transport_af_mctp;
+
+/* Init the transport backend */
+int pldm_transport_af_mctp_init(struct pldm_transport_af_mctp **ctx);
+
+/* Destroy the transport backend */
+void pldm_transport_af_mctp_destroy(struct pldm_transport_af_mctp *ctx);
+
+/* Get the core pldm transport struct */
+struct pldm_transport *
+pldm_transport_af_mctp_core(struct pldm_transport_af_mctp *ctx);
+
+#ifdef PLDM_HAS_POLL
+struct pollfd;
+/* Init pollfd for async calls */
+int pldm_transport_af_mctp_init_pollfd(struct pldm_transport_af_mctp *ctx,
+				       struct pollfd *pollfd);
+#endif
+
+/* Inserts a TID-to-EID mapping into the transport's device map */
+int pldm_transport_af_mctp_map_tid(struct pldm_transport_af_mctp *ctx,
+				   pldm_tid_t tid, mctp_eid_t eid);
+
+/* Removes a TID-to-EID mapping from the transport's device map */
+int pldm_transport_af_mctp_unmap_tid(struct pldm_transport_af_mctp *ctx,
+				     pldm_tid_t tid, mctp_eid_t eid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBPLDM_AF MCTP*/
diff --git a/src/transport/af-mctp.c b/src/transport/af-mctp.c
new file mode 100644
index 0000000..21d2c72
--- /dev/null
+++ b/src/transport/af-mctp.c
@@ -0,0 +1,157 @@
+#include "../mctp-defines.h"
+#include "base.h"
+#include "container-of.h"
+#include "libpldm/pldm.h"
+#include "libpldm/transport.h"
+#include "transport.h"
+
+#include <errno.h>
+#include <linux/mctp.h>
+#include <poll.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#define AF_MCTP_NAME "AF_MCTP"
+struct pldm_transport_af_mctp {
+	struct pldm_transport transport;
+	int socket;
+	pldm_tid_t tid_eid_map[MCTP_MAX_NUM_EID];
+};
+
+#define transport_to_af_mctp(ptr)                                              \
+	container_of(ptr, struct pldm_transport_af_mctp, transport)
+
+struct pldm_transport *
+pldm_transport_af_mctp_core(struct pldm_transport_af_mctp *ctx)
+{
+	return &ctx->transport;
+}
+
+int pldm_transport_af_mctp_init_pollfd(struct pldm_transport *t,
+				       struct pollfd *pollfd)
+{
+	struct pldm_transport_af_mctp *ctx = transport_to_af_mctp(t);
+	pollfd->fd = ctx->socket;
+	pollfd->events = POLLIN;
+	return 0;
+}
+
+static int pldm_transport_af_mctp_get_eid(struct pldm_transport_af_mctp *ctx,
+					  pldm_tid_t tid, mctp_eid_t *eid)
+{
+	int i;
+	for (i = 0; i < MCTP_MAX_NUM_EID; i++) {
+		if (ctx->tid_eid_map[i] == tid) {
+			*eid = i;
+			return 0;
+		}
+	}
+	*eid = -1;
+	return -1;
+}
+
+int pldm_transport_af_mctp_map_tid(struct pldm_transport_af_mctp *ctx,
+				   pldm_tid_t tid, mctp_eid_t eid)
+{
+	ctx->tid_eid_map[eid] = tid;
+
+	return 0;
+}
+
+int pldm_transport_af_mctp_unmap_tid(struct pldm_transport_af_mctp *ctx,
+				     __attribute__((unused)) pldm_tid_t tid,
+				     mctp_eid_t eid)
+{
+	ctx->tid_eid_map[eid] = 0;
+
+	return 0;
+}
+
+static pldm_requester_rc_t pldm_transport_af_mctp_recv(struct pldm_transport *t,
+						       pldm_tid_t tid,
+						       void **pldm_resp_msg,
+						       size_t *resp_msg_len)
+{
+	struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t);
+	mctp_eid_t eid = 0;
+	int rc = pldm_transport_af_mctp_get_eid(af_mctp, tid, &eid);
+	if (rc) {
+		return PLDM_REQUESTER_RECV_FAIL;
+	}
+
+	ssize_t length = recv(af_mctp->socket, NULL, 0, MSG_PEEK | MSG_TRUNC);
+	if (length <= 0) {
+		return PLDM_REQUESTER_RECV_FAIL;
+	}
+	*pldm_resp_msg = malloc(length);
+	length = recv(af_mctp->socket, *pldm_resp_msg, length, MSG_TRUNC);
+	if (length < (ssize_t)sizeof(struct pldm_msg_hdr)) {
+		free(*pldm_resp_msg);
+		return PLDM_REQUESTER_INVALID_RECV_LEN;
+	}
+	*resp_msg_len = length;
+	return PLDM_REQUESTER_SUCCESS;
+}
+
+static pldm_requester_rc_t pldm_transport_af_mctp_send(struct pldm_transport *t,
+						       pldm_tid_t tid,
+						       const void *pldm_req_msg,
+						       size_t req_msg_len)
+{
+	struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t);
+	mctp_eid_t eid = 0;
+	if (pldm_transport_af_mctp_get_eid(af_mctp, tid, &eid)) {
+		return PLDM_REQUESTER_SEND_FAIL;
+	}
+
+	struct sockaddr_mctp addr = {0};
+	addr.smctp_family = AF_MCTP;
+	addr.smctp_addr.s_addr = eid;
+	addr.smctp_type = MCTP_MSG_TYPE_PLDM;
+	addr.smctp_tag = MCTP_TAG_OWNER;
+
+	ssize_t rc = sendto(af_mctp->socket, pldm_req_msg, req_msg_len, 0,
+			    (struct sockaddr *)&addr, sizeof(addr));
+	if (rc == -1) {
+		return PLDM_REQUESTER_SEND_FAIL;
+	}
+	return PLDM_REQUESTER_SUCCESS;
+}
+
+int pldm_transport_af_mctp_init(struct pldm_transport_af_mctp **ctx)
+{
+	if (!ctx || *ctx) {
+		return -EINVAL;
+	}
+
+	struct pldm_transport_af_mctp *af_mctp =
+	    calloc(1, sizeof(struct pldm_transport_af_mctp));
+	if (!af_mctp) {
+		return -ENOMEM;
+	}
+
+	af_mctp->transport.name = AF_MCTP_NAME;
+	af_mctp->transport.version = 1;
+	af_mctp->transport.recv = pldm_transport_af_mctp_recv;
+	af_mctp->transport.send = pldm_transport_af_mctp_send;
+	af_mctp->socket = socket(AF_MCTP, SOCK_DGRAM, 0);
+	if (af_mctp->socket == -1) {
+		free(af_mctp);
+		return -1;
+	}
+	*ctx = af_mctp;
+	return 0;
+}
+
+void pldm_transport_af_mctp_destroy(struct pldm_transport_af_mctp *ctx)
+{
+	if (!ctx) {
+		return;
+	}
+	close(ctx->socket);
+	free(ctx);
+}
diff --git a/src/transport/meson.build b/src/transport/meson.build
index 1a2acc9..1fcc06a 100644
--- a/src/transport/meson.build
+++ b/src/transport/meson.build
@@ -1,4 +1,5 @@
 libpldm_sources += files(
+  'af-mctp.c',
   'mctp-demux.c',
   'transport.c'
 )