mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 17 23:23:45 2019 +0000
Revision:
0:5b88d5760320
Child:
1:9db0e321a9f4
mbed-os5 only for TYBLE16

Who changed what in which revision?

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