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