Merged IPv6 support in the NET module

This commit is contained in:
Paul Bakker 2013-12-17 14:33:42 +01:00
commit 5a607d26b7
6 changed files with 176 additions and 28 deletions

View file

@ -7,6 +7,7 @@ Features
(POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE) (POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE)
* Support for Curve25519 * Support for Curve25519
* Support for ECDH-RSA and ECDH-ECDSA key exchanges and ciphersuites * Support for ECDH-RSA and ECDH-ECDSA key exchanges and ciphersuites
* Support for IPv6 in the NET module
Changes Changes
* gen_prime() speedup * gen_prime() speedup

View file

@ -101,6 +101,16 @@
* Comment if your system does not support time functions * Comment if your system does not support time functions
*/ */
#define POLARSSL_HAVE_TIME #define POLARSSL_HAVE_TIME
/**
* \def POLARSSL_HAVE_IPV6
*
* System supports the basic socket interface for IPv6 (RFC 3493),
* specifically getaddrinfo(), freeaddrinfo() and struct sockaddr_storage.
*
* Comment if your system does not support the IPv6 socket interface
*/
#define POLARSSL_HAVE_IPV6
/* \} name SECTION: System support */ /* \} name SECTION: System support */
/** /**

View file

@ -82,9 +82,10 @@ int net_bind( int *fd, const char *bind_ip, int port );
* \param bind_fd Relevant socket * \param bind_fd Relevant socket
* \param client_fd Will contain the connected client socket * \param client_fd Will contain the connected client socket
* \param client_ip Will contain the client IP address * \param client_ip Will contain the client IP address
* Must be at least 4 bytes, or 16 if IPv6 is supported
* *
* \return 0 if successful, POLARSSL_ERR_NET_ACCEPT_FAILED, or * \return 0 if successful, POLARSSL_ERR_NET_ACCEPT_FAILED, or
* POLARSSL_ERR_NET_WOULD_BLOCK is bind_fd was set to * POLARSSL_ERR_NET_WANT_READ is bind_fd was set to
* non-blocking and accept() is blocking. * non-blocking and accept() is blocking.
*/ */
int net_accept( int bind_fd, int *client_fd, void *client_ip ); int net_accept( int bind_fd, int *client_fd, void *client_ip );

View file

