This is a fork due to permission issues

Dependencies:   mbed Socket lwip-eth lwip-sys lwip

Fork of 6_songs-from-the-cloud by MakingMusicWorkshop

Committer:
maclobdell
Date:
Wed May 18 19:06:32 2016 +0000
Revision:
0:f7c60d3e7b8a
clean version

Who changed what in which revision?

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