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