@ -81,6 +81,11 @@ static int wsa_init_done = 0;
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
!defined(EFI32)
#define snprintf _snprintf
#endif
#if defined(POLARSSL_HAVE_TIME) #if defined(POLARSSL_HAVE_TIME)
#include <time.h> #include <time.h>
#endif #endif
@ -115,16 +120,12 @@ unsigned long net_htonl(unsigned long n);
#define net_htonl(n) POLARSSL_HTONL(n) #define net_htonl(n) POLARSSL_HTONL(n)
/* /*
* Initiate a TCP connection with host:port * Prepare for using the sockets interface
*/ */
int net_connect( int *fd, const char *host, int port ) static void net_prepare( void )
{ {
struct sockaddr_in server_addr;
struct hostent *server_host;
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
!defined(EFI32) !defined(EFI32)
WSADATA wsaData; WSADATA wsaData;
if( wsa_init_done == 0 ) if( wsa_init_done == 0 )
@ -139,6 +140,64 @@ int net_connect( int *fd, const char *host, int port )
signal( SIGPIPE, SIG_IGN ); signal( SIGPIPE, SIG_IGN );
#endif #endif
#endif #endif
}
/*
* Initiate a TCP connection with host:port
*/
int net_connect( int *fd, const char *host, int port )
{
#if defined(POLARSSL_HAVE_IPV6)
int ret = POLARSSL_ERR_NET_UNKNOWN_HOST;
struct addrinfo hints, *addr_list, *cur;
char port_str[6];
net_prepare();
/* getaddrinfo expects port as a string */
memset( port_str, 0, sizeof( port_str ) );
snprintf( port_str, sizeof( port_str ), "%d", port );
/* Do name resolution with both IPv6 and IPv4, but only TCP */
memset( &hints, 0, sizeof( hints ) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if( getaddrinfo( host, port_str, &hints, &addr_list ) != 0 )
return( POLARSSL_ERR_NET_UNKNOWN_HOST );
/* Try the sockaddrs until a connection succeeds */
for( cur = addr_list; cur != NULL; cur = cur->ai_next )
{
*fd = socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol );
if( *fd < 0 )
{
ret = POLARSSL_ERR_NET_SOCKET_FAILED;
continue;
}
if( connect( *fd, cur->ai_addr, cur->ai_addrlen ) == 0 )
{
ret = 0;
break;
}
close( *fd );
ret = POLARSSL_ERR_NET_CONNECT_FAILED;
}
freeaddrinfo( addr_list );
return( ret );
#else
/* Legacy IPv4-only version */
struct sockaddr_in server_addr;
struct hostent *server_host;
net_prepare();
if( ( server_host = gethostbyname( host ) ) == NULL ) if( ( server_host = gethostbyname( host ) ) == NULL )
return( POLARSSL_ERR_NET_UNKNOWN_HOST ); return( POLARSSL_ERR_NET_UNKNOWN_HOST );
@ -161,6 +220,7 @@ int net_connect( int *fd, const char *host, int port )
} }
return( 0 ); return( 0 );
#endif /* POLARSSL_HAVE_IPV6 */
} }
/* /*
@ -168,25 +228,72 @@ int net_connect( int *fd, const char *host, int port )
*/ */
int net_bind( int *fd, const char *bind_ip, int port ) int net_bind( int *fd, const char *bind_ip, int port )
{ {
#if defined(POLARSSL_HAVE_IPV6)
int n, ret = POLARSSL_ERR_NET_UNKNOWN_HOST;
struct addrinfo hints, *addr_list, *cur;
char port_str[6];
net_prepare();
/* getaddrinfo expects port as a string */
memset( port_str, 0, sizeof( port_str ) );
snprintf( port_str, sizeof( port_str ), "%d", port );
/* Bind to IPv6 and/or IPv4, but only in TCP */
memset( &hints, 0, sizeof( hints ) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if( bind_ip == NULL )
hints.ai_flags = AI_PASSIVE;
if( getaddrinfo( bind_ip, port_str, &hints, &addr_list ) != 0 )
return( POLARSSL_ERR_NET_UNKNOWN_HOST );
/* Try the sockaddrs until a binding succeeds */
for( cur = addr_list; cur != NULL; cur = cur->ai_next )
{
*fd = socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol );
if( *fd < 0 )
{
ret = POLARSSL_ERR_NET_SOCKET_FAILED;
continue;
}
n = 1;
setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR,
(const char *) &n, sizeof( n ) );
if( bind( *fd, cur->ai_addr, cur->ai_addrlen ) != 0 )
{
close( *fd );
ret = POLARSSL_ERR_NET_BIND_FAILED;
continue;
}
if( listen( *fd, POLARSSL_NET_LISTEN_BACKLOG ) != 0 )
{
close( *fd );
ret = POLARSSL_ERR_NET_LISTEN_FAILED;
continue;
}
/* I we ever get there, it's a success */
ret = 0;
break;
}
freeaddrinfo( addr_list );
return( ret );
#else
/* Legacy IPv4-only version */
int n, c[4]; int n, c[4];
struct sockaddr_in server_addr; struct sockaddr_in server_addr;
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ net_prepare();
!defined(EFI32)
WSADATA wsaData;
if( wsa_init_done == 0 )
{
if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR )
return( POLARSSL_ERR_NET_SOCKET_FAILED );
wsa_init_done = 1;
}
#else
#if !defined(EFIX64) && !defined(EFI32)
signal( SIGPIPE, SIG_IGN );
#endif
#endif
if( ( *fd = (int) socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 ) if( ( *fd = (int) socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 )
return( POLARSSL_ERR_NET_SOCKET_FAILED ); return( POLARSSL_ERR_NET_SOCKET_FAILED );
@ -230,6 +337,7 @@ int net_bind( int *fd, const char *bind_ip, int port )
} }
return( 0 ); return( 0 );
#endif /* POLARSSL_HAVE_IPV6 */
} }
/* /*
@ -260,7 +368,11 @@ static int net_is_blocking( void )
*/ */
int net_accept( int bind_fd, int *client_fd, void *client_ip ) int net_accept( int bind_fd, int *client_fd, void *client_ip )
{ {
#if defined(POLARSSL_HAVE_IPV6)
struct sockaddr_storage client_addr;
#else
struct sockaddr_in client_addr; struct sockaddr_in client_addr;
#endif
#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \
defined(_SOCKLEN_T_DECLARED) defined(_SOCKLEN_T_DECLARED)
@ -281,8 +393,25 @@ int net_accept( int bind_fd, int *client_fd, void *client_ip )
} }
if( client_ip != NULL ) if( client_ip != NULL )
{
#if defined(POLARSSL_HAVE_IPV6)
if( client_addr.ss_family == AF_INET )
{
struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
memcpy( client_ip, &addr4->sin_addr.s_addr,
sizeof( addr4->sin_addr.s_addr ) );
}
else
{
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
memcpy( client_ip, &addr6->sin6_addr.s6_addr,
sizeof( addr6->sin6_addr.s6_addr ) );
}
#else
memcpy( client_ip, &client_addr.sin_addr.s_addr, memcpy( client_ip, &client_addr.sin_addr.s_addr,
sizeof( client_addr.sin_addr.s_addr ) ); sizeof( client_addr.sin_addr.s_addr ) );
#endif /* POLARSSL_HAVE_IPV6 */
}
return( 0 ); return( 0 );
} }

