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