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