diff --git a/ChangeLog b/ChangeLog index 7c238e54a..f87f1e1ce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -174,6 +174,8 @@ API changes from the 1.4 preview branch instead, see mbedtls_ssl_set_timer_cb(), with the Timing module providing an example implementation, see mbedtls_timing_delay_context and mbedtls_timing_set/get_delay(). + * With UDP sockets, it is no longer necessary to call net_bind() again + after a successful net_accept(). Changes * mbedtls_ctr_drbg_random() and mbedtls_hmac_drbg_random() are now diff --git a/include/mbedtls/net.h b/include/mbedtls/net.h index 85c4977cf..19746e55c 100644 --- a/include/mbedtls/net.h +++ b/include/mbedtls/net.h @@ -126,10 +126,6 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char * MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small, * MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to * non-blocking and accept() would block. - * - * \note With UDP, connects the bind_fd to the client and just copy - * its descriptor to client_fd. New clients will not be able - * to connect until you close the socket and bind a new one. */ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, mbedtls_net_context *client_ctx, diff --git a/library/net.c b/library/net.c index 7e72e0864..04aa0df13 100644 --- a/library/net.c +++ b/library/net.c @@ -338,13 +338,34 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); } - /* UDP: hijack the listening socket for communicating with the client */ + /* UDP: hijack the listening socket to communicate with the client, + * then bind a new socket to accept new connections */ if( type != SOCK_STREAM ) { + struct sockaddr_storage local_addr; + int one = 1; + if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 ) return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); client_ctx->fd = bind_ctx->fd; + 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 ); + } } if( client_ip != NULL ) diff --git a/programs/ssl/dtls_server.c b/programs/ssl/dtls_server.c index a3839c656..650b687df 100644 --- a/programs/ssl/dtls_server.c +++ b/programs/ssl/dtls_server.c @@ -273,13 +273,6 @@ reset: goto exit; } - /* With UDP, bind_fd is hijacked by client_fd, so bind a new one */ - if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_UDP ) ) != 0 ) - { - printf( " failed\n ! mbedtls_net_bind returned -0x%x\n\n", -ret ); - goto exit; - } - /* For HelloVerifyRequest cookies */ if( ( ret = mbedtls_ssl_set_client_transport_id( &ssl, client_ip, cliip_len ) ) != 0 ) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 99d43c949..a08aa9b29 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -1896,28 +1896,6 @@ reset: mbedtls_printf( " ok\n" ); - /* - * With UDP, bind_fd is hijacked by client_fd, so bind a new one - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - mbedtls_printf( " . Re-bind on udp://%s:%s/ ...", - opt.server_addr ? opt.server_addr : "*", - opt.server_port ); - fflush( stdout ); - - if( ( ret = mbedtls_net_bind( &listen_fd, opt.server_addr, - opt.server_port, MBEDTLS_NET_PROTO_UDP ) ) != 0 ) - { - mbedtls_printf( " failed\n ! mbedtls_net_bind returned -0x%x\n\n", -ret ); - goto exit; - } - - mbedtls_printf( " ok\n" ); - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - /* * 4. Handshake */ diff --git a/programs/test/udp_proxy.c b/programs/test/udp_proxy.c index 7360d8a37..76e3b31f8 100644 --- a/programs/test/udp_proxy.c +++ b/programs/test/udp_proxy.c @@ -533,6 +533,8 @@ int main( int argc, char *argv[] ) * 2. Wait until a client connects */ accept: + mbedtls_net_free( &client_fd ); + mbedtls_printf( " . Waiting for a remote connection ..." ); fflush( stdout ); @@ -543,20 +545,6 @@ accept: goto exit; } - mbedtls_printf( " ok\n" ); - fflush( stdout ); - - mbedtls_printf( " . Re-bind on UDP/%s/%s ...", - opt.listen_addr, opt.listen_port ); - fflush( stdout ); - - if( ( ret = mbedtls_net_bind( &listen_fd, opt.listen_addr, opt.listen_port, - MBEDTLS_NET_PROTO_UDP ) ) != 0 ) - { - mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); - goto exit; - } - mbedtls_printf( " ok\n" ); /*