net.c 14.9 KB
Newer Older
1
/*
2
 *  TCP/IP or UDP/IP networking functions
3
 *
4
 *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5
 *
6
 *  This file is part of mbed TLS (https://tls.mbed.org)
7
 *
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

23
#if !defined(MBEDTLS_CONFIG_FILE)
24
#include "mbedtls/config.h"
25
#else
26
#include MBEDTLS_CONFIG_FILE
27
#endif
28

29
#if defined(MBEDTLS_NET_C)
30

31
#include "mbedtls/net.h"
32

33 34
#include <string.h>

35 36
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
    !defined(EFI32)
37

38 39 40 41
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
/* Enables getaddrinfo() & Co */
42
#define _WIN32_WINNT 0x0501
43 44
#include <ws2tcpip.h>

45 46 47
#include <winsock2.h>
#include <windows.h>

48
#if defined(_MSC_VER)
49 50 51 52 53
#if defined(_WIN32_WCE)
#pragma comment( lib, "ws2.lib" )
#else
#pragma comment( lib, "ws2_32.lib" )
#endif
54
#endif /* _MSC_VER */
55

56 57
#define read(fd,buf,len)        recv(fd,(char*)buf,(int) len,0)
#define write(fd,buf,len)       send(fd,(char*)buf,(int) len,0)
58 59 60 61
#define close(fd)               closesocket(fd)

static int wsa_init_done = 0;

62
#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
63 64 65 66 67 68 69 70 71 72 73

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <netdb.h>
#include <errno.h>
74

75
#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
76

77 78 79 80 81 82 83 84
/* Some MS functions want int and MSVC warns if we pass size_t,
 * but the standard fucntions use socklen_t, so cast only for MSVC */
#if defined(_MSC_VER)
#define MSVC_INT_CAST   (int)
#else
#define MSVC_INT_CAST
#endif

85 86
#include <stdlib.h>
#include <stdio.h>
87

88 89
#include <time.h>

90
#include <stdint.h>
91

92
/*
93
 * Prepare for using the sockets interface
94
 */
95
static int net_prepare( void )
96
{
97 98
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
    !defined(EFI32)
99 100 101 102
    WSADATA wsaData;

    if( wsa_init_done == 0 )
    {
103
        if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
104
            return( MBEDTLS_ERR_NET_SOCKET_FAILED );
105 106 107 108

        wsa_init_done = 1;
    }
#else
109
#if !defined(EFIX64) && !defined(EFI32)
110
    signal( SIGPIPE, SIG_IGN );
111
#endif
112
#endif
113
    return( 0 );
114 115
}

116 117 118 119 120 121 122 123
/*
 * Initialize a context
 */
void mbedtls_net_init( mbedtls_net_context *ctx )
{
    ctx->fd = -1;
}

124
/*
125
 * Initiate a TCP connection with host:port and the given protocol
126
 */
127
int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto )
128
{
129
    int ret;
130 131
    struct addrinfo hints, *addr_list, *cur;

132 133
    if( ( ret = net_prepare() ) != 0 )
        return( ret );
134

135
    /* Do name resolution with both IPv6 and IPv4 */
136 137
    memset( &hints, 0, sizeof( hints ) );
    hints.ai_family = AF_UNSPEC;
138 139
    hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
    hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
140

141
    if( getaddrinfo( host, port, &hints, &addr_list ) != 0 )
142
        return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
143 144

    /* Try the sockaddrs until a connection succeeds */
145
    ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
146 147
    for( cur = addr_list; cur != NULL; cur = cur->ai_next )
    {
148
        ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
149
                            cur->ai_protocol );
150
        if( ctx->fd < 0 )
151
        {
152
            ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
153 154 155
            continue;
        }

156
        if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 )
157 158 159 160 161
        {
            ret = 0;
            break;
        }

162
        close( ctx->fd );
163
        ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
164 165 166 167 168
    }

    freeaddrinfo( addr_list );

    return( ret );
169 170 171 172 173
}

