diff options
Diffstat (limited to 'lib/libutee/tee_tcpudp_socket.c')
-rw-r--r-- | lib/libutee/tee_tcpudp_socket.c | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/lib/libutee/tee_tcpudp_socket.c b/lib/libutee/tee_tcpudp_socket.c new file mode 100644 index 0000000..d899b8c --- /dev/null +++ b/lib/libutee/tee_tcpudp_socket.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2016-2017, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#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; |