From 2e5c3163dbaba7ac84586f92fb7ea683d307de5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 13 Dec 2013 11:55:32 +0100 Subject: [PATCH 1/8] Factor our some code in net.c --- library/net.c | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/library/net.c b/library/net.c index be2785d98..c4ad42416 100644 --- a/library/net.c +++ b/library/net.c @@ -115,16 +115,12 @@ unsigned long net_htonl(unsigned long 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) && \ !defined(EFI32) - WSADATA wsaData; if( wsa_init_done == 0 ) @@ -139,6 +135,17 @@ int net_connect( int *fd, const char *host, int port ) signal( SIGPIPE, SIG_IGN ); #endif #endif +} + +/* + * Initiate a TCP connection with host:port + */ +int net_connect( int *fd, const char *host, int port ) +{ + struct sockaddr_in server_addr; + struct hostent *server_host; + + net_prepare(); if( ( server_host = gethostbyname( host ) ) == NULL ) return( POLARSSL_ERR_NET_UNKNOWN_HOST ); @@ -171,22 +178,7 @@ int net_bind( int *fd, const char *bind_ip, int port ) int n, c[4]; struct sockaddr_in server_addr; -#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ - !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 + net_prepare(); if( ( *fd = (int) socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 ) return( POLARSSL_ERR_NET_SOCKET_FAILED ); From 10934de1ca2689055a8d6d2157b0bb69d9a2d3ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 13 Dec 2013 12:54:09 +0100 Subject: [PATCH 2/8] Adapt net_connect() for IPv6 --- include/polarssl/config.h | 10 ++++++++ library/net.c | 53 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/include/polarssl/config.h b/include/polarssl/config.h index b2c8d637a..6ad4e0291 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -101,6 +101,16 @@ * Comment if your system does not support time functions */ #define POLARSSL_HAVE_TIME + +/** + * \def POLARSSL_HAVE_IPV6 + * + * System supports the basic socket interface for IPv6 (RFC 3493), + * specifically getaddrinfo(). + * + * Comment if your system does not support the IPv6 socket interface + */ +#define POLARSSL_HAVE_IPV6 /* \} name SECTION: System support */ /** diff --git a/library/net.c b/library/net.c index c4ad42416..97b193d13 100644 --- a/library/net.c +++ b/library/net.c @@ -81,6 +81,11 @@ static int wsa_init_done = 0; #include #include +#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \ + !defined(EFI32) +#define snprintf _snprintf +#endif + #if defined(POLARSSL_HAVE_TIME) #include #endif @@ -142,6 +147,53 @@ static void net_prepare( void ) */ 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; @@ -168,6 +220,7 @@ int net_connect( int *fd, const char *host, int port ) } return( 0 ); +#endif /* POLARSSL_HAVE_IPV6 */ } /* From 389ce63735bbf0926ee98f2a287494c909adcb73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 13 Dec 2013 14:00:51 +0100 Subject: [PATCH 3/8] Add IPv6 support to net_bind() --- library/net.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/library/net.c b/library/net.c index 97b193d13..d02e3f269 100644 --- a/library/net.c +++ b/library/net.c @@ -228,6 +228,64 @@ int net_connect( int *fd, const char *host, int port ) */ int net_bind( int *fd, const char *bind_ip, 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 ); + + /* 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; + } + + 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]; struct sockaddr_in server_addr; @@ -275,6 +333,7 @@ int net_bind( int *fd, const char *bind_ip, int port ) } return( 0 ); +#endif /* POLARSSL_HAVE_IPV6 */ } /* From 6e315a900932f50c85b281431a1a8a29c67216f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 13 Dec 2013 16:21:25 +0100 Subject: [PATCH 4/8] Adapt net_accept() to IPv6 --- include/polarssl/net.h | 3 ++- library/net.c | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/include/polarssl/net.h b/include/polarssl/net.h index 88302ac0a..22698b4ce 100644 --- a/include/polarssl/net.h +++ b/include/polarssl/net.h @@ -82,9 +82,10 @@ int net_bind( int *fd, const char *bind_ip, int port ); * \param bind_fd Relevant socket * \param client_fd Will contain the connected client socket * \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 - * 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. */ int net_accept( int bind_fd, int *client_fd, void *client_ip ); diff --git a/library/net.c b/library/net.c index d02e3f269..f00e8ef81 100644 --- a/library/net.c +++ b/library/net.c @@ -364,7 +364,11 @@ static int net_is_blocking( void ) */ 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; +#endif #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ defined(_SOCKLEN_T_DECLARED) @@ -385,8 +389,25 @@ int net_accept( int bind_fd, int *client_fd, void *client_ip ) } 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, sizeof( client_addr.sin_addr.s_addr ) ); +#endif /* POLARSSL_HAVE_IPV6 */ + } return( 0 ); } From 18d31f8e59aecbe2400469a8ac51bec9ab909a5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 13 Dec 2013 16:21:41 +0100 Subject: [PATCH 5/8] Make listening address configurable in ssl_server2 --- programs/ssl/ssl_server2.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 96cbb4902..7233dff45 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -49,6 +49,7 @@ #include "polarssl/memory.h" #endif +#define DFL_SERVER_ADDR NULL #define DFL_SERVER_PORT 4433 #define DFL_DEBUG_LEVEL 0 #define DFL_CA_FILE "" @@ -91,6 +92,7 @@ */ struct options { + const char *server_addr; /* address on which the ssl service runs */ int server_port; /* port on which the ssl service runs */ int debug_level; /* level of debugging */ 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 \ "\n usage: ssl_server2 param=<>...\n" \ "\n acceptable parameters:\n" \ + " server_addr=%%d default: (all interfaces)\n" \ " server_port=%%d default: 4433\n" \ " debug_level=%%d default: 0 (disabled)\n" \ USAGE_IO \ @@ -281,6 +284,7 @@ int main( int argc, char *argv[] ) goto exit; } + opt.server_addr = DFL_SERVER_ADDR; opt.server_port = DFL_SERVER_PORT; opt.debug_level = DFL_DEBUG_LEVEL; 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 ) goto usage; } + else if( strcmp( p, "server_addr" ) == 0 ) + opt.server_addr = q; else if( strcmp( p, "debug_level" ) == 0 ) { opt.debug_level = atoi( q ); @@ -678,7 +684,8 @@ int main( int argc, char *argv[] ) printf( " . Bind on tcp://localhost:%-4d/ ...", opt.server_port ); 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 ); goto exit; From 767f02cf6e2b0738796a06b56a5cd8204e7a4e59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 13 Dec 2013 16:23:39 +0100 Subject: [PATCH 6/8] Update IPv6 comments in config.h --- include/polarssl/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/polarssl/config.h b/include/polarssl/config.h index 6ad4e0291..0a6409265 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -106,7 +106,7 @@ * \def POLARSSL_HAVE_IPV6 * * System supports the basic socket interface for IPv6 (RFC 3493), - * specifically getaddrinfo(). + * specifically getaddrinfo(), freeaddrinfo() and struct sockaddr_storage. * * Comment if your system does not support the IPv6 socket interface */ From fd6b4cc1dbc7dd3fa7fabff5e165caf2db54ef20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 17 Dec 2013 13:59:01 +0100 Subject: [PATCH 7/8] Add forgotten SO_REUSEADDR option --- library/net.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/library/net.c b/library/net.c index f00e8ef81..19f699d50 100644 --- a/library/net.c +++ b/library/net.c @@ -229,7 +229,7 @@ int net_connect( int *fd, const char *host, int port ) int net_bind( int *fd, const char *bind_ip, int port ) { #if defined(POLARSSL_HAVE_IPV6) - int ret = POLARSSL_ERR_NET_UNKNOWN_HOST; + int n, ret = POLARSSL_ERR_NET_UNKNOWN_HOST; struct addrinfo hints, *addr_list, *cur; char port_str[6]; @@ -260,6 +260,10 @@ int net_bind( int *fd, const char *bind_ip, int port ) 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 ); From c9baa873ca699b23e3d4abbb343c03e26a54118c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 17 Dec 2013 14:10:58 +0100 Subject: [PATCH 8/8] Force server to IPv4 in compat.s --- tests/compat.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/compat.sh b/tests/compat.sh index 21ea4844a..136efa033 100755 --- a/tests/compat.sh +++ b/tests/compat.sh @@ -321,8 +321,8 @@ done kill $PROCESS_ID wait $PROCESS_ID 2>/dev/null -log "../programs/ssl/ssl_server2 $P_SERVER_ARGS force_version=$MODE > /dev/null" -../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 server_addr=0.0.0.0 $P_SERVER_ARGS force_version=$MODE > /dev/null & PROCESS_ID=$! sleep 1 @@ -357,8 +357,8 @@ done kill $PROCESS_ID wait $PROCESS_ID 2>/dev/null -log "../programs/ssl/ssl_server2 $P_SERVER_ARGS force_version=$MODE" -../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" +../programs/ssl/ssl_server2 server_addr=0.0.0.0 $P_SERVER_ARGS force_version=$MODE > /dev/null & PROCESS_ID=$! sleep 1