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