Preliminary main mbed library for nexpaq development

Committer:
nexpaq
Date:
Fri Nov 04 20:27:58 2016 +0000
Revision:
0:6c56fb4bc5f0
Moving to library for sharing updates

Who changed what in which revision?

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