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