blob: cd53d80d73b9fbc4bebf855ee636d3b8bca7c80e [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é-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_HAVE_IPV6)
Manuel Pégourié-Gonnard3b6269a2014-03-21 10:31:12 +010039#ifdef _WIN32_WINNT
40#undef _WIN32_WINNT
41#endif
42/* Enables getaddrinfo() & Co */
Manuel Pégourié-Gonnard13211352013-12-17 17:38:55 +010043#define _WIN32_WINNT 0x0501
Manuel Pégourié-Gonnard6a398d42013-12-17 16:10:58 +010044#include <ws2tcpip.h>
45#endif
46
Manuel Pégourié-Gonnard13211352013-12-17 17:38:55 +010047#include <winsock2.h>
48#include <windows.h>
49
Paul Bakkerf0fc2a22013-12-30 15:42:43 +010050#if defined(_MSC_VER)
Paul Bakker5121ce52009-01-03 21:22:43 +000051#if defined(_WIN32_WCE)
52#pragma comment( lib, "ws2.lib" )
53#else
54#pragma comment( lib, "ws2_32.lib" )
55#endif
Paul Bakkerf0fc2a22013-12-30 15:42:43 +010056#endif /* _MSC_VER */
Paul Bakker5121ce52009-01-03 21:22:43 +000057
Paul Bakkerf4f69682011-04-24 16:08:12 +000058#define read(fd,buf,len) recv(fd,(char*)buf,(int) len,0)
59#define write(fd,buf,len) send(fd,(char*)buf,(int) len,0)
Paul Bakker5121ce52009-01-03 21:22:43 +000060#define close(fd) closesocket(fd)
61
62static int wsa_init_done = 0;
63
Paul Bakkerdb20c102014-06-17 14:34:44 +020064#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
Paul Bakker5121ce52009-01-03 21:22:43 +000065
66#include <sys/types.h>
67#include <sys/socket.h>
68#include <netinet/in.h>
69#include <arpa/inet.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020070#if defined(MBEDTLS_HAVE_TIME)
Paul Bakker5121ce52009-01-03 21:22:43 +000071#include <sys/time.h>
Paul Bakkerfa9b1002013-07-03 15:31:03 +020072#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000073#include <unistd.h>
74#include <signal.h>
75#include <fcntl.h>
76#include <netdb.h>
77#include <errno.h>
Paul Bakkerb3bb6c02009-07-27 21:09:47 +000078
Paul Bakkerdb20c102014-06-17 14:34:44 +020079#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
Paul Bakker5121ce52009-01-03 21:22:43 +000080
Paul Bakker5121ce52009-01-03 21:22:43 +000081#include <stdlib.h>
82#include <stdio.h>
Paul Bakkerfa9b1002013-07-03 15:31:03 +020083
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +010084#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
85 !defined(EFI32)
86#define snprintf _snprintf
87#endif
88
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089#if defined(MBEDTLS_HAVE_TIME)
Paul Bakker5121ce52009-01-03 21:22:43 +000090#include <time.h>
Paul Bakkerfa9b1002013-07-03 15:31:03 +020091#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000092
Paul Bakkerfa6a6202013-10-28 18:48:30 +010093#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker5c2364c2012-10-01 14:41:15 +000094#include <basetsd.h>
95typedef UINT32 uint32_t;
96#else
97#include <inttypes.h>
98#endif
99
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100#if !defined(MBEDTLS_HAVE_IPV6)
Manuel Pégourié-Gonnarddf791a52015-04-03 17:10:22 +0200101#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || \
102 defined(__DragonFly__)
103#include <sys/endian.h>
104#elif defined(__APPLE__) || defined(HAVE_MACHINE_ENDIAN_H) || \
105 defined(EFIX64) || defined(EFI32)
106#include <machine/endian.h>
107#elif defined(sun)
108#include <sys/isa_defs.h>
109#elif defined(_AIX) || defined(HAVE_ARPA_NAMESER_COMPAT_H)
110#include <arpa/nameser_compat.h>
111#else
112#include <endian.h>
113#endif
114
Paul Bakker5121ce52009-01-03 21:22:43 +0000115/*
Paul Bakker1d4f30c2009-04-19 18:55:16 +0000116 * htons() is not always available.
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200117 * By default go for LITTLE_ENDIAN variant. Otherwise hope for _BYTE_ORDER and
118 * __BIG_ENDIAN to help determine endianness.
Paul Bakker5121ce52009-01-03 21:22:43 +0000119 */
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200120#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
121 __BYTE_ORDER == __BIG_ENDIAN
Manuel Pégourié-Gonnarddf791a52015-04-03 17:10:22 +0200122static unsigned short net_htons( unsigned short n ) { return( n ); }
123static unsigned long net_htonl( unsigned long n ) { return( n ); }
Paul Bakker1d4f30c2009-04-19 18:55:16 +0000124#else
Manuel Pégourié-Gonnarddf791a52015-04-03 17:10:22 +0200125static unsigned short net_htons( unsigned short n )
126{
127 return( (((unsigned short) n & 0xFF ) << 8 ) |
128 (((unsigned short) n & 0xFF00 ) >> 8 ) );
129}
130static unsigned long net_htonl( unsigned long n )
131{
132 return( (((unsigned long ) n & 0xFF ) << 24) |
133 (((unsigned long ) n & 0xFF00 ) << 8 ) |
134 (((unsigned long ) n & 0xFF0000 ) >> 8 ) |
135 (((unsigned long ) n & 0xFF000000) >> 24) );
136}
Paul Bakker1d4f30c2009-04-19 18:55:16 +0000137#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200138#endif /* !MBEDTLS_HAVE_IPV6 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000139
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200140#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +0000141#include "mbedtls/platform.h"
Rich Evansa18b11f2015-01-30 10:58:35 +0000142#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200143#define mbedtls_snprintf snprintf
Rich Evansa18b11f2015-01-30 10:58:35 +0000144#endif
145
Paul Bakker5121ce52009-01-03 21:22:43 +0000146/*
Manuel Pégourié-Gonnard2e5c3162013-12-13 11:55:32 +0100147 * Prepare for using the sockets interface
Paul Bakker5121ce52009-01-03 21:22:43 +0000148 */
Manuel Pégourié-Gonnard173402b2013-12-17 15:57:05 +0100149static int net_prepare( void )
Paul Bakker5121ce52009-01-03 21:22:43 +0000150{
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100151#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
152 !defined(EFI32)
Paul Bakker5121ce52009-01-03 21:22:43 +0000153 WSADATA wsaData;
154
155 if( wsa_init_done == 0 )
156 {
Peter Vaskovic7015de72014-05-15 02:54:37 +0200157 if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 return( MBEDTLS_ERR_NET_SOCKET_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000159
160 wsa_init_done = 1;
161 }
162#else
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100163#if !defined(EFIX64) && !defined(EFI32)
Paul Bakker5121ce52009-01-03 21:22:43 +0000164 signal( SIGPIPE, SIG_IGN );
165#endif
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100166#endif
Manuel Pégourié-Gonnardee5db1d2013-12-17 16:46:19 +0100167 return( 0 );
Manuel Pégourié-Gonnard2e5c3162013-12-13 11:55:32 +0100168}
169
170/*
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100171 * Initiate a TCP connection with host:port and the given protocol
Manuel Pégourié-Gonnard2e5c3162013-12-13 11:55:32 +0100172 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173int mbedtls_net_connect( int *fd, const char *host, int port, int proto )
Manuel Pégourié-Gonnard2e5c3162013-12-13 11:55:32 +0100174{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175#if defined(MBEDTLS_HAVE_IPV6)
Manuel Pégourié-Gonnard173402b2013-12-17 15:57:05 +0100176 int ret;
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100177 struct addrinfo hints, *addr_list, *cur;
178 char port_str[6];
179
Manuel Pégourié-Gonnard173402b2013-12-17 15:57:05 +0100180 if( ( ret = net_prepare() ) != 0 )
181 return( ret );
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100182
183 /* getaddrinfo expects port as a string */
184 memset( port_str, 0, sizeof( port_str ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185 mbedtls_snprintf( port_str, sizeof( port_str ), "%d", port );
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100186
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100187 /* Do name resolution with both IPv6 and IPv4 */
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100188 memset( &hints, 0, sizeof( hints ) );
189 hints.ai_family = AF_UNSPEC;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
191 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100192
193 if( getaddrinfo( host, port_str, &hints, &addr_list ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200194 return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100195
196 /* Try the sockaddrs until a connection succeeds */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200197 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100198 for( cur = addr_list; cur != NULL; cur = cur->ai_next )
199 {
Paul Bakker00f5c522013-12-31 10:45:16 +0100200 *fd = (int) socket( cur->ai_family, cur->ai_socktype,
201 cur->ai_protocol );
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100202 if( *fd < 0 )
203 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200204 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100205 continue;
206 }
207
208 if( connect( *fd, cur->ai_addr, cur->ai_addrlen ) == 0 )
209 {
210 ret = 0;
211 break;
212 }
213
214 close( *fd );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
Manuel Pégourié-Gonnard10934de2013-12-13 12:54:09 +0100216 }
217
218 freeaddrinfo( addr_list );
219
220 return( ret );
221
222#else
223 /* Legacy IPv4-only version */
224
Manuel Pégourié-Gonnard173402b2013-12-17 15:57:05 +0100225 int ret;
Manuel Pégourié-Gonnard2e5c3162013-12-13 11:55:32 +0100226 struct sockaddr_in server_addr;
227 struct hostent *server_host;
228
Manuel Pégourié-Gonnard173402b2013-12-17 15:57:05 +0100229 if( ( ret = net_prepare() ) != 0 )
230 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000231
232 if( ( server_host = gethostbyname( host ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233 return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
Paul Bakker5121ce52009-01-03 21:22:43 +0000234
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100235 if( ( *fd = (int) socket( AF_INET,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM,
237 proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP ) ) < 0 )
238 return( MBEDTLS_ERR_NET_SOCKET_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000239
240 memcpy( (void *) &server_addr.sin_addr,
241 (void *) server_host->h_addr,
242 server_host->h_length );
243
244 server_addr.sin_family = AF_INET;
245 server_addr.sin_port = net_htons( port );
246
247 if( connect( *fd, (struct sockaddr *) &server_addr,
248 sizeof( server_addr ) ) < 0 )
249 {
250 close( *fd );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200251 return( MBEDTLS_ERR_NET_CONNECT_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000252 }
253
254 return( 0 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255#endif /* MBEDTLS_HAVE_IPV6 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000256}
257
258/*
259 * Create a listening socket on bind_ip:port
260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261int mbedtls_net_bind( int *fd, const char *bind_ip, int port, int proto )
Paul Bakker5121ce52009-01-03 21:22:43 +0000262{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263#if defined(MBEDTLS_HAVE_IPV6)
Manuel Pégourié-Gonnard173402b2013-12-17 15:57:05 +0100264 int n, ret;
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100265 struct addrinfo hints, *addr_list, *cur;
266 char port_str[6];
267
Manuel Pégourié-Gonnard173402b2013-12-17 15:57:05 +0100268 if( ( ret = net_prepare() ) != 0 )
269 return( ret );
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100270
271 /* getaddrinfo expects port as a string */
272 memset( port_str, 0, sizeof( port_str ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200273 mbedtls_snprintf( port_str, sizeof( port_str ), "%d", port );
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100274
275 /* Bind to IPv6 and/or IPv4, but only in TCP */
276 memset( &hints, 0, sizeof( hints ) );
277 hints.ai_family = AF_UNSPEC;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200278 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
279 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100280 if( bind_ip == NULL )
281 hints.ai_flags = AI_PASSIVE;
282
283 if( getaddrinfo( bind_ip, port_str, &hints, &addr_list ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100285
286 /* Try the sockaddrs until a binding succeeds */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200287 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100288 for( cur = addr_list; cur != NULL; cur = cur->ai_next )
289 {
Paul Bakker00f5c522013-12-31 10:45:16 +0100290 *fd = (int) socket( cur->ai_family, cur->ai_socktype,
291 cur->ai_protocol );
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100292 if( *fd < 0 )
293 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100295 continue;
296 }
297
Manuel Pégourié-Gonnardfd6b4cc2013-12-17 13:59:01 +0100298 n = 1;
Paul Bakker874bd642014-04-17 12:43:05 +0200299 if( setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR,
300 (const char *) &n, sizeof( n ) ) != 0 )
301 {
302 close( *fd );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200303 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
Paul Bakker874bd642014-04-17 12:43:05 +0200304 continue;
305 }
Manuel Pégourié-Gonnardfd6b4cc2013-12-17 13:59:01 +0100306
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100307 if( bind( *fd, cur->ai_addr, cur->ai_addrlen ) != 0 )
308 {
309 close( *fd );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200310 ret = MBEDTLS_ERR_NET_BIND_FAILED;
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100311 continue;
312 }
313
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100314 /* Listen only makes sense for TCP */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315 if( proto == MBEDTLS_NET_PROTO_TCP )
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100316 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200317 if( listen( *fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 )
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100318 {
319 close( *fd );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200320 ret = MBEDTLS_ERR_NET_LISTEN_FAILED;
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100321 continue;
322 }
Manuel Pégourié-Gonnard389ce632013-12-13 14:00:51 +0100323 }
324
325 /* I we ever get there, it's a success */
326 ret = 0;
327 break;
328 }
329
330 freeaddrinfo( addr_list );
331
332 return( ret );
333
334#else
335 /* Legacy IPv4-only version */
336
Manuel Pégourié-Gonnard173402b2013-12-17 15:57:05 +0100337 int ret, n, c[4];
Paul Bakker5121ce52009-01-03 21:22:43 +0000338 struct sockaddr_in server_addr;
339
Manuel Pégourié-Gonnard173402b2013-12-17 15:57:05 +0100340 if( ( ret = net_prepare() ) != 0 )
341 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000342
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100343 if( ( *fd = (int) socket( AF_INET,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344 proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM,
345 proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP ) ) < 0 )
346 return( MBEDTLS_ERR_NET_SOCKET_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000347
348 n = 1;
349 setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR,
350 (const char *) &n, sizeof( n ) );
351
Paul Bakker37286a52013-03-06 16:55:11 +0100352 server_addr.sin_addr.s_addr = net_htonl( INADDR_ANY );
Paul Bakker5121ce52009-01-03 21:22:43 +0000353 server_addr.sin_family = AF_INET;
354 server_addr.sin_port = net_htons( port );
355
356 if( bind_ip != NULL )
357 {
358 memset( c, 0, sizeof( c ) );
359 sscanf( bind_ip, "%d.%d.%d.%d", &c[0], &c[1], &c[2], &c[3] );
360
361 for( n = 0; n < 4; n++ )
362 if( c[n] < 0 || c[n] > 255 )
363 break;
364
365 if( n == 4 )
Paul Bakker37286a52013-03-06 16:55:11 +0100366 server_addr.sin_addr.s_addr = net_htonl(
Paul Bakker5c2364c2012-10-01 14:41:15 +0000367 ( (uint32_t) c[0] << 24 ) |
368 ( (uint32_t) c[1] << 16 ) |
369 ( (uint32_t) c[2] << 8 ) |
Paul Bakker37286a52013-03-06 16:55:11 +0100370 ( (uint32_t) c[3] ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000371 }
372
373 if( bind( *fd, (struct sockaddr *) &server_addr,
374 sizeof( server_addr ) ) < 0 )
375 {
376 close( *fd );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200377 return( MBEDTLS_ERR_NET_BIND_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000378 }
379
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100380 /* Listen only makes sense for TCP */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381 if( proto == MBEDTLS_NET_PROTO_TCP )
Paul Bakker5121ce52009-01-03 21:22:43 +0000382 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383 if( listen( *fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 )
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100384 {
385 close( *fd );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200386 return( MBEDTLS_ERR_NET_LISTEN_FAILED );
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100387 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000388 }
389
390 return( 0 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200391#endif /* MBEDTLS_HAVE_IPV6 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000392}
393
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100394#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
395 !defined(EFI32)
Paul Bakker80025412014-01-23 20:59:49 +0100396/*
397 * Check if the requested operation would be blocking on a non-blocking socket
398 * and thus 'failed' with a negative return value.
399 */
400static int net_would_block( int fd )
401{
Manuel Pégourié-Gonnard3b6269a2014-03-21 10:31:12 +0100402 ((void) fd);
Paul Bakker5121ce52009-01-03 21:22:43 +0000403 return( WSAGetLastError() == WSAEWOULDBLOCK );
Paul Bakker80025412014-01-23 20:59:49 +0100404}
Paul Bakker5121ce52009-01-03 21:22:43 +0000405#else
Paul Bakker80025412014-01-23 20:59:49 +0100406/*
407 * Check if the requested operation would be blocking on a non-blocking socket
408 * and thus 'failed' with a negative return value.
409 *
410 * Note: on a blocking socket this function always returns 0!
411 */
412static int net_would_block( int fd )
413{
414 /*
415 * Never return 'WOULD BLOCK' on a non-blocking socket
416 */
417 if( ( fcntl( fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK )
418 return( 0 );
419
Paul Bakker5121ce52009-01-03 21:22:43 +0000420 switch( errno )
421 {
422#if defined EAGAIN
423 case EAGAIN:
424#endif
425#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
426 case EWOULDBLOCK:
427#endif
428 return( 1 );
429 }
430 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000431}
Paul Bakkerdb20c102014-06-17 14:34:44 +0200432#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000433
434/*
435 * Accept a connection from a remote client
436 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437int mbedtls_net_accept( int bind_fd, int *client_fd, void *client_ip )
Paul Bakker5121ce52009-01-03 21:22:43 +0000438{
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100439 int ret;
440 int type;
441
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442#if defined(MBEDTLS_HAVE_IPV6)
Manuel Pégourié-Gonnard6e315a92013-12-13 16:21:25 +0100443 struct sockaddr_storage client_addr;
444#else
Paul Bakker5121ce52009-01-03 21:22:43 +0000445 struct sockaddr_in client_addr;
Manuel Pégourié-Gonnard6e315a92013-12-13 16:21:25 +0100446#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000447
Paul Bakker394c56f2011-12-20 12:19:03 +0000448#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \
449 defined(_SOCKLEN_T_DECLARED)
Paul Bakker5121ce52009-01-03 21:22:43 +0000450 socklen_t n = (socklen_t) sizeof( client_addr );
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100451 socklen_t type_len = (socklen_t) sizeof( type );
Paul Bakker5121ce52009-01-03 21:22:43 +0000452#else
453 int n = (int) sizeof( client_addr );
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100454 int type_len = (int) sizeof( type );
Paul Bakker5121ce52009-01-03 21:22:43 +0000455#endif
456
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100457 /* Is this a TCP or UDP socket? */
Manuel Pégourié-Gonnard9325b262015-03-25 16:57:52 +0100458 if( getsockopt( bind_fd, SOL_SOCKET, SO_TYPE, (void *) &type, &type_len ) != 0 ||
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100459 ( type != SOCK_STREAM && type != SOCK_DGRAM ) )
460 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200461 return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100462 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000463
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100464 if( type == SOCK_STREAM )
465 {
466 /* TCP: actual accept() */
467 ret = *client_fd = (int) accept( bind_fd,
468 (struct sockaddr *) &client_addr, &n );
469 }
470 else
471 {
472 /* UDP: wait for a message, but keep it in the queue */
473 char buf[1] = { 0 };
474
Manuel Pégourié-Gonnardf3c500f2015-01-12 19:02:15 +0100475 ret = recvfrom( bind_fd, buf, sizeof( buf ), MSG_PEEK,
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100476 (struct sockaddr *) &client_addr, &n );
477 }
478
479 if( ret < 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000480 {
Manuel Pégourié-Gonnard9a6b4422014-07-21 13:42:54 +0200481 if( net_would_block( bind_fd ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 return( MBEDTLS_ERR_NET_WANT_READ );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484 return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000485 }
486
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100487 /* UDP: hijack the listening socket for communicating with the client */
488 if( type != SOCK_STREAM )
489 {
490 if( connect( bind_fd, (struct sockaddr *) &client_addr, n ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491 return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
Manuel Pégourié-Gonnardf5a13122014-03-23 17:38:16 +0100492
493 *client_fd = bind_fd;
494 }
495
Paul Bakker5121ce52009-01-03 21:22:43 +0000496 if( client_ip != NULL )
Manuel Pégourié-Gonnard6e315a92013-12-13 16:21:25 +0100497 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498#if defined(MBEDTLS_HAVE_IPV6)
Manuel Pégourié-Gonnard6e315a92013-12-13 16:21:25 +0100499 if( client_addr.ss_family == AF_INET )
500 {
501 struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
502 memcpy( client_ip, &addr4->sin_addr.s_addr,
503 sizeof( addr4->sin_addr.s_addr ) );
504 }
505 else
506 {
507 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
508 memcpy( client_ip, &addr6->sin6_addr.s6_addr,
509 sizeof( addr6->sin6_addr.s6_addr ) );
510 }
511#else
Paul Bakker5121ce52009-01-03 21:22:43 +0000512 memcpy( client_ip, &client_addr.sin_addr.s_addr,
513 sizeof( client_addr.sin_addr.s_addr ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514#endif /* MBEDTLS_HAVE_IPV6 */
Manuel Pégourié-Gonnard6e315a92013-12-13 16:21:25 +0100515 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000516
517 return( 0 );
518}
519
520/*
521 * Set the socket blocking or non-blocking
522 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200523int mbedtls_net_set_block( int fd )
Paul Bakker5121ce52009-01-03 21:22:43 +0000524{
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100525#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
526 !defined(EFI32)
Paul Bakkerf4f69682011-04-24 16:08:12 +0000527 u_long n = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000528 return( ioctlsocket( fd, FIONBIO, &n ) );
529#else
530 return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) & ~O_NONBLOCK ) );
531#endif
532}
533
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534int mbedtls_net_set_nonblock( int fd )
Paul Bakker5121ce52009-01-03 21:22:43 +0000535{
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100536#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
537 !defined(EFI32)
Paul Bakkerf4f69682011-04-24 16:08:12 +0000538 u_long n = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000539 return( ioctlsocket( fd, FIONBIO, &n ) );
540#else
541 return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) );
542#endif
543}
544
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200545#if defined(MBEDTLS_HAVE_TIME)
Paul Bakker5121ce52009-01-03 21:22:43 +0000546/*
547 * Portable usleep helper
548 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200549void mbedtls_net_usleep( unsigned long usec )
Paul Bakker5121ce52009-01-03 21:22:43 +0000550{
551 struct timeval tv;
Manuel Pégourié-Gonnarde4232462014-11-21 09:52:23 +0100552 tv.tv_sec = usec / 1000000;
Paul Bakker82788fb2014-10-20 13:59:19 +0200553#if !defined(_WIN32) && ( defined(__unix__) || defined(__unix) || \
554 ( defined(__APPLE__) && defined(__MACH__) ) )
Manuel Pégourié-Gonnarde4232462014-11-21 09:52:23 +0100555 tv.tv_usec = (suseconds_t) usec % 1000000;
Sander Niemeijeref5087d2014-08-16 12:45:52 +0200556#else
Manuel Pégourié-Gonnarde4232462014-11-21 09:52:23 +0100557 tv.tv_usec = usec % 1000000;
Sander Niemeijeref5087d2014-08-16 12:45:52 +0200558#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000559 select( 0, NULL, NULL, NULL, &tv );
560}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200561#endif /* MBEDTLS_HAVE_TIME */
Paul Bakker5121ce52009-01-03 21:22:43 +0000562
563/*
564 * Read at most 'len' characters
565 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100567{
Paul Bakker80025412014-01-23 20:59:49 +0100568 int fd = *((int *) ctx);
Sander Niemeijeref5087d2014-08-16 12:45:52 +0200569 int ret = (int) read( fd, buf, len );
Paul Bakker5121ce52009-01-03 21:22:43 +0000570
Paul Bakker5121ce52009-01-03 21:22:43 +0000571 if( ret < 0 )
572 {
Paul Bakker80025412014-01-23 20:59:49 +0100573 if( net_would_block( fd ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200574 return( MBEDTLS_ERR_NET_WANT_READ );
Paul Bakker5121ce52009-01-03 21:22:43 +0000575
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100576#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
577 !defined(EFI32)
Paul Bakker5121ce52009-01-03 21:22:43 +0000578 if( WSAGetLastError() == WSAECONNRESET )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200579 return( MBEDTLS_ERR_NET_CONN_RESET );
Paul Bakker5121ce52009-01-03 21:22:43 +0000580#else
581 if( errno == EPIPE || errno == ECONNRESET )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200582 return( MBEDTLS_ERR_NET_CONN_RESET );
Paul Bakker5121ce52009-01-03 21:22:43 +0000583
584 if( errno == EINTR )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200585 return( MBEDTLS_ERR_NET_WANT_READ );
Paul Bakker5121ce52009-01-03 21:22:43 +0000586#endif
587
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200588 return( MBEDTLS_ERR_NET_RECV_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000589 }
590
591 return( ret );
592}
593
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594#if defined(MBEDTLS_HAVE_TIME)
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200595/*
Manuel Pégourié-Gonnardc8d8e972014-10-01 15:01:39 +0200596 * Read at most 'len' characters, blocking for at most 'timeout' ms
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200597 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
Manuel Pégourié-Gonnardc8d8e972014-10-01 15:01:39 +0200599 uint32_t timeout )
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200600{
601 int ret;
602 struct timeval tv;
603 fd_set read_fds;
604 int fd = *((int *) ctx);
605
606 FD_ZERO( &read_fds );
607 FD_SET( fd, &read_fds );
608
Manuel Pégourié-Gonnardc8d8e972014-10-01 15:01:39 +0200609 tv.tv_sec = timeout / 1000;
610 tv.tv_usec = ( timeout % 1000 ) * 1000;
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200611
612 ret = select( fd + 1, &read_fds, NULL, NULL, &tv );
613
614 /* Zero fds ready means we timed out */
615 if( ret == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200616 return( MBEDTLS_ERR_NET_TIMEOUT );
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200617
618 if( ret < 0 )
619 {
620#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
621 !defined(EFI32)
622 if( WSAGetLastError() == WSAEINTR )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200623 return( MBEDTLS_ERR_NET_WANT_READ );
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200624#else
625 if( errno == EINTR )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200626 return( MBEDTLS_ERR_NET_WANT_READ );
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200627#endif
628
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629 return( MBEDTLS_ERR_NET_RECV_FAILED );
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200630 }
631
632 /* This call will not block */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200633 return( mbedtls_net_recv( ctx, buf, len ) );
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200634}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635#endif /* MBEDTLS_HAVE_TIME */
Manuel Pégourié-Gonnard9d9b0032014-09-18 11:22:45 +0200636
Paul Bakker5121ce52009-01-03 21:22:43 +0000637/*
638 * Write at most 'len' characters
639 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200640int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
Paul Bakker5121ce52009-01-03 21:22:43 +0000641{
Paul Bakker80025412014-01-23 20:59:49 +0100642 int fd = *((int *) ctx);
Sander Niemeijeref5087d2014-08-16 12:45:52 +0200643 int ret = (int) write( fd, buf, len );
Paul Bakker5121ce52009-01-03 21:22:43 +0000644
645 if( ret < 0 )
646 {
Paul Bakker80025412014-01-23 20:59:49 +0100647 if( net_would_block( fd ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648 return( MBEDTLS_ERR_NET_WANT_WRITE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000649
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100650#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
651 !defined(EFI32)
Paul Bakker5121ce52009-01-03 21:22:43 +0000652 if( WSAGetLastError() == WSAECONNRESET )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653 return( MBEDTLS_ERR_NET_CONN_RESET );
Paul Bakker5121ce52009-01-03 21:22:43 +0000654#else
655 if( errno == EPIPE || errno == ECONNRESET )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656 return( MBEDTLS_ERR_NET_CONN_RESET );
Paul Bakker5121ce52009-01-03 21:22:43 +0000657
658 if( errno == EINTR )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659 return( MBEDTLS_ERR_NET_WANT_WRITE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000660#endif
661
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 return( MBEDTLS_ERR_NET_SEND_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000663 }
664
665 return( ret );
666}
667
668/*
669 * Gracefully close the connection
670 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671void mbedtls_net_close( int fd )
Paul Bakker5121ce52009-01-03 21:22:43 +0000672{
673 shutdown( fd, 2 );
674 close( fd );
675}
676
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200677#endif /* MBEDTLS_NET_C */