/*
 * Create a listening socket on bind_ip:port
 */
174
int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto )
175
{
176
    int n, ret;
177 178
    struct addrinfo hints, *addr_list, *cur;

179 180
    if( ( ret = net_prepare() ) != 0 )
        return( ret );
181

182
    /* Bind to IPv6 and/or IPv4, but only in the desired protocol */
183 184
    memset( &hints, 0, sizeof( hints ) );
    hints.ai_family = AF_UNSPEC;
185 186
    hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
    hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
187 188 189
    if( bind_ip == NULL )
        hints.ai_flags = AI_PASSIVE;

190
    if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 )
191
        return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
192 193

    /* Try the sockaddrs until a binding succeeds */
194
    ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
195 196
    for( cur = addr_list; cur != NULL; cur = cur->ai_next )
    {
197
        ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
198
                            cur->ai_protocol );
199
        if( ctx->fd < 0 )
200
        {
201
            ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
202 203 204
            continue;
        }

205
        n = 1;
206
        if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR,
207 208
                        (const char *) &n, sizeof( n ) ) != 0 )
        {
209
            close( ctx->fd );
210
            ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
211 212
            continue;
        }
213

214
        if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 )
215
        {
216
            close( ctx->fd );
217
            ret = MBEDTLS_ERR_NET_BIND_FAILED;
218 219 220
            continue;
        }

221
        /* Listen only makes sense for TCP */
222
        if( proto == MBEDTLS_NET_PROTO_TCP )
223
        {
224
            if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 )
225
            {
226
                close( ctx->fd );
227
                ret = MBEDTLS_ERR_NET_LISTEN_FAILED;
228 229
                continue;
            }
230 231 232 233 234 235 236 237 238 239 240
        }

        /* I we ever get there, it's a success */
        ret = 0;
        break;
    }

    freeaddrinfo( addr_list );

    return( ret );

241 242
}

243 244
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
    !defined(EFI32)
245
/*
246 247
 * Check if the requested operation would be blocking on a non-blocking socket
 * and thus 'failed' with a negative return value.
248
 */
249
static int net_would_block( const mbedtls_net_context *ctx )
250
{
251
    ((void) ctx);
252
    return( WSAGetLastError() == WSAEWOULDBLOCK );
253
}
254
#else
255 256 257 258 259 260
/*
 * Check if the requested operation would be blocking on a non-blocking socket
 * and thus 'failed' with a negative return value.
 *
 * Note: on a blocking socket this function always returns 0!
 */
261
static int net_would_block( const mbedtls_net_context *ctx )
262 263 264 265
{
    /*
     * Never return 'WOULD BLOCK' on a non-blocking socket
     */
266
    if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK )
267 268
        return( 0 );

269 270 271 272 273 274 275 276 277 278 279 280
    switch( errno )
    {
#if defined EAGAIN
        case EAGAIN:
#endif
#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
        case EWOULDBLOCK:
#endif
            return( 1 );
    }
    return( 0 );
}
281
#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
282 283 284 285

/*
 * Accept a connection from a remote client
 */
286 287
int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
                        mbedtls_net_context *client_ctx,
288
                        void *client_ip, size_t buf_size, size_t *ip_len )
289
{
290 291 292
    int ret;
    int type;

293
    struct sockaddr_storage client_addr;
294

295 296
#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) ||  \
    defined(_SOCKLEN_T_DECLARED)
297
    socklen_t n = (socklen_t) sizeof( client_addr );
298
    socklen_t type_len = (socklen_t) sizeof( type );
299 300
#else
    int n = (int) sizeof( client_addr );
301
    int type_len = (int) sizeof( type );
302 303
#endif

304
    /* Is this a TCP or UDP socket? */
305 306
    if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE,
                    (void *) &type, &type_len ) != 0 ||
307 308
        ( type != SOCK_STREAM && type != SOCK_DGRAM ) )
    {
309
        return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
310
    }
311

