Rtos API example

Committer:
marcozecchini
Date:
Sat Feb 23 12:13:36 2019 +0000
Revision:
0:9fca2b23d0ba
final commit

Who changed what in which revision?

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