blob: e2300fbf566ad238099a009de5f89542b8b09dc7 [file] [log] [blame]
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (c) 2016-2017, Linaro Limited
*/
#include <pta_socket.h>
#include <tee_internal_api.h>
#include <tee_isocket.h>
#include <tee_tcpsocket.h>
#include <__tee_tcpsocket_defines_extensions.h>
#include <tee_udpsocket.h>
#include "tee_socket_private.h"
struct socket_ctx {
uint32_t handle;
uint32_t proto_error;
};
static TEE_Result tcp_open(TEE_iSocketHandle *ctx, void *setup,
uint32_t *proto_error)
{
TEE_Result res;
struct socket_ctx *sock_ctx;
TEE_tcpSocket_Setup *tcp_setup = setup;
if (!ctx || !setup || !proto_error)
TEE_Panic(0);
*proto_error = TEE_SUCCESS;
sock_ctx = TEE_Malloc(sizeof(*sock_ctx), TEE_MALLOC_FILL_ZERO);
if (!sock_ctx)
return TEE_ERROR_OUT_OF_MEMORY;
res = __tee_socket_pta_open(tcp_setup->ipVersion,
tcp_setup->server_addr,
tcp_setup->server_port,
TEE_ISOCKET_PROTOCOLID_TCP,
&sock_ctx->handle);
if (res != TEE_SUCCESS) {
TEE_Free(sock_ctx);
sock_ctx = NULL;
}
*ctx = (TEE_iSocketHandle)sock_ctx;
switch (res) {
case TEE_ISOCKET_ERROR_HOSTNAME:
*proto_error = res;
return TEE_ISOCKET_ERROR_PROTOCOL;
case TEE_ISOCKET_TCP_WARNING_UNKNOWN_OUT_OF_BAND:
*proto_error = res;
return TEE_ISOCKET_WARNING_PROTOCOL;
default:
return res;
}
}
static TEE_Result udp_open(TEE_iSocketHandle *ctx, void *setup,
uint32_t *proto_error)
{
TEE_Result res;
struct socket_ctx *sock_ctx;
TEE_udpSocket_Setup *udp_setup = setup;
if (!ctx || !setup || !proto_error)
TEE_Panic(0);
*proto_error = TEE_SUCCESS;
sock_ctx = TEE_Malloc(sizeof(*sock_ctx), TEE_MALLOC_FILL_ZERO);
if (!sock_ctx)
return TEE_ERROR_OUT_OF_MEMORY;
res = __tee_socket_pta_open(udp_setup->ipVersion,
udp_setup->server_addr,
udp_setup->server_port,
TEE_ISOCKET_PROTOCOLID_UDP,
&sock_ctx->handle);
if (res != TEE_SUCCESS) {
TEE_Free(sock_ctx);
sock_ctx = NULL;
}
*ctx = (TEE_iSocketHandle)sock_ctx;
switch (res) {
case TEE_ISOCKET_ERROR_HOSTNAME:
*proto_error = res;
return TEE_ISOCKET_ERROR_PROTOCOL;
case TEE_ISOCKET_UDP_WARNING_UNKNOWN_OUT_OF_BAND:
*proto_error = res;
return TEE_ISOCKET_WARNING_PROTOCOL;
default:
return res;
}
}
static TEE_Result sock_close(TEE_iSocketHandle ctx)
{
TEE_Result res;
struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx;
if (ctx == TEE_HANDLE_NULL)
return TEE_SUCCESS;
res = __tee_socket_pta_close(sock_ctx->handle);
TEE_Free(sock_ctx);
return res;
}
static TEE_Result sock_send(TEE_iSocketHandle ctx, const void *buf,
uint32_t *length, uint32_t timeout)
{
TEE_Result res;
struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx;
if (ctx == TEE_HANDLE_NULL || !buf || !length)
TEE_Panic(0);
res = __tee_socket_pta_send(sock_ctx->handle, buf, length, timeout);
sock_ctx->proto_error = res;
return res;
}
static TEE_Result sock_recv(TEE_iSocketHandle ctx, void *buf, uint32_t *length,
uint32_t timeout)
{
TEE_Result res;
struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx;
if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length))
TEE_Panic(0);
res = __tee_socket_pta_recv(sock_ctx->handle, buf, length, timeout);
sock_ctx->proto_error = res;
return res;
}
static uint32_t sock_error(TEE_iSocketHandle ctx)
{
struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx;
if (ctx == TEE_HANDLE_NULL)
TEE_Panic(0);
return sock_ctx->proto_error;
}
static TEE_Result tcp_ioctl(TEE_iSocketHandle ctx, uint32_t commandCode,
void *buf, uint32_t *length)
{
TEE_Result res = TEE_ERROR_GENERIC;
struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx;
if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length))
TEE_Panic(0);
if (__tee_socket_ioctl_cmd_to_proto(commandCode) == 0)
return TEE_SUCCESS;
switch (commandCode) {
case TEE_TCP_SET_RECVBUF:
case TEE_TCP_SET_SENDBUF:
res = __tee_socket_pta_ioctl(sock_ctx->handle, commandCode,
buf, length);
break;
default:
TEE_Panic(0);
}
sock_ctx->proto_error = res;
return res;
}
static TEE_Result udp_ioctl(TEE_iSocketHandle ctx, uint32_t commandCode,
void *buf, uint32_t *length)
{
TEE_Result res = TEE_ERROR_GENERIC;
struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx;
if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length))
TEE_Panic(0);
if (__tee_socket_ioctl_cmd_to_proto(commandCode) == 0)
return TEE_SUCCESS;
switch (commandCode) {
case TEE_UDP_CHANGEADDR:
case TEE_UDP_CHANGEPORT:
res = __tee_socket_pta_ioctl(sock_ctx->handle, commandCode,
buf, length);
break;
default:
TEE_Panic(0);
}
sock_ctx->proto_error = res;
return res;
}
static TEE_iSocket tcp_socket_instance = {
.TEE_iSocketVersion = TEE_ISOCKET_VERSION,
.protocolID = TEE_ISOCKET_PROTOCOLID_TCP,
.open = &tcp_open,
.close = &sock_close,
.send = &sock_send,
.recv = &sock_recv,
.error = &sock_error,
.ioctl = &tcp_ioctl,
};
static TEE_iSocket udp_socket_instance = {
.TEE_iSocketVersion = TEE_ISOCKET_VERSION,
.protocolID = TEE_ISOCKET_PROTOCOLID_UDP,
.open = &udp_open,
.close = &sock_close,
.send = &sock_send,
.recv = &sock_recv,
.error = &sock_error,
.ioctl = &udp_ioctl,
};
TEE_iSocket *const TEE_tcpSocket = &tcp_socket_instance;
TEE_iSocket *const TEE_udpSocket = &udp_socket_instance;