312 313 314
    if( type == SOCK_STREAM )
    {
        /* TCP: actual accept() */
315
        ret = client_ctx->fd = (int) accept( bind_ctx->fd,
316 317 318 319 320 321 322
                                         (struct sockaddr *) &client_addr, &n );
    }
    else
    {
        /* UDP: wait for a message, but keep it in the queue */
        char buf[1] = { 0 };

323
        ret = recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK,
324
                        (struct sockaddr *) &client_addr, &n );
325 326 327 328 329 330 331 332 333

#if defined(_WIN32)
        if( ret == SOCKET_ERROR &&
            WSAGetLastError() == WSAEMSGSIZE )
        {
            /* We know buf is too small, thanks, just peeking here */
            ret = 0;
        }
#endif
334 335 336
    }

    if( ret < 0 )
337
    {
338
        if( net_would_block( bind_ctx ) != 0 )
339
            return( MBEDTLS_ERR_SSL_WANT_READ );
340

341
        return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
342 343
    }

344 345
    /* UDP: hijack the listening socket to communicate with the client,
     * then bind a new socket to accept new connections */
346 347
    if( type != SOCK_STREAM )
    {
348 349 350
        struct sockaddr_storage local_addr;
        int one = 1;

351
        if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 )
352
            return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
353

354
        client_ctx->fd = bind_ctx->fd;
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
        bind_ctx->fd   = -1; /* In case we exit early */

        n = sizeof( struct sockaddr_storage );
        if( getsockname( client_ctx->fd,
                         (struct sockaddr *) &local_addr, &n ) != 0 ||
            ( bind_ctx->fd = (int) socket( local_addr.ss_family,
                                           SOCK_DGRAM, IPPROTO_UDP ) ) < 0 ||
            setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR,
                        (const char *) &one, sizeof( one ) ) != 0 )
        {
            return( MBEDTLS_ERR_NET_SOCKET_FAILED );
        }

        if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 )
        {
            return( MBEDTLS_ERR_NET_BIND_FAILED );
        }
372 373
    }

374
    if( client_ip != NULL )
375 376 377 378
    {
        if( client_addr.ss_family == AF_INET )
        {
            struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
379 380 381 382 383 384
            *ip_len = sizeof( addr4->sin_addr.s_addr );

            if( buf_size < *ip_len )
                return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );

            memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len );
385 386 387 388
        }
        else
        {
            struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
389 390 391 392 393 394
            *ip_len = sizeof( addr6->sin6_addr.s6_addr );

            if( buf_size < *ip_len )
                return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );

            memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len);
395 396
        }
    }
397 398 399 400 401 402 403

    return( 0 );
}

/*
 * Set the socket blocking or non-blocking
 */
404
int mbedtls_net_set_block( mbedtls_net_context *ctx )
405
{
406 407
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
    !defined(EFI32)
408
    u_long n = 0;
409
    return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
410
#else
411
    return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) );
412 413 414
#endif
}

415
int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
416
{
417 418
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
    !defined(EFI32)
419
    u_long n = 1;
420
    return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
421
#else
422
    return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) );
423 424 425 426 427 428
#endif
}

/*
 * Portable usleep helper
 */
429
void mbedtls_net_usleep( unsigned long usec )
430
{
431 432 433
#if defined(_WIN32)
    Sleep( ( usec + 999 ) / 1000 );
#else
434
    struct timeval tv;
435
    tv.tv_sec  = usec / 1000000;
436 437
#if defined(__unix__) || defined(__unix) || \
    ( defined(__APPLE__) && defined(__MACH__) )
438
    tv.tv_usec = (suseconds_t) usec % 1000000;
439
#else
440
    tv.tv_usec = usec % 1000000;
441
#endif
442
    select( 0, NULL, NULL, NULL, &tv );
443
#endif
444 445 446 447 448
}

/*
 * Read at most 'len' characters
 */
