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