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
tcp_open(TEE_iSocketHandle * ctx,void * setup,uint32_t * proto_error)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
udp_open(TEE_iSocketHandle * ctx,void * setup,uint32_t * proto_error)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
sock_close(TEE_iSocketHandle ctx)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
sock_send(TEE_iSocketHandle ctx,const void * buf,uint32_t * length,uint32_t timeout)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
sock_recv(TEE_iSocketHandle ctx,void * buf,uint32_t * length,uint32_t timeout)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
sock_error(TEE_iSocketHandle ctx)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
tcp_ioctl(TEE_iSocketHandle ctx,uint32_t commandCode,void * buf,uint32_t * length)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
udp_ioctl(TEE_iSocketHandle ctx,uint32_t commandCode,void * buf,uint32_t * length)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