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