mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

Committer:
ansond
Date:
Thu Jun 11 03:27:03 2015 +0000
Revision:
0:137634ff4186
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:137634ff4186 1 /*
ansond 0:137634ff4186 2 * TCP networking functions
ansond 0:137634ff4186 3 *
ansond 0:137634ff4186 4 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
ansond 0:137634ff4186 5 *
ansond 0:137634ff4186 6 * This file is part of mbed TLS (https://tls.mbed.org)
ansond 0:137634ff4186 7 *
ansond 0:137634ff4186 8 * This program is free software; you can redistribute it and/or modify
ansond 0:137634ff4186 9 * it under the terms of the GNU General Public License as published by
ansond 0:137634ff4186 10 * the Free Software Foundation; either version 2 of the License, or
ansond 0:137634ff4186 11 * (at your option) any later version.
ansond 0:137634ff4186 12 *
ansond 0:137634ff4186 13 * This program is distributed in the hope that it will be useful,
ansond 0:137634ff4186 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ansond 0:137634ff4186 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ansond 0:137634ff4186 16 * GNU General Public License for more details.
ansond 0:137634ff4186 17 *
ansond 0:137634ff4186 18 * You should have received a copy of the GNU General Public License along
ansond 0:137634ff4186 19 * with this program; if not, write to the Free Software Foundation, Inc.,
ansond 0:137634ff4186 20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ansond 0:137634ff4186 21 */
ansond 0:137634ff4186 22
ansond 0:137634ff4186 23 #if !defined(POLARSSL_CONFIG_FILE)
ansond 0:137634ff4186 24 #include "polarssl/config.h"
ansond 0:137634ff4186 25 #else
ansond 0:137634ff4186 26 #include POLARSSL_CONFIG_FILE
ansond 0:137634ff4186 27 #endif
ansond 0:137634ff4186 28
ansond 0:137634ff4186 29 #if defined(POLARSSL_NET_C)
ansond 0:137634ff4186 30
ansond 0:137634ff4186 31 #include "polarssl/net.h"
ansond 0:137634ff4186 32
ansond 0:137634ff4186 33 #include <string.h>
ansond 0:137634ff4186 34
ansond 0:137634ff4186 35 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
ansond 0:137634ff4186 36 !defined(EFI32)
ansond 0:137634ff4186 37
ansond 0:137634ff4186 38 #if defined(POLARSSL_HAVE_IPV6)
ansond 0:137634ff4186 39 #ifdef _WIN32_WINNT
ansond 0:137634ff4186 40 #undef _WIN32_WINNT
ansond 0:137634ff4186 41 #endif
ansond 0:137634ff4186 42 /* Enables getaddrinfo() & Co */
ansond 0:137634ff4186 43 #define _WIN32_WINNT 0x0501
ansond 0:137634ff4186 44 #include <ws2tcpip.h>
ansond 0:137634ff4186 45 #endif
ansond 0:137634ff4186 46
ansond 0:137634ff4186 47 #include <winsock2.h>
ansond 0:137634ff4186 48 #include <windows.h>
ansond 0:137634ff4186 49
ansond 0:137634ff4186 50 #if defined(_MSC_VER)
ansond 0:137634ff4186 51 #if defined(_WIN32_WCE)
ansond 0:137634ff4186 52 #pragma comment( lib, "ws2.lib" )
ansond 0:137634ff4186 53 #else
ansond 0:137634ff4186 54 #pragma comment( lib, "ws2_32.lib" )
ansond 0:137634ff4186 55 #endif
ansond 0:137634ff4186 56 #endif /* _MSC_VER */
ansond 0:137634ff4186 57
ansond 0:137634ff4186 58 #define read(fd,buf,len) recv(fd,(char*)buf,(int) len,0)
ansond 0:137634ff4186 59 #define write(fd,buf,len) send(fd,(char*)buf,(int) len,0)
ansond 0:137634ff4186 60 #define close(fd) closesocket(fd)
ansond 0:137634ff4186 61
ansond 0:137634ff4186 62 static int wsa_init_done = 0;
ansond 0:137634ff4186 63
ansond 0:137634ff4186 64 #else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
ansond 0:137634ff4186 65
ansond 0:137634ff4186 66 #include <sys/types.h>
ansond 0:137634ff4186 67 #include <sys/socket.h>
ansond 0:137634ff4186 68 #include <netinet/in.h>
ansond 0:137634ff4186 69 #include <arpa/inet.h>
ansond 0:137634ff4186 70 #if defined(POLARSSL_HAVE_TIME)
ansond 0:137634ff4186 71 #include <sys/time.h>
ansond 0:137634ff4186 72 #endif
ansond 0:137634ff4186 73 #include <unistd.h>
ansond 0:137634ff4186 74 #include <signal.h>
ansond 0:137634ff4186 75 #include <fcntl.h>
ansond 0:137634ff4186 76 #include <netdb.h>
ansond 0:137634ff4186 77 #include <errno.h>
ansond 0:137634ff4186 78
ansond 0:137634ff4186 79 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || \
ansond 0:137634ff4186 80 defined(__DragonFly__)
ansond 0:137634ff4186 81 #include <sys/endian.h>
ansond 0:137634ff4186 82 #elif defined(__APPLE__) || defined(HAVE_MACHINE_ENDIAN_H) || \
ansond 0:137634ff4186 83 defined(EFIX64) || defined(EFI32)
ansond 0:137634ff4186 84 #include <machine/endian.h>
ansond 0:137634ff4186 85 #elif defined(sun)
ansond 0:137634ff4186 86 #include <sys/isa_defs.h>
ansond 0:137634ff4186 87 #elif defined(_AIX) || defined(HAVE_ARPA_NAMESER_COMPAT_H)
ansond 0:137634ff4186 88 #include <arpa/nameser_compat.h>
ansond 0:137634ff4186 89 #else
ansond 0:137634ff4186 90 #include <endian.h>
ansond 0:137634ff4186 91 #endif
ansond 0:137634ff4186 92
ansond 0:137634ff4186 93 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
ansond 0:137634ff4186 94
ansond 0:137634ff4186 95 #include <stdlib.h>
ansond 0:137634ff4186 96 #include <stdio.h>
ansond 0:137634ff4186 97
ansond 0:137634ff4186 98 #if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
ansond 0:137634ff4186 99 !defined(EFI32)
ansond 0:137634ff4186 100 #define snprintf _snprintf
ansond 0:137634ff4186 101 #endif
ansond 0:137634ff4186 102
ansond 0:137634ff4186 103 #if defined(POLARSSL_HAVE_TIME)
ansond 0:137634ff4186 104 #include <time.h>
ansond 0:137634ff4186 105 #endif
ansond 0:137634ff4186 106
ansond 0:137634ff4186 107 #if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
ansond 0:137634ff4186 108 #include <basetsd.h>
ansond 0:137634ff4186 109 typedef UINT32 uint32_t;
ansond 0:137634ff4186 110 #else
ansond 0:137634ff4186 111 #include <inttypes.h>
ansond 0:137634ff4186 112 #endif
ansond 0:137634ff4186 113
ansond 0:137634ff4186 114 /*
ansond 0:137634ff4186 115 * htons() is not always available.
ansond 0:137634ff4186 116 * By default go for LITTLE_ENDIAN variant. Otherwise hope for _BYTE_ORDER and
ansond 0:137634ff4186 117 * __BIG_ENDIAN to help determine endianness.
ansond 0:137634ff4186 118 */
ansond 0:137634ff4186 119 #if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
ansond 0:137634ff4186 120 __BYTE_ORDER == __BIG_ENDIAN
ansond 0:137634ff4186 121 #define POLARSSL_HTONS(n) (n)
ansond 0:137634ff4186 122 #define POLARSSL_HTONL(n) (n)
ansond 0:137634ff4186 123 #else
ansond 0:137634ff4186 124 #define POLARSSL_HTONS(n) ((((unsigned short)(n) & 0xFF ) << 8 ) | \
ansond 0:137634ff4186 125 (((unsigned short)(n) & 0xFF00 ) >> 8 ))
ansond 0:137634ff4186 126 #define POLARSSL_HTONL(n) ((((unsigned long )(n) & 0xFF ) << 24) | \
ansond 0:137634ff4186 127 (((unsigned long )(n) & 0xFF00 ) << 8 ) | \
ansond 0:137634ff4186 128 (((unsigned long )(n) & 0xFF0000 ) >> 8 ) | \
ansond 0:137634ff4186 129 (((unsigned long )(n) & 0xFF000000) >> 24))
ansond 0:137634ff4186 130 #endif
ansond 0:137634ff4186 131
ansond 0:137634ff4186 132 #if defined(POLARSSL_PLATFORM_C)
ansond 0:137634ff4186 133 #include "polarssl/platform.h"
ansond 0:137634ff4186 134 #else
ansond 0:137634ff4186 135 #define polarssl_snprintf snprintf
ansond 0:137634ff4186 136 #endif
ansond 0:137634ff4186 137
ansond 0:137634ff4186 138 unsigned short net_htons( unsigned short n );
ansond 0:137634ff4186 139 unsigned long net_htonl( unsigned long n );
ansond 0:137634ff4186 140 #define net_htons(n) POLARSSL_HTONS(n)
ansond 0:137634ff4186 141 #define net_htonl(n) POLARSSL_HTONL(n)
ansond 0:137634ff4186 142
ansond 0:137634ff4186 143 /*
ansond 0:137634ff4186 144 * Prepare for using the sockets interface
ansond 0:137634ff4186 145 */
ansond 0:137634ff4186 146 static int net_prepare( void )
ansond 0:137634ff4186 147 {
ansond 0:137634ff4186 148 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
ansond 0:137634ff4186 149 !defined(EFI32)
ansond 0:137634ff4186 150 WSADATA wsaData;
ansond 0:137634ff4186 151
ansond 0:137634ff4186 152 if( wsa_init_done == 0 )
ansond 0:137634ff4186 153 {
ansond 0:137634ff4186 154 if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
ansond 0:137634ff4186 155 return( POLARSSL_ERR_NET_SOCKET_FAILED );
ansond 0:137634ff4186 156
ansond 0:137634ff4186 157 wsa_init_done = 1;
ansond 0:137634ff4186 158 }
ansond 0:137634ff4186 159 #else
ansond 0:137634ff4186 160 #if !defined(EFIX64) && !defined(EFI32)
ansond 0:137634ff4186 161 signal( SIGPIPE, SIG_IGN );
ansond 0:137634ff4186 162 #endif
ansond 0:137634ff4186 163 #endif
ansond 0:137634ff4186 164 return( 0 );
ansond 0:137634ff4186 165 }
ansond 0:137634ff4186 166
ansond 0:137634ff4186 167 /*
ansond 0:137634ff4186 168 * Initiate a TCP connection with host:port
ansond 0:137634ff4186 169 */
ansond 0:137634ff4186 170 int net_connect( int *fd, const char *host, int port )
ansond 0:137634ff4186 171 {
ansond 0:137634ff4186 172 #if defined(POLARSSL_HAVE_IPV6)
ansond 0:137634ff4186 173 int ret;
ansond 0:137634ff4186 174 struct addrinfo hints, *addr_list, *cur;
ansond 0:137634ff4186 175 char port_str[6];
ansond 0:137634ff4186 176
ansond 0:137634ff4186 177 if( ( ret = net_prepare() ) != 0 )
ansond 0:137634ff4186 178 return( ret );
ansond 0:137634ff4186 179
ansond 0:137634ff4186 180 /* getaddrinfo expects port as a string */
ansond 0:137634ff4186 181 memset( port_str, 0, sizeof( port_str ) );
ansond 0:137634ff4186 182 polarssl_snprintf( port_str, sizeof( port_str ), "%d", port );
ansond 0:137634ff4186 183
ansond 0:137634ff4186 184 /* Do name resolution with both IPv6 and IPv4, but only TCP */
ansond 0:137634ff4186 185 memset( &hints, 0, sizeof( hints ) );
ansond 0:137634ff4186 186 hints.ai_family = AF_UNSPEC;
ansond 0:137634ff4186 187 hints.ai_socktype = SOCK_STREAM;
ansond 0:137634ff4186 188 hints.ai_protocol = IPPROTO_TCP;
ansond 0:137634ff4186 189
ansond 0:137634ff4186 190 if( getaddrinfo( host, port_str, &hints, &addr_list ) != 0 )
ansond 0:137634ff4186 191 return( POLARSSL_ERR_NET_UNKNOWN_HOST );
ansond 0:137634ff4186 192
ansond 0:137634ff4186 193 /* Try the sockaddrs until a connection succeeds */
ansond 0:137634ff4186 194 ret = POLARSSL_ERR_NET_UNKNOWN_HOST;
ansond 0:137634ff4186 195 for( cur = addr_list; cur != NULL; cur = cur->ai_next )
ansond 0:137634ff4186 196 {
ansond 0:137634ff4186 197 *fd = (int) socket( cur->ai_family, cur->ai_socktype,
ansond 0:137634ff4186 198 cur->ai_protocol );
ansond 0:137634ff4186 199 if( *fd < 0 )
ansond 0:137634ff4186 200 {
ansond 0:137634ff4186 201 ret = POLARSSL_ERR_NET_SOCKET_FAILED;
ansond 0:137634ff4186 202 continue;
ansond 0:137634ff4186 203 }
ansond 0:137634ff4186 204
ansond 0:137634ff4186 205 if( connect( *fd, cur->ai_addr, cur->ai_addrlen ) == 0 )
ansond 0:137634ff4186 206 {
ansond 0:137634ff4186 207 ret = 0;
ansond 0:137634ff4186 208 break;
ansond 0:137634ff4186 209 }
ansond 0:137634ff4186 210
ansond 0:137634ff4186 211 close( *fd );
ansond 0:137634ff4186 212 ret = POLARSSL_ERR_NET_CONNECT_FAILED;
ansond 0:137634ff4186 213 }
ansond 0:137634ff4186 214
ansond 0:137634ff4186 215 freeaddrinfo( addr_list );
ansond 0:137634ff4186 216
ansond 0:137634ff4186 217 return( ret );
ansond 0:137634ff4186 218
ansond 0:137634ff4186 219 #else
ansond 0:137634ff4186 220 /* Legacy IPv4-only version */
ansond 0:137634ff4186 221
ansond 0:137634ff4186 222 int ret;
ansond 0:137634ff4186 223 struct sockaddr_in server_addr;
ansond 0:137634ff4186 224 struct hostent *server_host;
ansond 0:137634ff4186 225
ansond 0:137634ff4186 226 if( ( ret = net_prepare() ) != 0 )
ansond 0:137634ff4186 227 return( ret );
ansond 0:137634ff4186 228
ansond 0:137634ff4186 229 if( ( server_host = gethostbyname( host ) ) == NULL )
ansond 0:137634ff4186 230 return( POLARSSL_ERR_NET_UNKNOWN_HOST );
ansond 0:137634ff4186 231
ansond 0:137634ff4186 232 if( ( *fd = (int) socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 )
ansond 0:137634ff4186 233 return( POLARSSL_ERR_NET_SOCKET_FAILED );
ansond 0:137634ff4186 234
ansond 0:137634ff4186 235 memcpy( (void *) &server_addr.sin_addr,
ansond 0:137634ff4186 236 (void *) server_host->h_addr,
ansond 0:137634ff4186 237 server_host->h_length );
ansond 0:137634ff4186 238
ansond 0:137634ff4186 239 server_addr.sin_family = AF_INET;
ansond 0:137634ff4186 240 server_addr.sin_port = net_htons( port );
ansond 0:137634ff4186 241
ansond 0:137634ff4186 242 if( connect( *fd, (struct sockaddr *) &server_addr,
ansond 0:137634ff4186 243 sizeof( server_addr ) ) < 0 )
ansond 0:137634ff4186 244 {
ansond 0:137634ff4186 245 close( *fd );
ansond 0:137634ff4186 246 return( POLARSSL_ERR_NET_CONNECT_FAILED );
ansond 0:137634ff4186 247 }
ansond 0:137634ff4186 248
ansond 0:137634ff4186 249 return( 0 );
ansond 0:137634ff4186 250 #endif /* POLARSSL_HAVE_IPV6 */
ansond 0:137634ff4186 251 }
ansond 0:137634ff4186 252
ansond 0:137634ff4186 253 /*
ansond 0:137634ff4186 254 * Create a listening socket on bind_ip:port
ansond 0:137634ff4186 255 */
ansond 0:137634ff4186 256 int net_bind( int *fd, const char *bind_ip, int port )
ansond 0:137634ff4186 257 {
ansond 0:137634ff4186 258 #if defined(POLARSSL_HAVE_IPV6)
ansond 0:137634ff4186 259 int n, ret;
ansond 0:137634ff4186 260 struct addrinfo hints, *addr_list, *cur;
ansond 0:137634ff4186 261 char port_str[6];
ansond 0:137634ff4186 262
ansond 0:137634ff4186 263 if( ( ret = net_prepare() ) != 0 )
ansond 0:137634ff4186 264 return( ret );
ansond 0:137634ff4186 265
ansond 0:137634ff4186 266 /* getaddrinfo expects port as a string */
ansond 0:137634ff4186 267 memset( port_str, 0, sizeof( port_str ) );
ansond 0:137634ff4186 268 polarssl_snprintf( port_str, sizeof( port_str ), "%d", port );
ansond 0:137634ff4186 269
ansond 0:137634ff4186 270 /* Bind to IPv6 and/or IPv4, but only in TCP */
ansond 0:137634ff4186 271 memset( &hints, 0, sizeof( hints ) );
ansond 0:137634ff4186 272 hints.ai_family = AF_UNSPEC;
ansond 0:137634ff4186 273 hints.ai_socktype = SOCK_STREAM;
ansond 0:137634ff4186 274 hints.ai_protocol = IPPROTO_TCP;
ansond 0:137634ff4186 275 if( bind_ip == NULL )
ansond 0:137634ff4186 276 hints.ai_flags = AI_PASSIVE;
ansond 0:137634ff4186 277
ansond 0:137634ff4186 278 if( getaddrinfo( bind_ip, port_str, &hints, &addr_list ) != 0 )
ansond 0:137634ff4186 279 return( POLARSSL_ERR_NET_UNKNOWN_HOST );
ansond 0:137634ff4186 280
ansond 0:137634ff4186 281 /* Try the sockaddrs until a binding succeeds */
ansond 0:137634ff4186 282 ret = POLARSSL_ERR_NET_UNKNOWN_HOST;
ansond 0:137634ff4186 283 for( cur = addr_list; cur != NULL; cur = cur->ai_next )
ansond 0:137634ff4186 284 {
ansond 0:137634ff4186 285 *fd = (int) socket( cur->ai_family, cur->ai_socktype,
ansond 0:137634ff4186 286 cur->ai_protocol );
ansond 0:137634ff4186 287 if( *fd < 0 )
ansond 0:137634ff4186 288 {
ansond 0:137634ff4186 289 ret = POLARSSL_ERR_NET_SOCKET_FAILED;
ansond 0:137634ff4186 290 continue;
ansond 0:137634ff4186 291 }
ansond 0:137634ff4186 292
ansond 0:137634ff4186 293 n = 1;
ansond 0:137634ff4186 294 if( setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR,
ansond 0:137634ff4186 295 (const char *) &n, sizeof( n ) ) != 0 )
ansond 0:137634ff4186 296 {
ansond 0:137634ff4186 297 close( *fd );
ansond 0:137634ff4186 298 ret = POLARSSL_ERR_NET_SOCKET_FAILED;
ansond 0:137634ff4186 299 continue;
ansond 0:137634ff4186 300 }
ansond 0:137634ff4186 301
ansond 0:137634ff4186 302 if( bind( *fd, cur->ai_addr, cur->ai_addrlen ) != 0 )
ansond 0:137634ff4186 303 {
ansond 0:137634ff4186 304 close( *fd );
ansond 0:137634ff4186 305 ret = POLARSSL_ERR_NET_BIND_FAILED;
ansond 0:137634ff4186 306 continue;
ansond 0:137634ff4186 307 }
ansond 0:137634ff4186 308
ansond 0:137634ff4186 309 if( listen( *fd, POLARSSL_NET_LISTEN_BACKLOG ) != 0 )
ansond 0:137634ff4186 310 {
ansond 0:137634ff4186 311 close( *fd );
ansond 0:137634ff4186 312 ret = POLARSSL_ERR_NET_LISTEN_FAILED;
ansond 0:137634ff4186 313 continue;
ansond 0:137634ff4186 314 }
ansond 0:137634ff4186 315
ansond 0:137634ff4186 316 /* I we ever get there, it's a success */
ansond 0:137634ff4186 317 ret = 0;
ansond 0:137634ff4186 318 break;
ansond 0:137634ff4186 319 }
ansond 0:137634ff4186 320
ansond 0:137634ff4186 321 freeaddrinfo( addr_list );
ansond 0:137634ff4186 322
ansond 0:137634ff4186 323 return( ret );
ansond 0:137634ff4186 324
ansond 0:137634ff4186 325 #else
ansond 0:137634ff4186 326 /* Legacy IPv4-only version */
ansond 0:137634ff4186 327
ansond 0:137634ff4186 328 int ret, n, c[4];
ansond 0:137634ff4186 329 struct sockaddr_in server_addr;
ansond 0:137634ff4186 330
ansond 0:137634ff4186 331 if( ( ret = net_prepare() ) != 0 )
ansond 0:137634ff4186 332 return( ret );
ansond 0:137634ff4186 333
ansond 0:137634ff4186 334 if( ( *fd = (int) socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 )
ansond 0:137634ff4186 335 return( POLARSSL_ERR_NET_SOCKET_FAILED );
ansond 0:137634ff4186 336
ansond 0:137634ff4186 337 n = 1;
ansond 0:137634ff4186 338 setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR,
ansond 0:137634ff4186 339 (const char *) &n, sizeof( n ) );
ansond 0:137634ff4186 340
ansond 0:137634ff4186 341 server_addr.sin_addr.s_addr = net_htonl( INADDR_ANY );
ansond 0:137634ff4186 342 server_addr.sin_family = AF_INET;
ansond 0:137634ff4186 343 server_addr.sin_port = net_htons( port );
ansond 0:137634ff4186 344
ansond 0:137634ff4186 345 if( bind_ip != NULL )
ansond 0:137634ff4186 346 {
ansond 0:137634ff4186 347 memset( c, 0, sizeof( c ) );
ansond 0:137634ff4186 348 sscanf( bind_ip, "%d.%d.%d.%d", &c[0], &c[1], &c[2], &c[3] );
ansond 0:137634ff4186 349
ansond 0:137634ff4186 350 for( n = 0; n < 4; n++ )
ansond 0:137634ff4186 351 if( c[n] < 0 || c[n] > 255 )
ansond 0:137634ff4186 352 break;
ansond 0:137634ff4186 353
ansond 0:137634ff4186 354 if( n == 4 )
ansond 0:137634ff4186 355 server_addr.sin_addr.s_addr = net_htonl(
ansond 0:137634ff4186 356 ( (uint32_t) c[0] << 24 ) |
ansond 0:137634ff4186 357 ( (uint32_t) c[1] << 16 ) |
ansond 0:137634ff4186 358 ( (uint32_t) c[2] << 8 ) |
ansond 0:137634ff4186 359 ( (uint32_t) c[3] ) );
ansond 0:137634ff4186 360 }
ansond 0:137634ff4186 361
ansond 0:137634ff4186 362 if( bind( *fd, (struct sockaddr *) &server_addr,
ansond 0:137634ff4186 363 sizeof( server_addr ) ) < 0 )
ansond 0:137634ff4186 364 {
ansond 0:137634ff4186 365 close( *fd );
ansond 0:137634ff4186 366 return( POLARSSL_ERR_NET_BIND_FAILED );
ansond 0:137634ff4186 367 }
ansond 0:137634ff4186 368
ansond 0:137634ff4186 369 if( listen( *fd, POLARSSL_NET_LISTEN_BACKLOG ) != 0 )
ansond 0:137634ff4186 370 {
ansond 0:137634ff4186 371 close( *fd );
ansond 0:137634ff4186 372 return( POLARSSL_ERR_NET_LISTEN_FAILED );
ansond 0:137634ff4186 373 }
ansond 0:137634ff4186 374
ansond 0:137634ff4186 375 return( 0 );
ansond 0:137634ff4186 376 #endif /* POLARSSL_HAVE_IPV6 */
ansond 0:137634ff4186 377 }
ansond 0:137634ff4186 378
ansond 0:137634ff4186 379 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
ansond 0:137634ff4186 380 !defined(EFI32)
ansond 0:137634ff4186 381 /*
ansond 0:137634ff4186 382 * Check if the requested operation would be blocking on a non-blocking socket
ansond 0:137634ff4186 383 * and thus 'failed' with a negative return value.
ansond 0:137634ff4186 384 */
ansond 0:137634ff4186 385 static int net_would_block( int fd )
ansond 0:137634ff4186 386 {
ansond 0:137634ff4186 387 ((void) fd);
ansond 0:137634ff4186 388 return( WSAGetLastError() == WSAEWOULDBLOCK );
ansond 0:137634ff4186 389 }
ansond 0:137634ff4186 390 #else
ansond 0:137634ff4186 391 /*
ansond 0:137634ff4186 392 * Check if the requested operation would be blocking on a non-blocking socket
ansond 0:137634ff4186 393 * and thus 'failed' with a negative return value.
ansond 0:137634ff4186 394 *
ansond 0:137634ff4186 395 * Note: on a blocking socket this function always returns 0!
ansond 0:137634ff4186 396 */
ansond 0:137634ff4186 397 static int net_would_block( int fd )
ansond 0:137634ff4186 398 {
ansond 0:137634ff4186 399 /*
ansond 0:137634ff4186 400 * Never return 'WOULD BLOCK' on a non-blocking socket
ansond 0:137634ff4186 401 */
ansond 0:137634ff4186 402 if( ( fcntl( fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK )
ansond 0:137634ff4186 403 return( 0 );
ansond 0:137634ff4186 404
ansond 0:137634ff4186 405 switch( errno )
ansond 0:137634ff4186 406 {
ansond 0:137634ff4186 407 #if defined EAGAIN
ansond 0:137634ff4186 408 case EAGAIN:
ansond 0:137634ff4186 409 #endif
ansond 0:137634ff4186 410 #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
ansond 0:137634ff4186 411 case EWOULDBLOCK:
ansond 0:137634ff4186 412 #endif
ansond 0:137634ff4186 413 return( 1 );
ansond 0:137634ff4186 414 }
ansond 0:137634ff4186 415 return( 0 );
ansond 0:137634ff4186 416 }
ansond 0:137634ff4186 417 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
ansond 0:137634ff4186 418
ansond 0:137634ff4186 419 /*
ansond 0:137634ff4186 420 * Accept a connection from a remote client
ansond 0:137634ff4186 421 */
ansond 0:137634ff4186 422 int net_accept( int bind_fd, int *client_fd, void *client_ip )
ansond 0:137634ff4186 423 {
ansond 0:137634ff4186 424 #if defined(POLARSSL_HAVE_IPV6)
ansond 0:137634ff4186 425 struct sockaddr_storage client_addr;
ansond 0:137634ff4186 426 #else
ansond 0:137634ff4186 427 struct sockaddr_in client_addr;
ansond 0:137634ff4186 428 #endif
ansond 0:137634ff4186 429
ansond 0:137634ff4186 430 #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \
ansond 0:137634ff4186 431 defined(_SOCKLEN_T_DECLARED)
ansond 0:137634ff4186 432 socklen_t n = (socklen_t) sizeof( client_addr );
ansond 0:137634ff4186 433 #else
ansond 0:137634ff4186 434 int n = (int) sizeof( client_addr );
ansond 0:137634ff4186 435 #endif
ansond 0:137634ff4186 436
ansond 0:137634ff4186 437 *client_fd = (int) accept( bind_fd, (struct sockaddr *)
ansond 0:137634ff4186 438 &client_addr, &n );
ansond 0:137634ff4186 439
ansond 0:137634ff4186 440 if( *client_fd < 0 )
ansond 0:137634ff4186 441 {
ansond 0:137634ff4186 442 if( net_would_block( bind_fd ) != 0 )
ansond 0:137634ff4186 443 return( POLARSSL_ERR_NET_WANT_READ );
ansond 0:137634ff4186 444
ansond 0:137634ff4186 445 return( POLARSSL_ERR_NET_ACCEPT_FAILED );
ansond 0:137634ff4186 446 }
ansond 0:137634ff4186 447
ansond 0:137634ff4186 448 if( client_ip != NULL )
ansond 0:137634ff4186 449 {
ansond 0:137634ff4186 450 #if defined(POLARSSL_HAVE_IPV6)
ansond 0:137634ff4186 451 if( client_addr.ss_family == AF_INET )
ansond 0:137634ff4186 452 {
ansond 0:137634ff4186 453 struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
ansond 0:137634ff4186 454 memcpy( client_ip, &addr4->sin_addr.s_addr,
ansond 0:137634ff4186 455 sizeof( addr4->sin_addr.s_addr ) );
ansond 0:137634ff4186 456 }
ansond 0:137634ff4186 457 else
ansond 0:137634ff4186 458 {
ansond 0:137634ff4186 459 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
ansond 0:137634ff4186 460 memcpy( client_ip, &addr6->sin6_addr.s6_addr,
ansond 0:137634ff4186 461 sizeof( addr6->sin6_addr.s6_addr ) );
ansond 0:137634ff4186 462 }
ansond 0:137634ff4186 463 #else
ansond 0:137634ff4186 464 memcpy( client_ip, &client_addr.sin_addr.s_addr,
ansond 0:137634ff4186 465 sizeof( client_addr.sin_addr.s_addr ) );
ansond 0:137634ff4186 466 #endif /* POLARSSL_HAVE_IPV6 */
ansond 0:137634ff4186 467 }
ansond 0:137634ff4186 468
ansond 0:137634ff4186 469 return( 0 );
ansond 0:137634ff4186 470 }
ansond 0:137634ff4186 471
ansond 0:137634ff4186 472 /*
ansond 0:137634ff4186 473 * Set the socket blocking or non-blocking
ansond 0:137634ff4186 474 */
ansond 0:137634ff4186 475 int net_set_block( int fd )
ansond 0:137634ff4186 476 {
ansond 0:137634ff4186 477 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
ansond 0:137634ff4186 478 !defined(EFI32)
ansond 0:137634ff4186 479 u_long n = 0;
ansond 0:137634ff4186 480 return( ioctlsocket( fd, FIONBIO, &n ) );
ansond 0:137634ff4186 481 #else
ansond 0:137634ff4186 482 return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) & ~O_NONBLOCK ) );
ansond 0:137634ff4186 483 #endif
ansond 0:137634ff4186 484 }
ansond 0:137634ff4186 485
ansond 0:137634ff4186 486 int net_set_nonblock( int fd )
ansond 0:137634ff4186 487 {
ansond 0:137634ff4186 488 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
ansond 0:137634ff4186 489 !defined(EFI32)
ansond 0:137634ff4186 490 u_long n = 1;
ansond 0:137634ff4186 491 return( ioctlsocket( fd, FIONBIO, &n ) );
ansond 0:137634ff4186 492 #else
ansond 0:137634ff4186 493 return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) );
ansond 0:137634ff4186 494 #endif
ansond 0:137634ff4186 495 }
ansond 0:137634ff4186 496
ansond 0:137634ff4186 497 #if defined(POLARSSL_HAVE_TIME)
ansond 0:137634ff4186 498 /*
ansond 0:137634ff4186 499 * Portable usleep helper
ansond 0:137634ff4186 500 */
ansond 0:137634ff4186 501 void net_usleep( unsigned long usec )
ansond 0:137634ff4186 502 {
ansond 0:137634ff4186 503 struct timeval tv;
ansond 0:137634ff4186 504 tv.tv_sec = usec / 1000000;
ansond 0:137634ff4186 505 #if !defined(_WIN32) && ( defined(__unix__) || defined(__unix) || \
ansond 0:137634ff4186 506 ( defined(__APPLE__) && defined(__MACH__) ) )
ansond 0:137634ff4186 507 tv.tv_usec = (suseconds_t) usec % 1000000;
ansond 0:137634ff4186 508 #else
ansond 0:137634ff4186 509 tv.tv_usec = usec % 1000000;
ansond 0:137634ff4186 510 #endif
ansond 0:137634ff4186 511 select( 0, NULL, NULL, NULL, &tv );
ansond 0:137634ff4186 512 }
ansond 0:137634ff4186 513 #endif /* POLARSSL_HAVE_TIME */
ansond 0:137634ff4186 514
ansond 0:137634ff4186 515 /*
ansond 0:137634ff4186 516 * Read at most 'len' characters
ansond 0:137634ff4186 517 */
ansond 0:137634ff4186 518 int net_recv( void *ctx, unsigned char *buf, size_t len )
ansond 0:137634ff4186 519 {
ansond 0:137634ff4186 520 int fd = *((int *) ctx);
ansond 0:137634ff4186 521 int ret = (int) read( fd, buf, len );
ansond 0:137634ff4186 522
ansond 0:137634ff4186 523 if( ret < 0 )
ansond 0:137634ff4186 524 {
ansond 0:137634ff4186 525 if( net_would_block( fd ) != 0 )
ansond 0:137634ff4186 526 return( POLARSSL_ERR_NET_WANT_READ );
ansond 0:137634ff4186 527
ansond 0:137634ff4186 528 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
ansond 0:137634ff4186 529 !defined(EFI32)
ansond 0:137634ff4186 530 if( WSAGetLastError() == WSAECONNRESET )
ansond 0:137634ff4186 531 return( POLARSSL_ERR_NET_CONN_RESET );
ansond 0:137634ff4186 532 #else
ansond 0:137634ff4186 533 if( errno == EPIPE || errno == ECONNRESET )
ansond 0:137634ff4186 534 return( POLARSSL_ERR_NET_CONN_RESET );
ansond 0:137634ff4186 535
ansond 0:137634ff4186 536 if( errno == EINTR )
ansond 0:137634ff4186 537 return( POLARSSL_ERR_NET_WANT_READ );
ansond 0:137634ff4186 538 #endif
ansond 0:137634ff4186 539
ansond 0:137634ff4186 540 return( POLARSSL_ERR_NET_RECV_FAILED );
ansond 0:137634ff4186 541 }
ansond 0:137634ff4186 542
ansond 0:137634ff4186 543 return( ret );
ansond 0:137634ff4186 544 }
ansond 0:137634ff4186 545
ansond 0:137634ff4186 546 /*
ansond 0:137634ff4186 547 * Write at most 'len' characters
ansond 0:137634ff4186 548 */
ansond 0:137634ff4186 549 int net_send( void *ctx, const unsigned char *buf, size_t len )
ansond 0:137634ff4186 550 {
ansond 0:137634ff4186 551 int fd = *((int *) ctx);
ansond 0:137634ff4186 552 int ret = (int) write( fd, buf, len );
ansond 0:137634ff4186 553
ansond 0:137634ff4186 554 if( ret < 0 )
ansond 0:137634ff4186 555 {
ansond 0:137634ff4186 556 if( net_would_block( fd ) != 0 )
ansond 0:137634ff4186 557 return( POLARSSL_ERR_NET_WANT_WRITE );
ansond 0:137634ff4186 558
ansond 0:137634ff4186 559 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
ansond 0:137634ff4186 560 !defined(EFI32)
ansond 0:137634ff4186 561 if( WSAGetLastError() == WSAECONNRESET )
ansond 0:137634ff4186 562 return( POLARSSL_ERR_NET_CONN_RESET );
ansond 0:137634ff4186 563 #else
ansond 0:137634ff4186 564 if( errno == EPIPE || errno == ECONNRESET )
ansond 0:137634ff4186 565 return( POLARSSL_ERR_NET_CONN_RESET );
ansond 0:137634ff4186 566
ansond 0:137634ff4186 567 if( errno == EINTR )
ansond 0:137634ff4186 568 return( POLARSSL_ERR_NET_WANT_WRITE );
ansond 0:137634ff4186 569 #endif
ansond 0:137634ff4186 570
ansond 0:137634ff4186 571 return( POLARSSL_ERR_NET_SEND_FAILED );
ansond 0:137634ff4186 572 }
ansond 0:137634ff4186 573
ansond 0:137634ff4186 574 return( ret );
ansond 0:137634ff4186 575 }
ansond 0:137634ff4186 576
ansond 0:137634ff4186 577 /*
ansond 0:137634ff4186 578 * Gracefully close the connection
ansond 0:137634ff4186 579 */
ansond 0:137634ff4186 580 void net_close( int fd )
ansond 0:137634ff4186 581 {
ansond 0:137634ff4186 582 shutdown( fd, 2 );
ansond 0:137634ff4186 583 close( fd );
ansond 0:137634ff4186 584 }
ansond 0:137634ff4186 585
ansond 0:137634ff4186 586 #endif /* POLARSSL_NET_C */
ansond 0:137634ff4186 587