449
int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
450
{
451
    int ret;
452
    int fd = ((mbedtls_net_context *) ctx)->fd;
453 454 455 456 457

    if( fd < 0 )
        return( MBEDTLS_ERR_NET_INVALID_CONTEXT );

    ret = (int) read( fd, buf, len );
458 459 460

    if( ret < 0 )
    {
461
        if( net_would_block( ctx ) != 0 )
462
            return( MBEDTLS_ERR_SSL_WANT_READ );
463

464 465
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
    !defined(EFI32)
466
        if( WSAGetLastError() == WSAECONNRESET )
467
            return( MBEDTLS_ERR_NET_CONN_RESET );
468 469
#else
        if( errno == EPIPE || errno == ECONNRESET )
470
            return( MBEDTLS_ERR_NET_CONN_RESET );
471 472

        if( errno == EINTR )
473
            return( MBEDTLS_ERR_SSL_WANT_READ );
474 475
#endif

476
        return( MBEDTLS_ERR_NET_RECV_FAILED );
477 478 479 480 481
    }

    return( ret );
}

482
/*
483
 * Read at most 'len' characters, blocking for at most 'timeout' ms
484
 */
485
int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
486
                      uint32_t timeout )
487 488 489 490
{
    int ret;
    struct timeval tv;
    fd_set read_fds;
491
    int fd = ((mbedtls_net_context *) ctx)->fd;
492

493 494 495
    if( fd < 0 )
        return( MBEDTLS_ERR_NET_INVALID_CONTEXT );

496 497 498
    FD_ZERO( &read_fds );
    FD_SET( fd, &read_fds );

499 500
    tv.tv_sec  = timeout / 1000;
    tv.tv_usec = ( timeout % 1000 ) * 1000;
501

502
    ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv );
503 504 505

    /* Zero fds ready means we timed out */
    if( ret == 0 )
506
        return( MBEDTLS_ERR_SSL_TIMEOUT );
507 508 509 510 511 512

    if( ret < 0 )
    {
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
    !defined(EFI32)
        if( WSAGetLastError() == WSAEINTR )
513
            return( MBEDTLS_ERR_SSL_WANT_READ );
514 515
#else
        if( errno == EINTR )
516
            return( MBEDTLS_ERR_SSL_WANT_READ );
517 518
#endif

519
        return( MBEDTLS_ERR_NET_RECV_FAILED );
520 521 522
    }

    /* This call will not block */
523
    return( mbedtls_net_recv( ctx, buf, len ) );
524 525
}

526 527 528
/*
 * Write at most 'len' characters
 */
529
int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
530
{
531
    int ret;
532
    int fd = ((mbedtls_net_context *) ctx)->fd;
533 534 535 536 537

    if( fd < 0 )
        return( MBEDTLS_ERR_NET_INVALID_CONTEXT );

    ret = (int) write( fd, buf, len );
538 539 540

    if( ret < 0 )
    {
541
        if( net_would_block( ctx ) != 0 )
542
            return( MBEDTLS_ERR_SSL_WANT_WRITE );
543

544 545
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
    !defined(EFI32)
546
        if( WSAGetLastError() == WSAECONNRESET )
547
            return( MBEDTLS_ERR_NET_CONN_RESET );
548 549
#else
        if( errno == EPIPE || errno == ECONNRESET )
550
            return( MBEDTLS_ERR_NET_CONN_RESET );
551 552

        if( errno == EINTR )
553
            return( MBEDTLS_ERR_SSL_WANT_WRITE );
554 555
#endif

556
        return( MBEDTLS_ERR_NET_SEND_FAILED );
557 558 559 560 561 562 563 564
    }

    return( ret );
}

/*
 * Gracefully close the connection
 */
565
void mbedtls_net_free( mbedtls_net_context *ctx )
566
{
567 568 569 570 571 572 573
    if( ctx->fd == -1 )
        return;

    shutdown( ctx->fd, 2 );
    close( ctx->fd );

    ctx->fd = -1;
574 575
}

576
#endif /* MBEDTLS_NET_C */