blob: 8eb51727e98cb80cc8cc12dc364d84d9c4ae8cfd [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
Manuel Pégourié-Gonnardf4acfe12014-09-17 10:56:54 +02002 * TCP/IP or UDP/IP networking functions
Paul Bakker5121ce52009-01-03 21:22:43 +00003 *
Manuel Pégourié-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
Paul Bakkerb96f1542010-07-18 20:36:00 +00005 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +00006 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakkere0ccd0a2009-01-04 16:27:10 +00007 *
Paul Bakker5121ce52009-01-03 21:22:43 +00008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020023#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000024#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020025#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020026#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020027#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000028
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020029#if defined(MBEDTLS_NET_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000030
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000031#include "mbedtls/net.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000032
Rich Evans00ab4702015-02-06 13:43:58 +000033#include <string.h>
34
Paul Bakkerfa6a6202013-10-28 18:48:30 +010035#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
36 !defined(EFI32)
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard3b6269a2014-03-21 10:31:12 +010038#ifdef _WIN32_WINNT
39#undef _WIN32_WINNT
40#endif
41/* Enables getaddrinfo() & Co */
Manuel Pégourié-Gonnard13211352013-12-17 17:38:55 +010042#define _WIN32_WINNT 0x0501
Manuel Pégourié-Gonnard6a398d42013-12-17 16:10:58 +010043#include <ws2tcpip.h>
Manuel Pégourié-Gonnard6a398d42013-12-17 16:10:58 +010044
Manuel Pégourié-Gonnard13211352013-12-17 17:38:55 +010045#include <winsock2.h>
46#include <windows.h>
47
Paul Bakkerf0fc2a22013-12-30 15:42:43 +010048#if defined(_MSC_VER)
Paul Bakker5121ce52009-01-03 21:22:43 +000049#if defined(_WIN32_WCE)
50#pragma comment( lib, "ws2.lib" )
51#else
52#pragma comment( lib, "ws2_32.lib" )
53#endif
Paul Bakkerf0fc2a22013-12-30 15:42:43 +010054#endif /* _MSC_VER */
Paul Bakker5121ce52009-01-03 21:22:43 +000055
Paul Bakkerf4f69682011-04-24 16:08:12 +000056#define read(fd,buf,len) recv(fd,(char*)buf,(int) len,0)
57#define write(fd,buf,len) send(fd,(char*)buf,(int) len,0)
Paul Bakker5121ce52009-01-03 21:22:43 +000058#define close(fd) closesocket(fd)
59
60static int wsa_init_done = 0;
61
Paul Bakkerdb20c102014-06-17 14:34:44 +020062#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
Paul Bakker5121ce52009-01-03 21:22:43 +000063
64#include <sys/types.h>
65#include <sys/socket.h>
66#include <netinet/in.h>
67#include <arpa/inet.h>
68#include <sys/time.h>
69#include <unistd.h>
70#include <signal.h>
71#include <fcntl.h>
72#include <netdb.h>
73#include <errno.h>
Paul Bakkerb3bb6c02009-07-27 21:09:47 +000074
Paul Bakkerdb20c102014-06-17 14:34:44 +020075#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
Paul Bakker5121ce52009-01-03 21:22:43 +000076
Paul Bakker5121ce52009-01-03 21:22:43 +000077#include <stdlib.h>
78#include <stdio.h>
Paul Bakkerfa9b1002013-07-03 15:31:03 +020079
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +010080#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
81 !defined(EFI32)
82#define snprintf _snprintf
83#endif
84
Paul Bakker5121ce52009-01-03 21:22:43 +000085#include <time.h>
86
Paul Bakkerfa6a6202013-10-28 18:48:30 +010087#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker5c2364c2012-10-01 14:41:15 +000088#include <basetsd.h>
89typedef UINT32 uint32_t;
90#else
91#include <inttypes.h>
92#endif
93
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020094#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000095#include "mbedtls/platform.h"
Rich Evansa18b11f2015-01-30 10:58:35 +000096#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020097#define mbedtls_snprintf snprintf
Rich Evansa18b11f2015-01-30 10:58:35 +000098#endif
99
Paul Bakker5121ce52009-01-03 21:22:43 +0000100/*
Manuel Pégourié-Gonnard2e5c3162013-12-13 11:55:32 +0100101 * Prepare for using the sockets interface
Paul Bakker5121ce52009-01-03 21:22:43 +0000102 */
Manuel Pégourié-Gonnard173402b2013-12-17 15:57:05 +0100103static int net_prepare( void )
Paul Bakker5121ce52009-01-03 21:22:43 +0000104{
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100105#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
106 !defined(EFI32)
Paul Bakker5121ce52009-01-03 21:22:43 +0000107 WSADATA wsaData;
108
109 if( wsa_init_done == 0 )
110 {
Peter Vaskovic7015de72014-05-15 02:54:37 +0200111 if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200112 return( MBEDTLS_ERR_NET_SOCKET_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000113
114 wsa_init_done = 1;
115 }
116#else
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100117#if !defined(EFIX64) && !defined(EFI32)
Paul Bakker5121ce52009-01-03 21:22:43 +0000118 signal( SIGPIPE, SIG_IGN );
119#endif
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100120#endif
Manuel Pégourié-Gonnardee5db1d2013-12-17 16:46:19 +0100121 return( 0 );
Manuel Pégourié-Gonnard2e5c3162013-12-13 11:55:32 +0100122}
123
124/*
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100125 * Initiate a TCP connection with host:port and the given protocol
Manuel Pégourié-Gonnard2e5c3162013-12-13 11:55:32 +0100126 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127int mbedtls_net_connect( int *fd, const char *host, int port, int proto )
Manuel Pégourié-Gonnard2e5c3162013-12-13 11:55:32 +0100128{
Manuel Pégourié-Gonnard173402b2013-12-17 15:57:05 +0100129 int ret;
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100130 struct addrinfo hints, *addr_list, *cur;
131 char port_str[6];
132
Manuel Pégourié-Gonnard173402b2013-12-17 15:57:05 +0100133 if( ( ret = net_prepare() ) != 0 )
134 return( ret );
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100135
136 /* getaddrinfo expects port as a string */
137 memset( port_str, 0, sizeof( port_str ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200138 mbedtls_snprintf( port_str, sizeof( port_str ), "%d", port );
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100139
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100140 /* Do name resolution with both IPv6 and IPv4 */
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100141 memset( &hints, 0, sizeof( hints ) );
142 hints.ai_family = AF_UNSPEC;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200143 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
144 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100145
146 if( getaddrinfo( host, port_str, &hints, &addr_list ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200147 return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100148
149 /* Try the sockaddrs until a connection succeeds */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100151 for( cur = addr_list; cur != NULL; cur = cur->ai_next )
152 {
Paul Bakker00f5c522013-12-31 10:45:16 +0100153 *fd = (int) socket( cur->ai_family, cur->ai_socktype,
154 cur->ai_protocol );
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100155 if( *fd < 0 )
156 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100158 continue;
159 }
160
161 if( connect( *fd, cur->ai_addr, cur->ai_addrlen ) == 0 )
162 {
163 ret = 0;
164 break;
165 }
166
167 close( *fd );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100169 }
170
171 freeaddrinfo( addr_list );
172
173 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000174}
175
176/*
177 * Create a listening socket on bind_ip:port
178 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179int mbedtls_net_bind( int *fd, const char *bind_ip, int port, int proto )
Paul Bakker5121ce52009-01-03 21:22:43 +0000180{
Manuel Pégourié-Gonnard173402b2013-12-17 15:57:05 +0100181 int n, ret;
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100182 struct addrinfo hints, *addr_list, *cur;
183 char port_str[6];
184
Manuel Pégourié-Gonnard173402b2013-12-17 15:57:05 +0100185 if( ( ret = net_prepare() ) != 0 )
186 return( ret );
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100187
188 /* getaddrinfo expects port as a string */
189 memset( port_str, 0, sizeof( port_str ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 mbedtls_snprintf( port_str, sizeof( port_str ), "%d", port );
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100191
192 /* Bind to IPv6 and/or IPv4, but only in TCP */
193 memset( &hints, 0, sizeof( hints ) );
194 hints.ai_family = AF_UNSPEC;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200195 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
196 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100197 if( bind_ip == NULL )
198 hints.ai_flags = AI_PASSIVE;
199
200 if( getaddrinfo( bind_ip, port_str, &hints, &addr_list ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200201 return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100202
203 /* Try the sockaddrs until a binding succeeds */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200204 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100205 for( cur = addr_list; cur != NULL; cur = cur->ai_next )
206 {
Paul Bakker00f5c522013-12-31 10:45:16 +0100207 *fd = (int) socket( cur->ai_family, cur->ai_socktype,
208 cur->ai_protocol );
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100209 if( *fd < 0 )
210 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100212 continue;
213 }
214
Manuel Pégourié-Gonnardfd6b4cc2013-12-17 13:59:01 +0100215 n = 1;
Paul Bakker874bd642014-04-17 12:43:05 +0200216 if( setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR,
217 (const char *) &n, sizeof( n ) ) != 0 )
218 {
219 close( *fd );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
Paul Bakker874bd642014-04-17 12:43:05 +0200221 continue;
222 }
Manuel Pégourié-Gonnardfd6b4cc2013-12-17 13:59:01 +0100223
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100224 if( bind( *fd, cur->ai_addr, cur->ai_addrlen ) != 0 )
225 {
226 close( *fd );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200227 ret = MBEDTLS_ERR_NET_BIND_FAILED;
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100228 continue;
229 }
230
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100231 /* Listen only makes sense for TCP */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200232 if( proto == MBEDTLS_NET_PROTO_TCP )
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100233 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200234 if( listen( *fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 )
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100235 {
236 close( *fd );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200237 ret = MBEDTLS_ERR_NET_LISTEN_FAILED;
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100238 continue;
239 }
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100240 }
241
242 /* I we ever get there, it's a success */
243 ret = 0;
244 break;
245 }
246
247 freeaddrinfo( addr_list );
248
249 return( ret );
250
Paul Bakker5121ce52009-01-03 21:22:43 +0000251}
252
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100253#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
254 !defined(EFI32)
Paul Bakker80025412014-01-23 20:59:49 +0100255/*
256 * Check if the requested operation would be blocking on a non-blocking socket
257 * and thus 'failed' with a negative return value.
258 */
259static int net_would_block( int fd )
260{
Manuel Pégourié-Gonnard3b6269a2014-03-21 10:31:12 +0100261 ((void) fd);
Paul Bakker5121ce52009-01-03 21:22:43 +0000262 return( WSAGetLastError() == WSAEWOULDBLOCK );
Paul Bakker80025412014-01-23 20:59:49 +0100263}
Paul Bakker5121ce52009-01-03 21:22:43 +0000264#else
Paul Bakker80025412014-01-23 20:59:49 +0100265/*
266 * Check if the requested operation would be blocking on a non-blocking socket
267 * and thus 'failed' with a negative return value.
268 *
269 * Note: on a blocking socket this function always returns 0!
270 */
271static int net_would_block( int fd )
272{
273 /*
274 * Never return 'WOULD BLOCK' on a non-blocking socket
275 */
276 if( ( fcntl( fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK )
277 return( 0 );
278
Paul Bakker5121ce52009-01-03 21:22:43 +0000279 switch( errno )
280 {
281#if defined EAGAIN
282 case EAGAIN:
283#endif
284#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
285 case EWOULDBLOCK:
286#endif
287 return( 1 );
288 }
289 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000290}
Paul Bakkerdb20c102014-06-17 14:34:44 +0200291#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000292
293/*
294 * Accept a connection from a remote client
295 */
Manuel Pégourié-Gonnard0b104b02015-05-14 21:52:40 +0200296int mbedtls_net_accept( int bind_fd, int *client_fd,
297 void *client_ip, size_t buf_size, size_t *ip_len )
Paul Bakker5121ce52009-01-03 21:22:43 +0000298{
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100299 int ret;
300 int type;
301
Manuel Pégourié-Gonnard6e315a92013-12-13 16:21:25 +0100302 struct sockaddr_storage client_addr;
Paul Bakker5121ce52009-01-03 21:22:43 +0000303
Paul Bakker394c56f2011-12-20 12:19:03 +0000304#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \
305 defined(_SOCKLEN_T_DECLARED)
Paul Bakker5121ce52009-01-03 21:22:43 +0000306 socklen_t n = (socklen_t) sizeof( client_addr );
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100307 socklen_t type_len = (socklen_t) sizeof( type );
Paul Bakker5121ce52009-01-03 21:22:43 +0000308#else
309 int n = (int) sizeof( client_addr );
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100310 int type_len = (int) sizeof( type );
Paul Bakker5121ce52009-01-03 21:22:43 +0000311#endif
312
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100313 /* Is this a TCP or UDP socket? */
Manuel Pégourié-Gonnard9325b262015-03-25 16:57:52 +0100314 if( getsockopt( bind_fd, SOL_SOCKET, SO_TYPE, (void *) &type, &type_len ) != 0 ||
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100315 ( type != SOCK_STREAM && type != SOCK_DGRAM ) )
316 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200317 return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100318 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000319
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100320 if( type == SOCK_STREAM )
321 {
322 /* TCP: actual accept() */
323 ret = *client_fd = (int) accept( bind_fd,
324 (struct sockaddr *) &client_addr, &n );
325 }
326 else
327 {
328 /* UDP: wait for a message, but keep it in the queue */
329 char buf[1] = { 0 };
330
Manuel Pégourié-Gonnardf3c500f2015-01-12 19:02:15 +0100331 ret = recvfrom( bind_fd, buf, sizeof( buf ), MSG_PEEK,
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100332 (struct sockaddr *) &client_addr, &n );
333 }
334
335 if( ret < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000336 {
Manuel Pégourié-Gonnard9a6b4422014-07-21 13:42:54 +0200337 if( net_would_block( bind_fd ) != 0 )
Manuel Pégourié-Gonnard88369942015-05-06 16:19:31 +0100338 return( MBEDTLS_ERR_SSL_WANT_READ );
Paul Bakker5121ce52009-01-03 21:22:43 +0000339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200340 return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000341 }
342
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100343 /* UDP: hijack the listening socket for communicating with the client */
344 if( type != SOCK_STREAM )
345 {
346 if( connect( bind_fd, (struct sockaddr *) &client_addr, n ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347 return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100348
349 *client_fd = bind_fd;
350 }
351
Paul Bakker5121ce52009-01-03 21:22:43 +0000352 if( client_ip != NULL )
Manuel Pégourié-Gonnard6e315a92013-12-13 16:21:25 +0100353 {
Manuel Pégourié-Gonnard6e315a92013-12-13 16:21:25 +0100354 if( client_addr.ss_family == AF_INET )
355 {
356 struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
Manuel Pégourié-Gonnard0b104b02015-05-14 21:52:40 +0200357 *ip_len = sizeof( addr4->sin_addr.s_addr );
358
359 if( buf_size < *ip_len )
360 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
361
362 memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len );
Manuel Pégourié-Gonnard6e315a92013-12-13 16:21:25 +0100363 }
364 else
365 {
366 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
Manuel Pégourié-Gonnard0b104b02015-05-14 21:52:40 +0200367 *ip_len = sizeof( addr6->sin6_addr.s6_addr );
368
369 if( buf_size < *ip_len )
370 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
371
372 memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len);
Manuel Pégourié-Gonnard6e315a92013-12-13 16:21:25 +0100373 }
Manuel Pégourié-Gonnard6e315a92013-12-13 16:21:25 +0100374 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000375
376 return( 0 );
377}
378
379/*
380 * Set the socket blocking or non-blocking
381 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382int mbedtls_net_set_block( int fd )
Paul Bakker5121ce52009-01-03 21:22:43 +0000383{
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100384#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
385 !defined(EFI32)
Paul Bakkerf4f69682011-04-24 16:08:12 +0000386 u_long n = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000387 return( ioctlsocket( fd, FIONBIO, &n ) );
388#else
389 return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) & ~O_NONBLOCK ) );
390#endif
391}
392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393int mbedtls_net_set_nonblock( int fd )
Paul Bakker5121ce52009-01-03 21:22:43 +0000394{
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100395#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
396 !defined(EFI32)
Paul Bakkerf4f69682011-04-24 16:08:12 +0000397 u_long n = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000398 return( ioctlsocket( fd, FIONBIO, &n ) );
399#else
400 return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) );
401#endif
402}
403
404/*
405 * Portable usleep helper
406 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407void mbedtls_net_usleep( unsigned long usec )
Paul Bakker5121ce52009-01-03 21:22:43 +0000408{
409 struct timeval tv;
Manuel Pégourié-Gonnarde4232462014-11-21 09:52:23 +0100410 tv.tv_sec = usec / 1000000;
Paul Bakker82788fb2014-10-20 13:59:19 +0200411#if !defined(_WIN32) && ( defined(__unix__) || defined(__unix) || \
412 ( defined(__APPLE__) && defined(__MACH__) ) )
Manuel Pégourié-Gonnarde4232462014-11-21 09:52:23 +0100413 tv.tv_usec = (suseconds_t) usec % 1000000;
Sander Niemeijeref5087d2014-08-16 12:45:52 +0200414#else
Manuel Pégourié-Gonnarde4232462014-11-21 09:52:23 +0100415 tv.tv_usec = usec % 1000000;
Sander Niemeijeref5087d2014-08-16 12:45:52 +0200416#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000417 select( 0, NULL, NULL, NULL, &tv );
418}
419
420/*
421 * Read at most 'len' characters
422 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200423int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100424{
Paul Bakker80025412014-01-23 20:59:49 +0100425 int fd = *((int *) ctx);
Sander Niemeijeref5087d2014-08-16 12:45:52 +0200426 int ret = (int) read( fd, buf, len );
Paul Bakker5121ce52009-01-03 21:22:43 +0000427
Paul Bakker5121ce52009-01-03 21:22:43 +0000428 if( ret < 0 )
429 {
Paul Bakker80025412014-01-23 20:59:49 +0100430 if( net_would_block( fd ) != 0 )
Manuel Pégourié-Gonnard88369942015-05-06 16:19:31 +0100431 return( MBEDTLS_ERR_SSL_WANT_READ );
Paul Bakker5121ce52009-01-03 21:22:43 +0000432
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100433#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
434 !defined(EFI32)
Paul Bakker5121ce52009-01-03 21:22:43 +0000435 if( WSAGetLastError() == WSAECONNRESET )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200436 return( MBEDTLS_ERR_NET_CONN_RESET );
Paul Bakker5121ce52009-01-03 21:22:43 +0000437#else
438 if( errno == EPIPE || errno == ECONNRESET )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200439 return( MBEDTLS_ERR_NET_CONN_RESET );
Paul Bakker5121ce52009-01-03 21:22:43 +0000440
441 if( errno == EINTR )
Manuel Pégourié-Gonnard88369942015-05-06 16:19:31 +0100442 return( MBEDTLS_ERR_SSL_WANT_READ );
Paul Bakker5121ce52009-01-03 21:22:43 +0000443#endif
444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445 return( MBEDTLS_ERR_NET_RECV_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000446 }
447
448 return( ret );
449}
450
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200451/*
Manuel Pégourié-Gonnardc8d8e972014-10-01 15:01:39 +0200452 * Read at most 'len' characters, blocking for at most 'timeout' ms
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200453 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
Manuel Pégourié-Gonnardc8d8e972014-10-01 15:01:39 +0200455 uint32_t timeout )
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200456{
457 int ret;
458 struct timeval tv;
459 fd_set read_fds;
460 int fd = *((int *) ctx);
461
462 FD_ZERO( &read_fds );
463 FD_SET( fd, &read_fds );
464
Manuel Pégourié-Gonnardc8d8e972014-10-01 15:01:39 +0200465 tv.tv_sec = timeout / 1000;
466 tv.tv_usec = ( timeout % 1000 ) * 1000;
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200467
468 ret = select( fd + 1, &read_fds, NULL, NULL, &tv );
469
470 /* Zero fds ready means we timed out */
471 if( ret == 0 )
Manuel Pégourié-Gonnard88369942015-05-06 16:19:31 +0100472 return( MBEDTLS_ERR_SSL_TIMEOUT );
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200473
474 if( ret < 0 )
475 {
476#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
477 !defined(EFI32)
478 if( WSAGetLastError() == WSAEINTR )
Manuel Pégourié-Gonnard88369942015-05-06 16:19:31 +0100479 return( MBEDTLS_ERR_SSL_WANT_READ );
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200480#else
481 if( errno == EINTR )
Manuel Pégourié-Gonnard88369942015-05-06 16:19:31 +0100482 return( MBEDTLS_ERR_SSL_WANT_READ );
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200483#endif
484
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485 return( MBEDTLS_ERR_NET_RECV_FAILED );
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200486 }
487
488 /* This call will not block */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489 return( mbedtls_net_recv( ctx, buf, len ) );
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200490}
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200491
Paul Bakker5121ce52009-01-03 21:22:43 +0000492/*
493 * Write at most 'len' characters
494 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200495int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
Paul Bakker5121ce52009-01-03 21:22:43 +0000496{
Paul Bakker80025412014-01-23 20:59:49 +0100497 int fd = *((int *) ctx);
Sander Niemeijeref5087d2014-08-16 12:45:52 +0200498 int ret = (int) write( fd, buf, len );
Paul Bakker5121ce52009-01-03 21:22:43 +0000499
500 if( ret < 0 )
501 {
Paul Bakker80025412014-01-23 20:59:49 +0100502 if( net_would_block( fd ) != 0 )
Manuel Pégourié-Gonnard88369942015-05-06 16:19:31 +0100503 return( MBEDTLS_ERR_SSL_WANT_WRITE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000504
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100505#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
506 !defined(EFI32)
Paul Bakker5121ce52009-01-03 21:22:43 +0000507 if( WSAGetLastError() == WSAECONNRESET )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508 return( MBEDTLS_ERR_NET_CONN_RESET );
Paul Bakker5121ce52009-01-03 21:22:43 +0000509#else
510 if( errno == EPIPE || errno == ECONNRESET )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200511 return( MBEDTLS_ERR_NET_CONN_RESET );
Paul Bakker5121ce52009-01-03 21:22:43 +0000512
513 if( errno == EINTR )
Manuel Pégourié-Gonnard88369942015-05-06 16:19:31 +0100514 return( MBEDTLS_ERR_SSL_WANT_WRITE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000515#endif
516
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 return( MBEDTLS_ERR_NET_SEND_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000518 }
519
520 return( ret );
521}
522
523/*
524 * Gracefully close the connection
525 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200526void mbedtls_net_close( int fd )
Paul Bakker5121ce52009-01-03 21:22:43 +0000527{
528 shutdown( fd, 2 );
529 close( fd );
530}
531
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532#endif /* MBEDTLS_NET_C */