mbedtls ported to mbed-classic

Fork of mbedtls by Christopher Haster

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers net.c Source File

net.c

00001 /*
00002  *  TCP/IP or UDP/IP networking functions
00003  *
00004  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
00005  *  SPDX-License-Identifier: Apache-2.0
00006  *
00007  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
00008  *  not use this file except in compliance with the License.
00009  *  You may obtain a copy of the License at
00010  *
00011  *  http://www.apache.org/licenses/LICENSE-2.0
00012  *
00013  *  Unless required by applicable law or agreed to in writing, software
00014  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00015  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016  *  See the License for the specific language governing permissions and
00017  *  limitations under the License.
00018  *
00019  *  This file is part of mbed TLS (https://tls.mbed.org)
00020  */
00021 
00022 #if !defined(MBEDTLS_CONFIG_FILE)
00023 #include "mbedtls/config.h"
00024 #else
00025 #include MBEDTLS_CONFIG_FILE
00026 #endif
00027 
00028 #if defined(MBEDTLS_NET_C)
00029 
00030 #include "mbedtls/net.h"
00031 
00032 #include <string.h>
00033 
00034 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
00035     !defined(EFI32)
00036 
00037 #ifdef _WIN32_WINNT
00038 #undef _WIN32_WINNT
00039 #endif
00040 /* Enables getaddrinfo() & Co */
00041 #define _WIN32_WINNT 0x0501
00042 #include <ws2tcpip.h>
00043 
00044 #include <winsock2.h>
00045 #include <windows.h>
00046 
00047 #if defined(_MSC_VER)
00048 #if defined(_WIN32_WCE)
00049 #pragma comment( lib, "ws2.lib" )
00050 #else
00051 #pragma comment( lib, "ws2_32.lib" )
00052 #endif
00053 #endif /* _MSC_VER */
00054 
00055 #define read(fd,buf,len)        recv(fd,(char*)buf,(int) len,0)
00056 #define write(fd,buf,len)       send(fd,(char*)buf,(int) len,0)
00057 #define close(fd)               closesocket(fd)
00058 
00059 static int wsa_init_done = 0;
00060 
00061 #else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
00062 
00063 #include <sys/types.h>
00064 #include <sys/socket.h>
00065 #include <netinet/in.h>
00066 #include <arpa/inet.h>
00067 #include <sys/time.h>
00068 #include <unistd.h>
00069 #include <signal.h>
00070 #include <fcntl.h>
00071 #include <netdb.h>
00072 #include <errno.h>
00073 
00074 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
00075 
00076 /* Some MS functions want int and MSVC warns if we pass size_t,
00077  * but the standard fucntions use socklen_t, so cast only for MSVC */
00078 #if defined(_MSC_VER)
00079 #define MSVC_INT_CAST   (int)
00080 #else
00081 #define MSVC_INT_CAST
00082 #endif
00083 
00084 #include <stdlib.h>
00085 #include <stdio.h>
00086 
00087 #include <time.h>
00088 
00089 #include <stdint.h>
00090 
00091 /*
00092  * Prepare for using the sockets interface
00093  */
00094 static int net_prepare( void )
00095 {
00096 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
00097     !defined(EFI32)
00098     WSADATA wsaData;
00099 
00100     if( wsa_init_done == 0 )
00101     {
00102         if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
00103             return( MBEDTLS_ERR_NET_SOCKET_FAILED );
00104 
00105         wsa_init_done = 1;
00106     }
00107 #else
00108 #if !defined(EFIX64) && !defined(EFI32)
00109     signal( SIGPIPE, SIG_IGN );
00110 #endif
00111 #endif
00112     return( 0 );
00113 }
00114 
00115 /*
00116  * Initialize a context
00117  */
00118 void mbedtls_net_init( mbedtls_net_context *ctx )
00119 {
00120     ctx->fd = -1;
00121 }
00122 
00123 /*
00124  * Initiate a TCP connection with host:port and the given protocol
00125  */
00126 int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto )
00127 {
00128     int ret;
00129     struct addrinfo hints, *addr_list, *cur;
00130 
00131     if( ( ret = net_prepare() ) != 0 )
00132         return( ret );
00133 
00134     /* Do name resolution with both IPv6 and IPv4 */
00135     memset( &hints, 0, sizeof( hints ) );
00136     hints.ai_family = AF_UNSPEC;
00137     hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
00138     hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
00139 
00140     if( getaddrinfo( host, port, &hints, &addr_list ) != 0 )
00141         return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
00142 
00143     /* Try the sockaddrs until a connection succeeds */
00144     ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
00145     for( cur = addr_list; cur != NULL; cur = cur->ai_next )
00146     {
00147         ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
00148                             cur->ai_protocol );
00149         if( ctx->fd < 0 )
00150         {
00151             ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
00152             continue;
00153         }
00154 
00155         if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 )
00156         {
00157             ret = 0;
00158             break;
00159         }
00160 
00161         close( ctx->fd );
00162         ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
00163     }
00164 
00165     freeaddrinfo( addr_list );
00166 
00167     return( ret );
00168 }
00169 
00170 /*
00171  * Create a listening socket on bind_ip:port
00172  */
00173 int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto )
00174 {
00175     int n, ret;
00176     struct addrinfo hints, *addr_list, *cur;
00177 
00178     if( ( ret = net_prepare() ) != 0 )
00179         return( ret );
00180 
00181     /* Bind to IPv6 and/or IPv4, but only in the desired protocol */
00182     memset( &hints, 0, sizeof( hints ) );
00183     hints.ai_family = AF_UNSPEC;
00184     hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
00185     hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
00186     if( bind_ip == NULL )
00187         hints.ai_flags = AI_PASSIVE;
00188 
00189     if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 )
00190         return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
00191 
00192     /* Try the sockaddrs until a binding succeeds */
00193     ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
00194     for( cur = addr_list; cur != NULL; cur = cur->ai_next )
00195     {
00196         ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
00197                             cur->ai_protocol );
00198         if( ctx->fd < 0 )
00199         {
00200             ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
00201             continue;
00202         }
00203 
00204         n = 1;
00205         if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR,
00206                         (const char *) &n, sizeof( n ) ) != 0 )
00207         {
00208             close( ctx->fd );
00209             ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
00210             continue;
00211         }
00212 
00213         if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 )
00214         {
00215             close( ctx->fd );
00216             ret = MBEDTLS_ERR_NET_BIND_FAILED;
00217             continue;
00218         }
00219 
00220         /* Listen only makes sense for TCP */
00221         if( proto == MBEDTLS_NET_PROTO_TCP )
00222         {
00223             if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 )
00224             {
00225                 close( ctx->fd );
00226                 ret = MBEDTLS_ERR_NET_LISTEN_FAILED;
00227                 continue;
00228             }
00229         }
00230 
00231         /* I we ever get there, it's a success */
00232         ret = 0;
00233         break;
00234     }
00235 
00236     freeaddrinfo( addr_list );
00237 
00238     return( ret );
00239 
00240 }
00241 
00242 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
00243     !defined(EFI32)
00244 /*
00245  * Check if the requested operation would be blocking on a non-blocking socket
00246  * and thus 'failed' with a negative return value.
00247  */
00248 static int net_would_block( const mbedtls_net_context *ctx )
00249 {
00250     ((void) ctx);
00251     return( WSAGetLastError() == WSAEWOULDBLOCK );
00252 }
00253 #else
00254 /*
00255  * Check if the requested operation would be blocking on a non-blocking socket
00256  * and thus 'failed' with a negative return value.
00257  *
00258  * Note: on a blocking socket this function always returns 0!
00259  */
00260 static int net_would_block( const mbedtls_net_context *ctx )
00261 {
00262     /*
00263      * Never return 'WOULD BLOCK' on a non-blocking socket
00264      */
00265     if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK )
00266         return( 0 );
00267 
00268     switch( errno )
00269     {
00270 #if defined EAGAIN
00271         case EAGAIN:
00272 #endif
00273 #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
00274         case EWOULDBLOCK:
00275 #endif
00276             return( 1 );
00277     }
00278     return( 0 );
00279 }
00280 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
00281 
00282 /*
00283  * Accept a connection from a remote client
00284  */
00285 int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
00286                         mbedtls_net_context *client_ctx,
00287                         void *client_ip, size_t buf_size, size_t *ip_len )
00288 {
00289     int ret;
00290     int type;
00291 
00292     struct sockaddr_storage client_addr;
00293 
00294 #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) ||  \
00295     defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t)
00296     socklen_t n = (socklen_t) sizeof( client_addr );
00297     socklen_t type_len = (socklen_t) sizeof( type );
00298 #else
00299     int n = (int) sizeof( client_addr );
00300     int type_len = (int) sizeof( type );
00301 #endif
00302 
00303     /* Is this a TCP or UDP socket? */
00304     if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE,
00305                     (void *) &type, &type_len ) != 0 ||
00306         ( type != SOCK_STREAM && type != SOCK_DGRAM ) )
00307     {
00308         return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
00309     }
00310 
00311     if( type == SOCK_STREAM )
00312     {
00313         /* TCP: actual accept() */
00314         ret = client_ctx->fd = (int) accept( bind_ctx->fd,
00315                                          (struct sockaddr *) &client_addr, &n );
00316     }
00317     else
00318     {
00319         /* UDP: wait for a message, but keep it in the queue */
00320         char buf[1] = { 0 };
00321 
00322         ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK,
00323                         (struct sockaddr *) &client_addr, &n );
00324 
00325 #if defined(_WIN32)
00326         if( ret == SOCKET_ERROR &&
00327             WSAGetLastError() == WSAEMSGSIZE )
00328         {
00329             /* We know buf is too small, thanks, just peeking here */
00330             ret = 0;
00331         }
00332 #endif
00333     }
00334 
00335     if( ret < 0 )
00336     {
00337         if( net_would_block( bind_ctx ) != 0 )
00338             return( MBEDTLS_ERR_SSL_WANT_READ );
00339 
00340         return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
00341     }
00342 
00343     /* UDP: hijack the listening socket to communicate with the client,
00344      * then bind a new socket to accept new connections */
00345     if( type != SOCK_STREAM )
00346     {
00347         struct sockaddr_storage local_addr;
00348         int one = 1;
00349 
00350         if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 )
00351             return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
00352 
00353         client_ctx->fd = bind_ctx->fd;
00354         bind_ctx->fd   = -1; /* In case we exit early */
00355 
00356         n = sizeof( struct sockaddr_storage );
00357         if( getsockname( client_ctx->fd,
00358                          (struct sockaddr *) &local_addr, &n ) != 0 ||
00359             ( bind_ctx->fd = (int) socket( local_addr.ss_family,
00360                                            SOCK_DGRAM, IPPROTO_UDP ) ) < 0 ||
00361             setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR,
00362                         (const char *) &one, sizeof( one ) ) != 0 )
00363         {
00364             return( MBEDTLS_ERR_NET_SOCKET_FAILED );
00365         }
00366 
00367         if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 )
00368         {
00369             return( MBEDTLS_ERR_NET_BIND_FAILED );
00370         }
00371     }
00372 
00373     if( client_ip != NULL )
00374     {
00375         if( client_addr.ss_family == AF_INET )
00376         {
00377             struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
00378             *ip_len = sizeof( addr4->sin_addr.s_addr );
00379 
00380             if( buf_size < *ip_len )
00381                 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
00382 
00383             memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len );
00384         }
00385         else
00386         {
00387             struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
00388             *ip_len = sizeof( addr6->sin6_addr.s6_addr );
00389 
00390             if( buf_size < *ip_len )
00391                 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
00392 
00393             memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len);
00394         }
00395     }
00396 
00397     return( 0 );
00398 }
00399 
00400 /*
00401  * Set the socket blocking or non-blocking
00402  */
00403 int mbedtls_net_set_block( mbedtls_net_context *ctx )
00404 {
00405 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
00406     !defined(EFI32)
00407     u_long n = 0;
00408     return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
00409 #else
00410     return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) );
00411 #endif
00412 }
00413 
00414 int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
00415 {
00416 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
00417     !defined(EFI32)
00418     u_long n = 1;
00419     return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
00420 #else
00421     return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) );
00422 #endif
00423 }
00424 
00425 /*
00426  * Portable usleep helper
00427  */
00428 void mbedtls_net_usleep( unsigned long usec )
00429 {
00430 #if defined(_WIN32)
00431     Sleep( ( usec + 999 ) / 1000 );
00432 #else
00433     struct timeval tv;
00434     tv.tv_sec  = usec / 1000000;
00435 #if defined(__unix__) || defined(__unix) || \
00436     ( defined(__APPLE__) && defined(__MACH__) )
00437     tv.tv_usec = (suseconds_t) usec % 1000000;
00438 #else
00439     tv.tv_usec = usec % 1000000;
00440 #endif
00441     select( 0, NULL, NULL, NULL, &tv );
00442 #endif
00443 }
00444 
00445 /*
00446  * Read at most 'len' characters
00447  */
00448 int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
00449 {
00450     int ret;
00451     int fd = ((mbedtls_net_context *) ctx)->fd;
00452 
00453     if( fd < 0 )
00454         return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
00455 
00456     ret = (int) read( fd, buf, len );
00457 
00458     if( ret < 0 )
00459     {
00460         if( net_would_block( ctx ) != 0 )
00461             return( MBEDTLS_ERR_SSL_WANT_READ );
00462 
00463 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
00464     !defined(EFI32)
00465         if( WSAGetLastError() == WSAECONNRESET )
00466             return( MBEDTLS_ERR_NET_CONN_RESET );
00467 #else
00468         if( errno == EPIPE || errno == ECONNRESET )
00469             return( MBEDTLS_ERR_NET_CONN_RESET );
00470 
00471         if( errno == EINTR )
00472             return( MBEDTLS_ERR_SSL_WANT_READ );
00473 #endif
00474 
00475         return( MBEDTLS_ERR_NET_RECV_FAILED );
00476     }
00477 
00478     return( ret );
00479 }
00480 
00481 /*
00482  * Read at most 'len' characters, blocking for at most 'timeout' ms
00483  */
00484 int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
00485                       uint32_t timeout )
00486 {
00487     int ret;
00488     struct timeval tv;
00489     fd_set read_fds;
00490     int fd = ((mbedtls_net_context *) ctx)->fd;
00491 
00492     if( fd < 0 )
00493         return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
00494 
00495     FD_ZERO( &read_fds );
00496     FD_SET( fd, &read_fds );
00497 
00498     tv.tv_sec  = timeout / 1000;
00499     tv.tv_usec = ( timeout % 1000 ) * 1000;
00500 
00501     ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv );
00502 
00503     /* Zero fds ready means we timed out */
00504     if( ret == 0 )
00505         return( MBEDTLS_ERR_SSL_TIMEOUT );
00506 
00507     if( ret < 0 )
00508     {
00509 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
00510     !defined(EFI32)
00511         if( WSAGetLastError() == WSAEINTR )
00512             return( MBEDTLS_ERR_SSL_WANT_READ );
00513 #else
00514         if( errno == EINTR )
00515             return( MBEDTLS_ERR_SSL_WANT_READ );
00516 #endif
00517 
00518         return( MBEDTLS_ERR_NET_RECV_FAILED );
00519     }
00520 
00521     /* This call will not block */
00522     return( mbedtls_net_recv( ctx, buf, len ) );
00523 }
00524 
00525 /*
00526  * Write at most 'len' characters
00527  */
00528 int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
00529 {
00530     int ret;
00531     int fd = ((mbedtls_net_context *) ctx)->fd;
00532 
00533     if( fd < 0 )
00534         return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
00535 
00536     ret = (int) write( fd, buf, len );
00537 
00538     if( ret < 0 )
00539     {
00540         if( net_would_block( ctx ) != 0 )
00541             return( MBEDTLS_ERR_SSL_WANT_WRITE );
00542 
00543 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
00544     !defined(EFI32)
00545         if( WSAGetLastError() == WSAECONNRESET )
00546             return( MBEDTLS_ERR_NET_CONN_RESET );
00547 #else
00548         if( errno == EPIPE || errno == ECONNRESET )
00549             return( MBEDTLS_ERR_NET_CONN_RESET );
00550 
00551         if( errno == EINTR )
00552             return( MBEDTLS_ERR_SSL_WANT_WRITE );
00553 #endif
00554 
00555         return( MBEDTLS_ERR_NET_SEND_FAILED );
00556     }
00557 
00558     return( ret );
00559 }
00560 
00561 /*
00562  * Gracefully close the connection
00563  */
00564 void mbedtls_net_free( mbedtls_net_context *ctx )
00565 {
00566     if( ctx->fd == -1 )
00567         return;
00568 
00569     shutdown( ctx->fd, 2 );
00570     close( ctx->fd );
00571 
00572     ctx->fd = -1;
00573 }
00574 
00575 #endif /* MBEDTLS_NET_C */