1 /*
2 * TCP/IP or UDP/IP networking functions
3 * modified for LWIP support on ESP32
4 *
5 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
6 * Additions Copyright (C) 2015 Angus Gratton
7 * SPDX-License-Identifier: Apache-2.0
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License"); you may
10 * not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 * This file is part of mbed TLS (https://tls.mbed.org)
22 */
23
24 #if defined(CONFIG_SAL) || defined(CONFIG_TCPIP)
25
26 #if !defined(MBEDTLS_CONFIG_FILE)
27 #include "mbedtls/config.h"
28 #else
29 #include MBEDTLS_CONFIG_FILE
30 #endif
31
32 #if !defined(MBEDTLS_NET_C)
33
34 #if defined(MBEDTLS_NET_C_ALT)
35
36 #if defined(MBEDTLS_PLATFORM_C)
37 #include "mbedtls/platform.h"
38 #else
39 #include <stdlib.h>
40 #define mbedtls_calloc calloc
41 #define mbedtls_free free
42 #define mbedtls_time time
43 #define mbedtls_time_t time_t
44 #endif
45
46 #include "mbedtls/net_sockets.h"
47
48 #include <string.h>
49 #include <sys/types.h>
50 #include <sys/select.h>
51 #include <unistd.h>
52 #include <lwip/netdb.h>
53 #include <stdlib.h>
54 #include <stdio.h>
55 #include <time.h>
56 #include <stdint.h>
57
58 /*
59 * Prepare for using the sockets interface
60 */
net_prepare(void)61 static int net_prepare( void )
62 {
63 return ( 0 );
64 }
65
66 /*
67 * Initialize a context
68 */
mbedtls_net_init(mbedtls_net_context * ctx)69 void mbedtls_net_init( mbedtls_net_context *ctx )
70 {
71 ctx->fd = -1;
72 }
73
74 /*
75 * Initiate a TCP connection with host:port and the given protocol
76 */
mbedtls_net_connect(mbedtls_net_context * ctx,const char * host,const char * port,int proto)77 int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto )
78 {
79 int ret;
80 struct addrinfo hints, *addr_list, *cur;
81
82 /* Do name resolution with both IPv6 and IPv4 */
83 memset( &hints, 0, sizeof( hints ) );
84 hints.ai_family = AF_UNSPEC;
85 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
86 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
87
88 if( getaddrinfo( host, port, &hints, &addr_list ) != 0 )
89 return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
90
91 /* Try the sockaddrs until a connection succeeds */
92 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
93 for( cur = addr_list; cur != NULL; cur = cur->ai_next )
94 {
95 ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
96 cur->ai_protocol );
97 if( ctx->fd < 0 )
98 {
99 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
100 continue;
101 }
102
103 if( connect( ctx->fd, cur->ai_addr, (socklen_t)cur->ai_addrlen ) == 0 )
104 {
105 ret = 0;
106 break;
107 }
108
109 close( ctx->fd );
110 ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
111 }
112
113 freeaddrinfo( addr_list );
114
115 return( ret );
116 }
117
118 /*
119 * Create a listening socket on bind_ip:port
120 */
mbedtls_net_bind(mbedtls_net_context * ctx,const char * bind_ip,const char * port,int proto)121 int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto )
122 {
123 int ret;
124 struct addrinfo hints, *addr_list, *cur;
125 struct sockaddr_in *serv_addr = NULL;
126 #if SO_REUSE
127 int n = 1;
128 #endif
129
130 if ( ( ret = net_prepare() ) != 0 ) {
131 return ( ret );
132 }
133
134 /* Bind to IPv6 and/or IPv4, but only in the desired protocol */
135 memset( &hints, 0, sizeof( hints ) );
136 hints.ai_family = AF_UNSPEC;
137 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
138 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
139
140 if ( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) {
141 return ( MBEDTLS_ERR_NET_UNKNOWN_HOST );
142 }
143
144 /* Try the sockaddrs until a binding succeeds */
145 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
146 for ( cur = addr_list; cur != NULL; cur = cur->ai_next ) {
147 int fd = socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol );
148 if ( fd < 0 ) {
149 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
150 continue;
151 }
152
153 /*SO_REUSEADDR option dafault is disable in source code(lwip)*/
154 #if SO_REUSE
155 if ( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
156 (const char *) &n, sizeof( n ) ) != 0 ) {
157 close( fd );
158 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
159 continue;
160 }
161 #endif
162 /*bind interface dafault don't process the addr is 0xffffffff for TCP Protocol*/
163 serv_addr = (struct sockaddr_in *)cur->ai_addr;
164 serv_addr->sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
165 if ( bind( fd, (struct sockaddr *)serv_addr, cur->ai_addrlen ) != 0 ) {
166 close( fd );
167 ret = MBEDTLS_ERR_NET_BIND_FAILED;
168 continue;
169 }
170
171 /* Listen only makes sense for TCP */
172 if ( proto == MBEDTLS_NET_PROTO_TCP ) {
173 if ( listen( fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 ) {
174 close( fd );
175 ret = MBEDTLS_ERR_NET_LISTEN_FAILED;
176 continue;
177 }
178 }
179
180 /* I we ever get there, it's a success */
181 ctx->fd = fd;
182 ret = 0;
183 break;
184 }
185
186 freeaddrinfo( addr_list );
187
188 return ( ret );
189
190 }
191
192 /*
193 * Check if the requested operation would be blocking on a non-blocking socket
194 * and thus 'failed' with a negative return value.
195 *
196 * Note: on a blocking socket this function always returns 0!
197 */
net_would_block(const mbedtls_net_context * ctx)198 static int net_would_block( const mbedtls_net_context *ctx )
199 {
200 int error = errno;
201
202 /*
203 * Never return 'WOULD BLOCK' on a non-blocking socket
204 */
205 if ( ( fcntl( ctx->fd, F_GETFL, 0) & O_NONBLOCK ) != O_NONBLOCK ) {
206 errno = error;
207 return ( 0 );
208 }
209
210 switch ( errno = error ) {
211 #if defined EAGAIN
212 case EAGAIN:
213 #endif
214 #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
215 case EWOULDBLOCK:
216 #endif
217 return ( 1 );
218 }
219 return ( 0 );
220 }
221
222 /*
223 * Accept a connection from a remote client
224 */
mbedtls_net_accept(mbedtls_net_context * bind_ctx,mbedtls_net_context * client_ctx,void * client_ip,size_t buf_size,size_t * ip_len)225 int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
226 mbedtls_net_context *client_ctx,
227 void *client_ip, size_t buf_size, size_t *ip_len )
228 {
229 int ret;
230 int type;
231
232 struct sockaddr_in client_addr;
233
234 socklen_t n = (socklen_t) sizeof( client_addr );
235 socklen_t type_len = (socklen_t) sizeof( type );
236
237 /* Is this a TCP or UDP socket? */
238 if ( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE,
239 (void *) &type, (socklen_t *) &type_len ) != 0 ||
240 ( type != SOCK_STREAM && type != SOCK_DGRAM ) ) {
241 return ( MBEDTLS_ERR_NET_ACCEPT_FAILED );
242 }
243
244 if ( type == SOCK_STREAM ) {
245 /* TCP: actual accept() */
246 ret = client_ctx->fd = (int) accept( bind_ctx->fd,
247 (struct sockaddr *) &client_addr, &n );
248 } else {
249 /* UDP: wait for a message, but keep it in the queue */
250 char buf[1] = { 0 };
251
252 ret = recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK,
253 (struct sockaddr *) &client_addr, &n );
254
255 }
256
257 if ( ret < 0 ) {
258 if ( net_would_block( bind_ctx ) != 0 ) {
259 return ( MBEDTLS_ERR_SSL_WANT_READ );
260 }
261
262 return ( MBEDTLS_ERR_NET_ACCEPT_FAILED );
263 }
264
265 /* UDP: hijack the listening socket to communicate with the client,
266 * then bind a new socket to accept new connections */
267 if ( type != SOCK_STREAM ) {
268 struct sockaddr_in local_addr;
269 int one = 1;
270
271 if ( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 ) {
272 return ( MBEDTLS_ERR_NET_ACCEPT_FAILED );
273 }
274
275 client_ctx->fd = bind_ctx->fd;
276 bind_ctx->fd = -1; /* In case we exit early */
277
278 n = sizeof( struct sockaddr_in );
279 if ( getsockname( client_ctx->fd,
280 (struct sockaddr *) &local_addr, &n ) != 0 ||
281 ( bind_ctx->fd = (int) socket( AF_INET,
282 SOCK_DGRAM, IPPROTO_UDP ) ) < 0 ||
283 setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR,
284 (const char *) &one, sizeof( one ) ) != 0 ) {
285 return ( MBEDTLS_ERR_NET_SOCKET_FAILED );
286 }
287
288 if ( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 ) {
289 return ( MBEDTLS_ERR_NET_BIND_FAILED );
290 }
291 }
292
293 if ( client_ip != NULL ) {
294 struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
295 *ip_len = sizeof( addr4->sin_addr.s_addr );
296
297 if ( buf_size < *ip_len ) {
298 return ( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
299 }
300
301 memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len );
302 }
303
304 return ( 0 );
305 }
306
307 /*
308 * Set the socket blocking or non-blocking
309 */
mbedtls_net_set_block(mbedtls_net_context * ctx)310 int mbedtls_net_set_block( mbedtls_net_context *ctx )
311 {
312 return ( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL, 0 ) & ~O_NONBLOCK ) );
313 }
314
mbedtls_net_set_nonblock(mbedtls_net_context * ctx)315 int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
316 {
317 return ( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL, 0 ) | O_NONBLOCK ) );
318 }
319
320 /*
321 * Portable usleep helper
322 */
mbedtls_net_usleep(unsigned long usec)323 void mbedtls_net_usleep( unsigned long usec )
324 {
325 struct timeval tv;
326 tv.tv_sec = usec / 1000000;
327 tv.tv_usec = usec % 1000000;
328 select( 0, NULL, NULL, NULL, &tv );
329 }
330
331 /*
332 * Read at most 'len' characters
333 */
mbedtls_net_recv(void * ctx,unsigned char * buf,size_t len)334 int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
335 {
336 int ret;
337 int fd = ((mbedtls_net_context *) ctx)->fd;
338
339 if( fd < 0 )
340 return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
341
342 ret = (int) recv( fd, buf, len, 0);
343 // DBG("@@ret:%d, errno:%d", ret, errno);
344 if( ret < 0 )
345 {
346 // if( errno == EAGAIN )
347 // return( MBEDTLS_ERR_SSL_WANT_READ );
348
349 if( errno == EPIPE || errno == ECONNRESET )
350 return( MBEDTLS_ERR_NET_CONN_RESET );
351
352 if( errno == EINTR )
353 return( MBEDTLS_ERR_SSL_WANT_READ );
354
355 return( MBEDTLS_ERR_NET_RECV_FAILED );
356 }
357
358 return( ret );
359 }
360
361 /*
362 * Read at most 'len' characters, blocking for at most 'timeout' ms
363 */
mbedtls_net_recv_timeout(void * ctx,unsigned char * buf,size_t len,uint32_t timeout)364 int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
365 uint32_t timeout )
366 {
367 int ret;
368 struct timeval tv;
369 fd_set read_fds;
370 int fd = ((mbedtls_net_context *) ctx)->fd;
371
372 if( fd < 0 )
373 return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
374
375 FD_ZERO( &read_fds );
376 FD_SET( fd, &read_fds );
377
378 tv.tv_sec = timeout / 1000;
379 tv.tv_usec = ( timeout % 1000 ) * 1000;
380
381 /* no wait if timeout == 0 */
382 ret = select( fd + 1, &read_fds, NULL, NULL, &tv );
383 // printf("%s, %d, select ret:%d\n", __func__, __LINE__, ret);
384 /* Zero fds ready means we timed out */
385 if( ret == 0 )
386 return( MBEDTLS_ERR_SSL_TIMEOUT );
387
388 if( ret < 0 )
389 {
390 if( errno == EINTR )
391 return( MBEDTLS_ERR_SSL_WANT_READ );
392
393 return( MBEDTLS_ERR_NET_RECV_FAILED );
394 }
395
396 /* This call will not block */
397 return( mbedtls_net_recv( ctx, buf, len ) );
398 }
399
400 /*
401 * Write at most 'len' characters
402 */
mbedtls_net_send(void * ctx,const unsigned char * buf,size_t len)403 int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
404 {
405 int ret;
406 int fd = ((mbedtls_net_context *) ctx)->fd;
407
408 ret = (int) send( fd, buf, len, 0);
409
410 if( ret < 0 )
411 {
412 if( errno == EPIPE || errno == ECONNRESET )
413 return( MBEDTLS_ERR_NET_CONN_RESET );
414
415 if( errno == EINTR )
416 return( MBEDTLS_ERR_SSL_WANT_WRITE );
417
418 return( MBEDTLS_ERR_NET_SEND_FAILED );
419 }
420
421 return( ret );
422 }
423
424 /*
425 * Gracefully close the connection
426 */
mbedtls_net_free(mbedtls_net_context * ctx)427 void mbedtls_net_free( mbedtls_net_context *ctx )
428 {
429 if ( ctx->fd == -1 ) {
430 return;
431 }
432
433 shutdown( ctx->fd, 2 );
434 close( ctx->fd );
435
436 ctx->fd = -1;
437 }
438
439 #endif /* MBEDTLS_NET_C_ALT */
440
441 #endif /* MBEDTLS_NET_C */
442
443 #endif
444