RTC auf true

Committer:
kevman
Date:
Wed Nov 28 15:10:15 2018 +0000
Revision:
0:38ceb79fef03
RTC modified

Who changed what in which revision?

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