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