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