View file

@ -49,6 +49,7 @@
#include "polarssl/memory.h" #include "polarssl/memory.h"
#endif #endif
#define DFL_SERVER_ADDR NULL
#define DFL_SERVER_PORT 4433 #define DFL_SERVER_PORT 4433
#define DFL_DEBUG_LEVEL 0 #define DFL_DEBUG_LEVEL 0
#define DFL_CA_FILE "" #define DFL_CA_FILE ""
@ -91,6 +92,7 @@
*/ */
struct options struct options
{ {
const char *server_addr; /* address on which the ssl service runs */
int server_port; /* port on which the ssl service runs */ int server_port; /* port on which the ssl service runs */
int debug_level; /* level of debugging */ int debug_level; /* level of debugging */
const char *ca_file; /* the file with the CA certificate(s) */ const char *ca_file; /* the file with the CA certificate(s) */
@ -172,6 +174,7 @@ static void my_debug( void *ctx, int level, const char *str )
#define USAGE \ #define USAGE \
"\n usage: ssl_server2 param=<>...\n" \ "\n usage: ssl_server2 param=<>...\n" \
"\n acceptable parameters:\n" \ "\n acceptable parameters:\n" \
" server_addr=%%d default: (all interfaces)\n" \
" server_port=%%d default: 4433\n" \ " server_port=%%d default: 4433\n" \
" debug_level=%%d default: 0 (disabled)\n" \ " debug_level=%%d default: 0 (disabled)\n" \
USAGE_IO \ USAGE_IO \
@ -281,6 +284,7 @@ int main( int argc, char *argv[] )
goto exit; goto exit;
} }
opt.server_addr = DFL_SERVER_ADDR;
opt.server_port = DFL_SERVER_PORT; opt.server_port = DFL_SERVER_PORT;
opt.debug_level = DFL_DEBUG_LEVEL; opt.debug_level = DFL_DEBUG_LEVEL;
opt.ca_file = DFL_CA_FILE; opt.ca_file = DFL_CA_FILE;
@ -313,6 +317,8 @@ int main( int argc, char *argv[] )
if( opt.server_port < 1 || opt.server_port > 65535 ) if( opt.server_port < 1 || opt.server_port > 65535 )
goto usage; goto usage;
} }
else if( strcmp( p, "server_addr" ) == 0 )
opt.server_addr = q;
else if( strcmp( p, "debug_level" ) == 0 ) else if( strcmp( p, "debug_level" ) == 0 )
{ {
opt.debug_level = atoi( q ); opt.debug_level = atoi( q );
@ -678,7 +684,8 @@ int main( int argc, char *argv[] )
printf( " . Bind on tcp://localhost:%-4d/ ...", opt.server_port ); printf( " . Bind on tcp://localhost:%-4d/ ...", opt.server_port );
fflush( stdout ); fflush( stdout );
if( ( ret = net_bind( &listen_fd, NULL, opt.server_port ) ) != 0 ) if( ( ret = net_bind( &listen_fd, opt.server_addr,
opt.server_port ) ) != 0 )
{ {
printf( " failed\n ! net_bind returned -0x%x\n\n", -ret ); printf( " failed\n ! net_bind returned -0x%x\n\n", -ret );
goto exit; goto exit;

View file

@ -354,8 +354,8 @@ done
kill $PROCESS_ID kill $PROCESS_ID
wait $PROCESS_ID 2>/dev/null wait $PROCESS_ID 2>/dev/null
log "../programs/ssl/ssl_server2 $P_SERVER_ARGS force_version=$MODE > /dev/null" log "../programs/ssl/ssl_server2 server_addr=0.0.0.0 $P_SERVER_ARGS force_version=$MODE > /dev/null"
../programs/ssl/ssl_server2 $P_SERVER_ARGS force_version=$MODE > /dev/null & ../programs/ssl/ssl_server2 server_addr=0.0.0.0 $P_SERVER_ARGS force_version=$MODE > /dev/null &
PROCESS_ID=$! PROCESS_ID=$!
sleep 1 sleep 1
@ -390,8 +390,8 @@ done
kill $PROCESS_ID kill $PROCESS_ID
wait $PROCESS_ID 2>/dev/null wait $PROCESS_ID 2>/dev/null
log "../programs/ssl/ssl_server2 $P_SERVER_ARGS force_version=$MODE" log "../programs/ssl/ssl_server2 server_addr=0.0.0.0 $P_SERVER_ARGS force_version=$MODE"
../programs/ssl/ssl_server2 $P_SERVER_ARGS force_version=$MODE > /dev/null & ../programs/ssl/ssl_server2 server_addr=0.0.0.0 $P_SERVER_ARGS force_version=$MODE > /dev/null &
PROCESS_ID=$! PROCESS_ID=$!
sleep 1 sleep 1