1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2016-2017, Linaro Limited 4 * All rights reserved. 5 */ 6 7 #include <pta_socket.h> 8 #include <tee_internal_api.h> 9 #include <tee_isocket.h> 10 #include <tee_tcpsocket.h> 11 #include <__tee_tcpsocket_defines_extensions.h> 12 #include <tee_udpsocket.h> 13 14 #include "tee_socket_private.h" 15 16 struct socket_ctx { 17 uint32_t handle; 18 uint32_t proto_error; 19 }; 20 21 static TEE_Result tcp_open(TEE_iSocketHandle *ctx, void *setup, 22 uint32_t *proto_error) 23 { 24 TEE_Result res; 25 struct socket_ctx *sock_ctx; 26 TEE_tcpSocket_Setup *tcp_setup = setup; 27 28 if (!ctx || !setup || !proto_error) 29 TEE_Panic(0); 30 31 *proto_error = TEE_SUCCESS; 32 33 sock_ctx = TEE_Malloc(sizeof(*sock_ctx), TEE_MALLOC_FILL_ZERO); 34 if (!sock_ctx) 35 return TEE_ERROR_OUT_OF_MEMORY; 36 37 res = __tee_socket_pta_open(tcp_setup->ipVersion, 38 tcp_setup->server_addr, 39 tcp_setup->server_port, 40 TEE_ISOCKET_PROTOCOLID_TCP, 41 &sock_ctx->handle); 42 if (res != TEE_SUCCESS) { 43 TEE_Free(sock_ctx); 44 sock_ctx = NULL; 45 } 46 *ctx = (TEE_iSocketHandle)sock_ctx; 47 48 switch (res) { 49 case TEE_ISOCKET_ERROR_HOSTNAME: 50 *proto_error = res; 51 return TEE_ISOCKET_ERROR_PROTOCOL; 52 case TEE_ISOCKET_TCP_WARNING_UNKNOWN_OUT_OF_BAND: 53 *proto_error = res; 54 return TEE_ISOCKET_WARNING_PROTOCOL; 55 default: 56 return res; 57 } 58 } 59 60 static TEE_Result udp_open(TEE_iSocketHandle *ctx, void *setup, 61 uint32_t *proto_error) 62 { 63 TEE_Result res; 64 struct socket_ctx *sock_ctx; 65 TEE_udpSocket_Setup *udp_setup = setup; 66 67 if (!ctx || !setup || !proto_error) 68 TEE_Panic(0); 69 70 *proto_error = TEE_SUCCESS; 71 72 sock_ctx = TEE_Malloc(sizeof(*sock_ctx), TEE_MALLOC_FILL_ZERO); 73 if (!sock_ctx) 74 return TEE_ERROR_OUT_OF_MEMORY; 75 76 res = __tee_socket_pta_open(udp_setup->ipVersion, 77 udp_setup->server_addr, 78 udp_setup->server_port, 79 TEE_ISOCKET_PROTOCOLID_UDP, 80 &sock_ctx->handle); 81 if (res != TEE_SUCCESS) { 82 TEE_Free(sock_ctx); 83 sock_ctx = NULL; 84 } 85 *ctx = (TEE_iSocketHandle)sock_ctx; 86 87 switch (res) { 88 case TEE_ISOCKET_ERROR_HOSTNAME: 89 *proto_error = res; 90 return TEE_ISOCKET_ERROR_PROTOCOL; 91 case TEE_ISOCKET_UDP_WARNING_UNKNOWN_OUT_OF_BAND: 92 *proto_error = res; 93 return TEE_ISOCKET_WARNING_PROTOCOL; 94 default: 95 return res; 96 } 97 } 98 99 static TEE_Result sock_close(TEE_iSocketHandle ctx) 100 { 101 TEE_Result res; 102 struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; 103 104 if (ctx == TEE_HANDLE_NULL) 105 return TEE_SUCCESS; 106 107 res = __tee_socket_pta_close(sock_ctx->handle); 108 TEE_Free(sock_ctx); 109 110 return res; 111 } 112 113 static TEE_Result sock_send(TEE_iSocketHandle ctx, const void *buf, 114 uint32_t *length, uint32_t timeout) 115 { 116 TEE_Result res; 117 struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; 118 119 if (ctx == TEE_HANDLE_NULL || !buf || !length) 120 TEE_Panic(0); 121 122 res = __tee_socket_pta_send(sock_ctx->handle, buf, length, timeout); 123 sock_ctx->proto_error = res; 124 125 return res; 126 } 127 128 static TEE_Result sock_recv(TEE_iSocketHandle ctx, void *buf, uint32_t *length, 129 uint32_t timeout) 130 { 131 TEE_Result res; 132 struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; 133 134 if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length)) 135 TEE_Panic(0); 136 137 res = __tee_socket_pta_recv(sock_ctx->handle, buf, length, timeout); 138 sock_ctx->proto_error = res; 139 140 return res; 141 } 142 143 static uint32_t sock_error(TEE_iSocketHandle ctx) 144 { 145 struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; 146 147 if (ctx == TEE_HANDLE_NULL) 148 TEE_Panic(0); 149 150 return sock_ctx->proto_error; 151 } 152 153 static TEE_Result tcp_ioctl(TEE_iSocketHandle ctx, uint32_t commandCode, 154 void *buf, uint32_t *length) 155 { 156 TEE_Result res = TEE_ERROR_GENERIC; 157 struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; 158 159 if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length)) 160 TEE_Panic(0); 161 162 if (__tee_socket_ioctl_cmd_to_proto(commandCode) == 0) 163 return TEE_SUCCESS; 164 165 switch (commandCode) { 166 case TEE_TCP_SET_RECVBUF: 167 case TEE_TCP_SET_SENDBUF: 168 res = __tee_socket_pta_ioctl(sock_ctx->handle, commandCode, 169 buf, length); 170 break; 171 default: 172 TEE_Panic(0); 173 } 174 175 sock_ctx->proto_error = res; 176 177 return res; 178 } 179 180 static TEE_Result udp_ioctl(TEE_iSocketHandle ctx, uint32_t commandCode, 181 void *buf, uint32_t *length) 182 { 183 TEE_Result res = TEE_ERROR_GENERIC; 184 struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; 185 186 if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length)) 187 TEE_Panic(0); 188 189 if (__tee_socket_ioctl_cmd_to_proto(commandCode) == 0) 190 return TEE_SUCCESS; 191 192 switch (commandCode) { 193 case TEE_UDP_CHANGEADDR: 194 case TEE_UDP_CHANGEPORT: 195 res = __tee_socket_pta_ioctl(sock_ctx->handle, commandCode, 196 buf, length); 197 break; 198 default: 199 TEE_Panic(0); 200 } 201 202 sock_ctx->proto_error = res; 203 204 return res; 205 } 206 207 208 209 static TEE_iSocket tcp_socket_instance = { 210 .TEE_iSocketVersion = TEE_ISOCKET_VERSION, 211 .protocolID = TEE_ISOCKET_PROTOCOLID_TCP, 212 .open = &tcp_open, 213 .close = &sock_close, 214 .send = &sock_send, 215 .recv = &sock_recv, 216 .error = &sock_error, 217 .ioctl = &tcp_ioctl, 218 }; 219 220 static TEE_iSocket udp_socket_instance = { 221 .TEE_iSocketVersion = TEE_ISOCKET_VERSION, 222 .protocolID = TEE_ISOCKET_PROTOCOLID_UDP, 223 .open = &udp_open, 224 .close = &sock_close, 225 .send = &sock_send, 226 .recv = &sock_recv, 227 .error = &sock_error, 228 .ioctl = &udp_ioctl, 229 }; 230 231 TEE_iSocket *const TEE_tcpSocket = &tcp_socket_instance; 232 TEE_iSocket *const TEE_udpSocket = &udp_socket_instance; 233