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