1 /*
2  *  TCP/IP or UDP/IP networking functions
3  *
4  *  Copyright The Mbed TLS Contributors
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 /* Enable definition of getaddrinfo() even when compiling with -std=c99. Must
21  * be set before config.h, which pulls in glibc's features.h indirectly.
22  * Harmless on other platforms. */
23 #define _POSIX_C_SOURCE 200112L
24 #define _XOPEN_SOURCE 600 /* sockaddr_storage */
25 
26 #include "common.h"
27 
28 #if defined(MBEDTLS_NET_C)
29 
30 #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
31     !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
32     !defined(__HAIKU__) && !defined(__midipix__)
33 #error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h"
34 #endif
35 
36 #if defined(MBEDTLS_PLATFORM_C)
37 #include "mbedtls/platform.h"
38 #else
39 #include <stdlib.h>
40 #endif
41 
42 #include "mbedtls/net_sockets.h"
43 #include "mbedtls/error.h"
44 
45 #include <string.h>
46 
47 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
48     !defined(EFI32)
49 
50 #define IS_EINTR( ret ) ( ( ret ) == WSAEINTR )
51 
52 #if !defined(_WIN32_WINNT)
53 /* Enables getaddrinfo() & Co */
54 #define _WIN32_WINNT 0x0501
55 #endif
56 
57 #include <ws2tcpip.h>
58 
59 #include <winsock2.h>
60 #include <windows.h>
61 #if (_WIN32_WINNT < 0x0501)
62 #include <wspiapi.h>
63 #endif
64 
65 #if defined(_MSC_VER)
66 #if defined(_WIN32_WCE)
67 #pragma comment( lib, "ws2.lib" )
68 #else
69 #pragma comment( lib, "ws2_32.lib" )
70 #endif
71 #endif /* _MSC_VER */
72 
73 #define read(fd,buf,len)        recv( fd, (char*)( buf ), (int)( len ), 0 )
74 #define write(fd,buf,len)       send( fd, (char*)( buf ), (int)( len ), 0 )
75 #define close(fd)               closesocket(fd)
76 
77 static int wsa_init_done = 0;
78 
79 #else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
80 
81 #include <sys/types.h>
82 #include <sys/socket.h>
83 #include <netinet/in.h>
84 #include <arpa/inet.h>
85 #include <sys/time.h>
86 #include <unistd.h>
87 #include <signal.h>
88 #include <fcntl.h>
89 #include <netdb.h>
90 #include <errno.h>
91 
92 #define IS_EINTR( ret ) ( ( ret ) == EINTR )
93 
94 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
95 
96 /* Some MS functions want int and MSVC warns if we pass size_t,
97  * but the standard functions use socklen_t, so cast only for MSVC */
98 #if defined(_MSC_VER)
99 #define MSVC_INT_CAST   (int)
100 #else
101 #define MSVC_INT_CAST
102 #endif
103 
104 #include <stdio.h>
105 
106 #include <time.h>
107 
108 #include <stdint.h>
109 
110 /*
111  * Prepare for using the sockets interface
112  */
net_prepare(void)113 static int net_prepare( void )
114 {
115 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
116     !defined(EFI32)
117     WSADATA wsaData;
118 
119     if( wsa_init_done == 0 )
120     {
121         if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
122             return( MBEDTLS_ERR_NET_SOCKET_FAILED );
123 
124         wsa_init_done = 1;
125     }
126 #else
127 #if !defined(EFIX64) && !defined(EFI32)
128     signal( SIGPIPE, SIG_IGN );
129 #endif
130 #endif
131     return( 0 );
132 }
133 
134 /*
135  * Initialize a context
136  */
mbedtls_net_init(mbedtls_net_context * ctx)137 void mbedtls_net_init( mbedtls_net_context *ctx )
138 {
139     ctx->fd = -1;
140 }
141 
142 /*
143  * Initiate a TCP connection with host:port and the given protocol
144  */
mbedtls_net_connect(mbedtls_net_context * ctx,const char * host,const char * port,int proto)145 int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host,
146                          const char *port, int proto )
147 {
148     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
149     struct addrinfo hints, *addr_list, *cur;
150 
151     if( ( ret = net_prepare() ) != 0 )
152         return( ret );
153 
154     /* Do name resolution with both IPv6 and IPv4 */
155     memset( &hints, 0, sizeof( hints ) );
156     hints.ai_family = AF_UNSPEC;
157     hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
158     hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
159 
160     if( getaddrinfo( host, port, &hints, &addr_list ) != 0 )
161         return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
162 
163     /* Try the sockaddrs until a connection succeeds */
164     ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
165     for( cur = addr_list; cur != NULL; cur = cur->ai_next )
166     {
167         ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
168                             cur->ai_protocol );
169         if( ctx->fd < 0 )
170         {
171             ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
172             continue;
173         }
174 
175         if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 )
176         {
177             ret = 0;
178             break;
179         }
180 
181         close( ctx->fd );
182         ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
183     }
184 
185     freeaddrinfo( addr_list );
186 
187     return( ret );
188 }
189 
190 /*
191  * Create a listening socket on bind_ip:port
192  */
mbedtls_net_bind(mbedtls_net_context * ctx,const char * bind_ip,const char * port,int proto)193 int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto )
194 {
195     int n, ret;
196     struct addrinfo hints, *addr_list, *cur;
197 
198     if( ( ret = net_prepare() ) != 0 )
199         return( ret );
200 
201     /* Bind to IPv6 and/or IPv4, but only in the desired protocol */
202     memset( &hints, 0, sizeof( hints ) );
203     hints.ai_family = AF_UNSPEC;
204     hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
205     hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
206     if( bind_ip == NULL )
207         hints.ai_flags = AI_PASSIVE;
208 
209     if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 )
210         return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
211 
212     /* Try the sockaddrs until a binding succeeds */
213     ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
214     for( cur = addr_list; cur != NULL; cur = cur->ai_next )
215     {
216         ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
217                             cur->ai_protocol );
218         if( ctx->fd < 0 )
219         {
220             ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
221             continue;
222         }
223 
224         n = 1;
225         if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR,
226                         (const char *) &n, sizeof( n ) ) != 0 )
227         {
228             close( ctx->fd );
229             ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
230             continue;
231         }
232 
233         if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 )
234         {
235             close( ctx->fd );
236             ret = MBEDTLS_ERR_NET_BIND_FAILED;
237             continue;
238         }
239 
240         /* Listen only makes sense for TCP */
241         if( proto == MBEDTLS_NET_PROTO_TCP )
242         {
243             if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 )
244             {
245                 close( ctx->fd );
246                 ret = MBEDTLS_ERR_NET_LISTEN_FAILED;
247                 continue;
248             }
249         }
250 
251         /* Bind was successful */
252         ret = 0;
253         break;
254     }
255 
256     freeaddrinfo( addr_list );
257 
258     return( ret );
259 
260 }
261 
262 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
263     !defined(EFI32)
264 /*
265  * Check if the requested operation would be blocking on a non-blocking socket
266  * and thus 'failed' with a negative return value.
267  */
net_would_block(const mbedtls_net_context * ctx)268 static int net_would_block( const mbedtls_net_context *ctx )
269 {
270     ((void) ctx);
271     return( WSAGetLastError() == WSAEWOULDBLOCK );
272 }
273 #else
274 /*
275  * Check if the requested operation would be blocking on a non-blocking socket
276  * and thus 'failed' with a negative return value.
277  *
278  * Note: on a blocking socket this function always returns 0!
279  */
net_would_block(const mbedtls_net_context * ctx)280 static int net_would_block( const mbedtls_net_context *ctx )
281 {
282     int err = errno;
283 
284     /*
285      * Never return 'WOULD BLOCK' on a blocking socket
286      */
287     if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK )
288     {
289         errno = err;
290         return( 0 );
291     }
292 
293     switch( errno = err )
294     {
295 #if defined EAGAIN
296         case EAGAIN:
297 #endif
298 #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
299         case EWOULDBLOCK:
300 #endif
301             return( 1 );
302     }
303     return( 0 );
304 }
305 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
306 
307 /*
308  * Accept a connection from a remote client
309  */
mbedtls_net_accept(mbedtls_net_context * bind_ctx,mbedtls_net_context * client_ctx,void * client_ip,size_t buf_size,size_t * ip_len)310 int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
311                         mbedtls_net_context *client_ctx,
312                         void *client_ip, size_t buf_size, size_t *ip_len )
313 {
314     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
315     int type;
316 
317     struct sockaddr_storage client_addr;
318 
319 #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) ||  \
320     defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) || \
321     defined(socklen_t) || (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L)
322     socklen_t n = (socklen_t) sizeof( client_addr );
323     socklen_t type_len = (socklen_t) sizeof( type );
324 #else
325     int n = (int) sizeof( client_addr );
326     int type_len = (int) sizeof( type );
327 #endif
328 
329     /* Is this a TCP or UDP socket? */
330     if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE,
331                     (void *) &type, &type_len ) != 0 ||
332         ( type != SOCK_STREAM && type != SOCK_DGRAM ) )
333     {
334         return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
335     }
336 
337     if( type == SOCK_STREAM )
338     {
339         /* TCP: actual accept() */
340         ret = client_ctx->fd = (int) accept( bind_ctx->fd,
341                                              (struct sockaddr *) &client_addr, &n );
342     }
343     else
344     {
345         /* UDP: wait for a message, but keep it in the queue */
346         char buf[1] = { 0 };
347 
348         ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK,
349                         (struct sockaddr *) &client_addr, &n );
350 
351 #if defined(_WIN32)
352         if( ret == SOCKET_ERROR &&
353             WSAGetLastError() == WSAEMSGSIZE )
354         {
355             /* We know buf is too small, thanks, just peeking here */
356             ret = 0;
357         }
358 #endif
359     }
360 
361     if( ret < 0 )
362     {
363         if( net_would_block( bind_ctx ) != 0 )
364             return( MBEDTLS_ERR_SSL_WANT_READ );
365 
366         return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
367     }
368 
369     /* UDP: hijack the listening socket to communicate with the client,
370      * then bind a new socket to accept new connections */
371     if( type != SOCK_STREAM )
372     {
373         struct sockaddr_storage local_addr;
374         int one = 1;
375 
376         if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 )
377             return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
378 
379         client_ctx->fd = bind_ctx->fd;
380         bind_ctx->fd   = -1; /* In case we exit early */
381 
382         n = sizeof( struct sockaddr_storage );
383         if( getsockname( client_ctx->fd,
384                          (struct sockaddr *) &local_addr, &n ) != 0 ||
385             ( bind_ctx->fd = (int) socket( local_addr.ss_family,
386                                            SOCK_DGRAM, IPPROTO_UDP ) ) < 0 ||
387             setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR,
388                         (const char *) &one, sizeof( one ) ) != 0 )
389         {
390             return( MBEDTLS_ERR_NET_SOCKET_FAILED );
391         }
392 
393         if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 )
394         {
395             return( MBEDTLS_ERR_NET_BIND_FAILED );
396         }
397     }
398 
399     if( client_ip != NULL )
400     {
401         if( client_addr.ss_family == AF_INET )
402         {
403             struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
404             *ip_len = sizeof( addr4->sin_addr.s_addr );
405 
406             if( buf_size < *ip_len )
407                 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
408 
409             memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len );
410         }
411         else
412         {
413             struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
414             *ip_len = sizeof( addr6->sin6_addr.s6_addr );
415 
416             if( buf_size < *ip_len )
417                 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
418 
419             memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len);
420         }
421     }
422 
423     return( 0 );
424 }
425 
426 /*
427  * Set the socket blocking or non-blocking
428  */
mbedtls_net_set_block(mbedtls_net_context * ctx)429 int mbedtls_net_set_block( mbedtls_net_context *ctx )
430 {
431 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
432     !defined(EFI32)
433     u_long n = 0;
434     return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
435 #else
436     return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) );
437 #endif
438 }
439 
mbedtls_net_set_nonblock(mbedtls_net_context * ctx)440 int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
441 {
442 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
443     !defined(EFI32)
444     u_long n = 1;
445     return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
446 #else
447     return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) );
448 #endif
449 }
450 
451 /*
452  * Check if data is available on the socket
453  */
454 
mbedtls_net_poll(mbedtls_net_context * ctx,uint32_t rw,uint32_t timeout)455 int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout )
456 {
457     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
458     struct timeval tv;
459 
460     fd_set read_fds;
461     fd_set write_fds;
462 
463     int fd = ctx->fd;
464 
465     if( fd < 0 )
466         return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
467 
468 #if defined(__has_feature)
469 #if __has_feature(memory_sanitizer)
470     /* Ensure that memory sanitizers consider read_fds and write_fds as
471      * initialized even on platforms such as Glibc/x86_64 where FD_ZERO
472      * is implemented in assembly. */
473     memset( &read_fds, 0, sizeof( read_fds ) );
474     memset( &write_fds, 0, sizeof( write_fds ) );
475 #endif
476 #endif
477 
478     FD_ZERO( &read_fds );
479     if( rw & MBEDTLS_NET_POLL_READ )
480     {
481         rw &= ~MBEDTLS_NET_POLL_READ;
482         FD_SET( fd, &read_fds );
483     }
484 
485     FD_ZERO( &write_fds );
486     if( rw & MBEDTLS_NET_POLL_WRITE )
487     {
488         rw &= ~MBEDTLS_NET_POLL_WRITE;
489         FD_SET( fd, &write_fds );
490     }
491 
492     if( rw != 0 )
493         return( MBEDTLS_ERR_NET_BAD_INPUT_DATA );
494 
495     tv.tv_sec  = timeout / 1000;
496     tv.tv_usec = ( timeout % 1000 ) * 1000;
497 
498     do
499     {
500         ret = select( fd + 1, &read_fds, &write_fds, NULL,
501                       timeout == (uint32_t) -1 ? NULL : &tv );
502     }
503     while( IS_EINTR( ret ) );
504 
505     if( ret < 0 )
506         return( MBEDTLS_ERR_NET_POLL_FAILED );
507 
508     ret = 0;
509     if( FD_ISSET( fd, &read_fds ) )
510         ret |= MBEDTLS_NET_POLL_READ;
511     if( FD_ISSET( fd, &write_fds ) )
512         ret |= MBEDTLS_NET_POLL_WRITE;
513 
514     return( ret );
515 }
516 
517 /*
518  * Portable usleep helper
519  */
mbedtls_net_usleep(unsigned long usec)520 void mbedtls_net_usleep( unsigned long usec )
521 {
522 #if defined(_WIN32)
523     Sleep( ( usec + 999 ) / 1000 );
524 #else
525     struct timeval tv;
526     tv.tv_sec  = usec / 1000000;
527 #if defined(__unix__) || defined(__unix) || \
528     ( defined(__APPLE__) && defined(__MACH__) )
529     tv.tv_usec = (suseconds_t) usec % 1000000;
530 #else
531     tv.tv_usec = usec % 1000000;
532 #endif
533     select( 0, NULL, NULL, NULL, &tv );
534 #endif
535 }
536 
537 /*
538  * Read at most 'len' characters
539  */
mbedtls_net_recv(void * ctx,unsigned char * buf,size_t len)540 int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
541 {
542     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
543     int fd = ((mbedtls_net_context *) ctx)->fd;
544 
545     if( fd < 0 )
546         return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
547 
548     ret = (int) read( fd, buf, len );
549 
550     if( ret < 0 )
551     {
552         if( net_would_block( ctx ) != 0 )
553             return( MBEDTLS_ERR_SSL_WANT_READ );
554 
555 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
556     !defined(EFI32)
557         if( WSAGetLastError() == WSAECONNRESET )
558             return( MBEDTLS_ERR_NET_CONN_RESET );
559 #else
560         if( errno == EPIPE || errno == ECONNRESET )
561             return( MBEDTLS_ERR_NET_CONN_RESET );
562 
563         if( errno == EINTR )
564             return( MBEDTLS_ERR_SSL_WANT_READ );
565 #endif
566 
567         return( MBEDTLS_ERR_NET_RECV_FAILED );
568     }
569 
570     return( ret );
571 }
572 
573 /*
574  * Read at most 'len' characters, blocking for at most 'timeout' ms
575  */
mbedtls_net_recv_timeout(void * ctx,unsigned char * buf,size_t len,uint32_t timeout)576 int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf,
577                               size_t len, uint32_t timeout )
578 {
579     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
580     struct timeval tv;
581     fd_set read_fds;
582     int fd = ((mbedtls_net_context *) ctx)->fd;
583 
584     if( fd < 0 )
585         return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
586 
587     FD_ZERO( &read_fds );
588     FD_SET( fd, &read_fds );
589 
590     tv.tv_sec  = timeout / 1000;
591     tv.tv_usec = ( timeout % 1000 ) * 1000;
592 
593     ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv );
594 
595     /* Zero fds ready means we timed out */
596     if( ret == 0 )
597         return( MBEDTLS_ERR_SSL_TIMEOUT );
598 
599     if( ret < 0 )
600     {
601 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
602     !defined(EFI32)
603         if( WSAGetLastError() == WSAEINTR )
604             return( MBEDTLS_ERR_SSL_WANT_READ );
605 #else
606         if( errno == EINTR )
607             return( MBEDTLS_ERR_SSL_WANT_READ );
608 #endif
609 
610         return( MBEDTLS_ERR_NET_RECV_FAILED );
611     }
612 
613     /* This call will not block */
614     return( mbedtls_net_recv( ctx, buf, len ) );
615 }
616 
617 /*
618  * Write at most 'len' characters
619  */
mbedtls_net_send(void * ctx,const unsigned char * buf,size_t len)620 int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
621 {
622     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
623     int fd = ((mbedtls_net_context *) ctx)->fd;
624 
625     if( fd < 0 )
626         return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
627 
628     ret = (int) write( fd, buf, len );
629 
630     if( ret < 0 )
631     {
632         if( net_would_block( ctx ) != 0 )
633             return( MBEDTLS_ERR_SSL_WANT_WRITE );
634 
635 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
636     !defined(EFI32)
637         if( WSAGetLastError() == WSAECONNRESET )
638             return( MBEDTLS_ERR_NET_CONN_RESET );
639 #else
640         if( errno == EPIPE || errno == ECONNRESET )
641             return( MBEDTLS_ERR_NET_CONN_RESET );
642 
643         if( errno == EINTR )
644             return( MBEDTLS_ERR_SSL_WANT_WRITE );
645 #endif
646 
647         return( MBEDTLS_ERR_NET_SEND_FAILED );
648     }
649 
650     return( ret );
651 }
652 
653 /*
654  * Close the connection
655  */
mbedtls_net_close(mbedtls_net_context * ctx)656 void mbedtls_net_close( mbedtls_net_context *ctx )
657 {
658     if( ctx->fd == -1 )
659         return;
660 
661     close( ctx->fd );
662 
663     ctx->fd = -1;
664 }
665 
666 /*
667  * Gracefully close the connection
668  */
mbedtls_net_free(mbedtls_net_context * ctx)669 void mbedtls_net_free( mbedtls_net_context *ctx )
670 {
671     if( ctx->fd == -1 )
672         return;
673 
674     shutdown( ctx->fd, 2 );
675     close( ctx->fd );
676 
677     ctx->fd = -1;
678 }
679 
680 #endif /* MBEDTLS_NET_C */
681