mbedtls ported to mbed-classic

Fork of mbedtls by Christopher Haster

Committer:
Brian Daniels
Date:
Thu Apr 07 11:11:18 2016 +0100
Revision:
4:bef26f687287
Parent:
1:24750b9ad5ef
Adding ported selftest test case

Who changed what in which revision?

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