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