xref: /optee_os/lib/libutee/tee_tcpudp_socket.c (revision 1bb929836182ecb96d2d9d268daa807c67596396)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2016-2017, Linaro Limited
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <pta_socket.h>
30 #include <tee_internal_api.h>
31 #include <tee_isocket.h>
32 #include <tee_tcpsocket.h>
33 #include <__tee_tcpsocket_defines_extensions.h>
34 #include <tee_udpsocket.h>
35 
36 #include "tee_socket_private.h"
37 
38 struct socket_ctx {
39 	uint32_t handle;
40 	uint32_t proto_error;
41 };
42 
43 static TEE_Result tcp_open(TEE_iSocketHandle *ctx, void *setup,
44 			   uint32_t *proto_error)
45 {
46 	TEE_Result res;
47 	struct socket_ctx *sock_ctx;
48 	TEE_tcpSocket_Setup *tcp_setup = setup;
49 
50 	if (!ctx || !setup || !proto_error)
51 		TEE_Panic(0);
52 
53 	*proto_error = TEE_SUCCESS;
54 
55 	sock_ctx = TEE_Malloc(sizeof(*sock_ctx), TEE_MALLOC_FILL_ZERO);
56 	if (!sock_ctx)
57 		return TEE_ERROR_OUT_OF_MEMORY;
58 
59 	res = __tee_socket_pta_open(tcp_setup->ipVersion,
60 				    tcp_setup->server_addr,
61 				    tcp_setup->server_port,
62 				    TEE_ISOCKET_PROTOCOLID_TCP,
63 				    &sock_ctx->handle);
64 	if (res != TEE_SUCCESS) {
65 		TEE_Free(sock_ctx);
66 		sock_ctx = NULL;
67 	}
68 	*ctx = (TEE_iSocketHandle)sock_ctx;
69 
70 	switch (res) {
71 	case TEE_ISOCKET_ERROR_HOSTNAME:
72 		*proto_error = res;
73 		return TEE_ISOCKET_ERROR_PROTOCOL;
74 	case TEE_ISOCKET_TCP_WARNING_UNKNOWN_OUT_OF_BAND:
75 		*proto_error = res;
76 		return TEE_ISOCKET_WARNING_PROTOCOL;
77 	default:
78 		return res;
79 	}
80 }
81 
82 static TEE_Result udp_open(TEE_iSocketHandle *ctx, void *setup,
83 			   uint32_t *proto_error)
84 {
85 	TEE_Result res;
86 	struct socket_ctx *sock_ctx;
87 	TEE_udpSocket_Setup *udp_setup = setup;
88 
89 	if (!ctx || !setup || !proto_error)
90 		TEE_Panic(0);
91 
92 	*proto_error = TEE_SUCCESS;
93 
94 	sock_ctx = TEE_Malloc(sizeof(*sock_ctx), TEE_MALLOC_FILL_ZERO);
95 	if (!sock_ctx)
96 		return TEE_ERROR_OUT_OF_MEMORY;
97 
98 	res = __tee_socket_pta_open(udp_setup->ipVersion,
99 				    udp_setup->server_addr,
100 				    udp_setup->server_port,
101 				    TEE_ISOCKET_PROTOCOLID_UDP,
102 				    &sock_ctx->handle);
103 	if (res != TEE_SUCCESS) {
104 		TEE_Free(sock_ctx);
105 		sock_ctx = NULL;
106 	}
107 	*ctx = (TEE_iSocketHandle)sock_ctx;
108 
109 	switch (res) {
110 	case TEE_ISOCKET_ERROR_HOSTNAME:
111 		*proto_error = res;
112 		return TEE_ISOCKET_ERROR_PROTOCOL;
113 	case TEE_ISOCKET_UDP_WARNING_UNKNOWN_OUT_OF_BAND:
114 		*proto_error = res;
115 		return TEE_ISOCKET_WARNING_PROTOCOL;
116 	default:
117 		return res;
118 	}
119 }
120 
121 static TEE_Result sock_close(TEE_iSocketHandle ctx)
122 {
123 	TEE_Result res;
124 	struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx;
125 
126 	if (ctx == TEE_HANDLE_NULL)
127 		return TEE_SUCCESS;
128 
129 	res = __tee_socket_pta_close(sock_ctx->handle);
130 	TEE_Free(sock_ctx);
131 
132 	return res;
133 }
134 
135 static TEE_Result sock_send(TEE_iSocketHandle ctx, const void *buf,
136 			   uint32_t *length, uint32_t timeout)
137 {
138 	TEE_Result res;
139 	struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx;
140 
141 	if (ctx == TEE_HANDLE_NULL || !buf || !length)
142 		TEE_Panic(0);
143 
144 	res = __tee_socket_pta_send(sock_ctx->handle, buf, length, timeout);
145 	sock_ctx->proto_error = res;
146 
147 	return res;
148 }
149 
150 static TEE_Result sock_recv(TEE_iSocketHandle ctx, void *buf, uint32_t *length,
151 			   uint32_t timeout)
152 {
153 	TEE_Result res;
154 	struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx;
155 
156 	if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length))
157 		TEE_Panic(0);
158 
159 	res = __tee_socket_pta_recv(sock_ctx->handle, buf, length, timeout);
160 	sock_ctx->proto_error = res;
161 
162 	return res;
163 }
164 
165 static uint32_t sock_error(TEE_iSocketHandle ctx)
166 {
167 	struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx;
168 
169 	if (ctx == TEE_HANDLE_NULL)
170 		TEE_Panic(0);
171 
172 	return sock_ctx->proto_error;
173 }
174 
175 static TEE_Result tcp_ioctl(TEE_iSocketHandle ctx, uint32_t commandCode,
176 			    void *buf, uint32_t *length)
177 {
178 	TEE_Result res = TEE_ERROR_GENERIC;
179 	struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx;
180 
181 	if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length))
182 		TEE_Panic(0);
183 
184 	if  (__tee_socket_ioctl_cmd_to_proto(commandCode) == 0)
185 		return TEE_SUCCESS;
186 
187 	switch (commandCode) {
188 	case TEE_TCP_SET_RECVBUF:
189 	case TEE_TCP_SET_SENDBUF:
190 		res = __tee_socket_pta_ioctl(sock_ctx->handle, commandCode,
191 					     buf, length);
192 		break;
193 	default:
194 		TEE_Panic(0);
195 	}
196 
197 	sock_ctx->proto_error = res;
198 
199 	return res;
200 }
201 
202 static TEE_Result udp_ioctl(TEE_iSocketHandle ctx, uint32_t commandCode,
203 			    void *buf, uint32_t *length)
204 {
205 	TEE_Result res = TEE_ERROR_GENERIC;
206 	struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx;
207 
208 	if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length))
209 		TEE_Panic(0);
210 
211 	if  (__tee_socket_ioctl_cmd_to_proto(commandCode) == 0)
212 		return TEE_SUCCESS;
213 
214 	switch (commandCode) {
215 	case TEE_UDP_CHANGEADDR:
216 	case TEE_UDP_CHANGEPORT:
217 		res = __tee_socket_pta_ioctl(sock_ctx->handle, commandCode,
218 					     buf, length);
219 		break;
220 	default:
221 		TEE_Panic(0);
222 	}
223 
224 	sock_ctx->proto_error = res;
225 
226 	return res;
227 }
228 
229 
230 
231 static TEE_iSocket tcp_socket_instance = {
232 	.TEE_iSocketVersion = TEE_ISOCKET_VERSION,
233 	.protocolID = TEE_ISOCKET_PROTOCOLID_TCP,
234 	.open = &tcp_open,
235 	.close = &sock_close,
236 	.send = &sock_send,
237 	.recv = &sock_recv,
238 	.error = &sock_error,
239 	.ioctl = &tcp_ioctl,
240 };
241 
242 static TEE_iSocket udp_socket_instance = {
243 	.TEE_iSocketVersion = TEE_ISOCKET_VERSION,
244 	.protocolID = TEE_ISOCKET_PROTOCOLID_UDP,
245 	.open = &udp_open,
246 	.close = &sock_close,
247 	.send = &sock_send,
248 	.recv = &sock_recv,
249 	.error = &sock_error,
250 	.ioctl = &udp_ioctl,
251 };
252 
253 TEE_iSocket *const TEE_tcpSocket = &tcp_socket_instance;
254 TEE_iSocket *const TEE_udpSocket = &udp_socket_instance;
255