1 /*
2 * TCP/IP or UDP/IP networking functions
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */
20
21 #if !defined(MBEDTLS_CONFIG_FILE)
22 #include "mbedtls/config.h"
23 #else
24 #include MBEDTLS_CONFIG_FILE
25 #endif
26 #if !defined(MBEDTLS_NET_C)
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <stdint.h>
30 #include <string.h>
31
32 #include "mbedtls/net_sockets.h"
33
34 #if defined(STM32_USE_SPI_WIFI)
35
36 #include "stm32_wifi.h"
37
38 #define WIFI_WRITE_TIMEOUT 200
39 #define WIFI_READ_TIMEOUT 200
40 #define WIFI_PAYLOAD_SIZE ES_WIFI_PAYLOAD_SIZE
41 #define WIFI_READ_RETRY_TIME 5
42
mbedtls_net_init(mbedtls_net_context * ctx)43 void mbedtls_net_init( mbedtls_net_context *ctx )
44 {
45 ctx->fd = -1;
46 }
47
mbedtls_net_connect(mbedtls_net_context * ctx,const char * host,const char * port,int proto)48 int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto )
49 {
50 WIFI_Status_t ret;
51 WIFI_Protocol_t type;
52 uint8_t ip_addr[4];
53
54 ret = WIFI_GetHostAddress( (char *)host, ip_addr );
55 if( ret != WIFI_STATUS_OK )
56 return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
57
58 type = ( proto == MBEDTLS_NET_PROTO_UDP ?
59 WIFI_UDP_PROTOCOL : WIFI_TCP_PROTOCOL );
60 ret = WIFI_OpenClientConnection( 0, type, "", ip_addr, atoi(port), 0 );
61 if( ret != WIFI_STATUS_OK )
62 return( MBEDTLS_ERR_NET_CONNECT_FAILED );
63
64 ctx->fd = 0;
65
66 return( ret );
67 }
68
mbedtls_net_recv(void * ctx,unsigned char * buf,size_t len)69 int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
70 {
71 WIFI_Status_t ret;
72 uint16_t recv_size;
73 int fd = ((mbedtls_net_context *) ctx)->fd;
74
75 if (fd < 0)
76 return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
77
78 if ( len > WIFI_PAYLOAD_SIZE )
79 len = WIFI_PAYLOAD_SIZE;
80
81 int err_count = 0;
82 do
83 {
84 ret = WIFI_ReceiveData( (uint8_t)fd,
85 buf, (uint16_t)len,
86 &recv_size, WIFI_READ_TIMEOUT );
87 if( ret != WIFI_STATUS_OK )
88 return( MBEDTLS_ERR_NET_RECV_FAILED );
89
90 if( recv_size == 0 )
91 {
92 if( err_count == WIFI_READ_RETRY_TIME )
93 return( MBEDTLS_ERR_SSL_WANT_READ );
94 else
95 err_count++;
96 }
97 } while( ( ret == WIFI_STATUS_OK ) && ( recv_size == 0 ) );
98
99 return( recv_size );
100 }
101
mbedtls_net_recv_timeout(void * ctx,unsigned char * buf,size_t len,uint32_t timeout)102 int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
103 uint32_t timeout )
104 {
105 WIFI_Status_t ret;
106 uint16_t recv_size;
107 int fd = ((mbedtls_net_context *) ctx)->fd;
108
109 if( fd < 0 )
110 return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
111
112 if( len > WIFI_PAYLOAD_SIZE )
113 len = WIFI_PAYLOAD_SIZE;
114
115 int err_count = 0;
116 do
117 {
118 ret = WIFI_ReceiveData( (uint8_t)fd,
119 buf, (uint16_t)len,
120 &recv_size, WIFI_READ_TIMEOUT );
121 if( ret != WIFI_STATUS_OK )
122 return( MBEDTLS_ERR_NET_RECV_FAILED );
123
124 if( recv_size == 0 )
125 {
126 if( err_count == WIFI_READ_RETRY_TIME )
127 return( MBEDTLS_ERR_SSL_WANT_READ );
128 else
129 err_count++;
130 }
131 } while( ( ret == WIFI_STATUS_OK ) && ( recv_size == 0 ) );
132
133 return( recv_size );
134 }
135
mbedtls_net_send(void * ctx,const unsigned char * buf,size_t len)136 int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
137 {
138 WIFI_Status_t ret;
139 uint16_t send_size;
140 uint16_t once_len;
141 uint8_t *pdata = (uint8_t *)buf;
142 uint16_t send_total = 0;
143 int fd = ((mbedtls_net_context *) ctx)->fd;
144
145 if( fd < 0 )
146 return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
147
148 do
149 {
150 if( len > WIFI_PAYLOAD_SIZE )
151 {
152 once_len = WIFI_PAYLOAD_SIZE;
153 len -= WIFI_PAYLOAD_SIZE;
154 }
155 else
156 {
157 once_len = len;
158 len = 0;
159 }
160
161 ret = WIFI_SendData( (uint8_t)fd,
162 pdata, once_len,
163 &send_size, WIFI_WRITE_TIMEOUT );
164 if( ret != WIFI_STATUS_OK )
165 return( MBEDTLS_ERR_NET_SEND_FAILED );
166
167 pdata += once_len;
168 send_total += send_size;
169 } while ( len > 0 );
170
171 return( send_total );
172 }
173
mbedtls_net_free(mbedtls_net_context * ctx)174 void mbedtls_net_free( mbedtls_net_context *ctx )
175 {
176 WIFI_Status_t ret;
177
178 if (ctx->fd == -1)
179 return;
180
181 ret = WIFI_CloseClientConnection( (uint32_t)ctx->fd );
182 if( ret != WIFI_STATUS_OK )
183 return;
184
185 ctx->fd = -1;
186 }
187
188 #else /* STM32_USE_SPI_WIFI */
189
190 #include <fcntl.h>
191 #include <unistd.h>
192
193 #include <netdb.h>
194 #include <sys/socket.h>
195
mbedtls_net_init(mbedtls_net_context * ctx)196 void mbedtls_net_init( mbedtls_net_context *ctx )
197 {
198 ctx->fd = -1;
199 }
200
mbedtls_net_connect(mbedtls_net_context * ctx,const char * host,const char * port,int proto)201 int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto )
202 {
203 int ret;
204 struct addrinfo hints, *addr_list, *cur;
205
206 memset( &hints, 0, sizeof( hints ) );
207 hints.ai_family = AF_UNSPEC;
208 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
209 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
210
211 if( getaddrinfo( host, port, &hints, &addr_list ) != 0 )
212 return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
213
214 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
215
216 for( cur = addr_list; cur != NULL; cur = cur->ai_next )
217 {
218 ctx->fd = (int) socket( cur->ai_family,
219 cur->ai_socktype, cur->ai_protocol );
220 if( ctx->fd < 0 )
221 {
222 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
223 continue;
224 }
225
226 do
227 {
228 ret = connect( ctx->fd, cur->ai_addr, cur->ai_addrlen );
229 if( ret == 0 )
230 goto out;
231 else
232 {
233 if (errno == EINTR)
234 continue;
235
236 break;
237 }
238 } while( 1 );
239
240 close( ctx->fd );
241 ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
242 }
243
244 out:
245 freeaddrinfo( addr_list );
246
247 return( ret );
248 }
249
net_would_block(const mbedtls_net_context * ctx)250 static int net_would_block( const mbedtls_net_context *ctx )
251 {
252 int err = errno;
253
254 /*
255 * Never return 'WOULD BLOCK' on a non-blocking socket
256 */
257 if( ( fcntl( ctx->fd, F_GETFL, 0) & O_NONBLOCK ) != O_NONBLOCK )
258 {
259 errno = err;
260 return( 0 );
261 }
262
263 switch( errno = err )
264 {
265 #if defined EAGAIN
266 case EAGAIN:
267 #endif
268 #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
269 case EWOULDBLOCK:
270 #endif
271 return( 1 );
272 }
273 return( 0 );
274 }
275
mbedtls_net_set_block(mbedtls_net_context * ctx)276 int mbedtls_net_set_block( mbedtls_net_context *ctx )
277 {
278 int flags;
279
280 flags = fcntl( ctx->fd, F_GETFL, 0 );
281 flags &= ~O_NONBLOCK;
282
283 return fcntl( ctx->fd, F_SETFL, flags );
284 }
285
mbedtls_net_set_nonblock(mbedtls_net_context * ctx)286 int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
287 {
288 int flags;
289
290 flags = fcntl( ctx->fd, F_GETFL, 0 );
291 flags |= O_NONBLOCK;
292
293 return fcntl( ctx->fd, F_SETFL, flags );
294 }
295
mbedtls_net_recv(void * ctx,unsigned char * buf,size_t len)296 int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
297 {
298 int ret;
299 int fd = ((mbedtls_net_context *) ctx)->fd;
300
301 if( fd < 0 )
302 return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
303
304 ret = (int) read( fd, buf, len );
305
306 if( ret < 0 )
307 {
308 if( net_would_block( ctx ) != 0 )
309 return( MBEDTLS_ERR_SSL_WANT_READ );
310
311 if( errno == EPIPE || errno == ECONNRESET )
312 return( MBEDTLS_ERR_NET_CONN_RESET );
313
314 if( errno == EINTR )
315 return( MBEDTLS_ERR_SSL_WANT_READ );
316
317 return( MBEDTLS_ERR_NET_RECV_FAILED );
318 }
319
320 return( ret );
321 }
322
mbedtls_net_recv_timeout(void * ctx,unsigned char * buf,size_t len,uint32_t timeout)323 int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
324 uint32_t timeout )
325 {
326 int ret;
327 struct timeval tv;
328 fd_set read_fds;
329 int fd = ((mbedtls_net_context *) ctx)->fd;
330
331 if( fd < 0 )
332 return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
333
334 FD_ZERO( &read_fds );
335 FD_SET( fd, &read_fds );
336
337 tv.tv_sec = timeout / 1000;
338 tv.tv_usec = ( timeout % 1000 ) * 1000;
339
340 ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv );
341 if( ret == 0 )
342 return( MBEDTLS_ERR_SSL_TIMEOUT );
343
344 if( ret < 0 )
345 {
346 if( errno == EINTR )
347 return( MBEDTLS_ERR_SSL_WANT_READ );
348
349 return( MBEDTLS_ERR_NET_RECV_FAILED );
350 }
351
352 return( mbedtls_net_recv( ctx, buf, len ) );
353 }
354
mbedtls_net_send(void * ctx,const unsigned char * buf,size_t len)355 int mbedtls_net_send(void *ctx, const unsigned char *buf, size_t len)
356 {
357 int ret;
358 int fd = ((mbedtls_net_context *) ctx)->fd;
359
360 if( fd < 0 )
361 return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
362
363 ret = (int) write( fd, buf, len );
364
365 if( ret < 0 )
366 {
367 if( net_would_block( ctx ) != 0 )
368 return( MBEDTLS_ERR_SSL_WANT_WRITE );
369
370 if( errno == EPIPE || errno == ECONNRESET )
371 return( MBEDTLS_ERR_NET_CONN_RESET );
372
373 if( errno == EINTR )
374 return( MBEDTLS_ERR_SSL_WANT_WRITE );
375
376 return( MBEDTLS_ERR_NET_SEND_FAILED );
377 }
378
379 return ret;
380 }
381
mbedtls_net_free(mbedtls_net_context * ctx)382 void mbedtls_net_free( mbedtls_net_context *ctx )
383 {
384 if( ctx->fd == -1 )
385 return;
386
387 shutdown( ctx->fd, 2 );
388 close( ctx->fd );
389
390 ctx->fd = -1;
391 }
392
393 #endif /* STM32_USE_SPI_WIFI */
394 #endif /* MBEDTLS_NET_C */
395