Hello!
I was playing around with DTLSv1 (openssl 1.0.1e) and tried to get DTLS
working with a nonblocking socket and multiple destinations.
The outline of my application is as follows:
On every socket event I peek the socket address and lookup the correct SSL
struct. If none is found I try to DTLSv1_listen on accept_dtls:
BIO_dgram_set_peer(udp_bio, sa);
ret = DTLSv1_listen(accept_dtls, sa);
if (ret <= 0) {
ERRssl_x(accept_dtls, ret, "DTLSv1_listen");
BIO_dgram_set_peer(udp_bio, &empty);
return;
}
BIO_dgram_set_peer(udp_bio, &empty);
If DTLSv1_listen succeeds I'll use 'accept_dtls' as the new SSL struct for
this source and generate a new 'accept_dtls':
accept_dtls = SSL_new(dtls_ctx);
if (accept_dtls == NULL)
ERR("SSL_new");
SSL_set_bio(accept_dtls, udp_bio, udp_bio);
SSL_set_options(accept_dtls, SSL_OP_COOKIE_EXCHANGE);
SSL_set_accept_state(accept_dtls);
If I found the address, I'll do (SSL_write code is analogue):
BIO_dgram_set_peer(udp_bio, sa);
ret = SSL_read(ssl, buffer, sizeof(buffer)-1);
if (ret <= 0)
ERRssl_x(ssl, ret, "SSL_read");
BIO_dgram_set_peer(udp_bio, &empty);
In case of timeout I'll do:
BIO_dgram_set_peer(udp_bio, sa);
DTLSv1_handle_timeout(ssl);
BIO_dgram_set_peer(udp_bio, &empty);
This bascially works, I guess it will screw up MTU managment (I wanted
to take care of it the same way with BIO_dgram_set_peer). Also the
BIO_dgram_set_peer calls seems superfluous, as they get reset by the
BIO layer (I'll get activated on reads, so I hope the ssl layer first
tries a readmsg in all cases on the BIO before sending replies).
With this setup I experienced a one second connection latency because
the first packet got slurped by DTLSv1_listen and only after the client
does its retry, the connection returns first data.
I'll looked into this further and saw that at least two readmsgs()
are tried on SSL_read or DTLSv1_listen. This could swap in new address
information and make this setup non-working.
When trying toreduce the read_ahead down further to 0
SSL_CTX_set_read_ahead(dtls_ctx, 0);
I got the following crash:
Program received signal SIGSEGV, Segmentation fault.
dtls1_get_record (s=s@entry=0x6265c0) at d1_pkt.c:679
679 if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE &&
(gdb) frame
#0 dtls1_get_record (s=s@entry=0x6265c0) at d1_pkt.c:679
679 if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE &&
(gdb) list
674 * Don't check if we're listening and this message is
675 * a ClientHello. They can look as if they're replayed,
676 * since they arrive from different connections and
677 * would be dropped unnecessarily.
678 */
679 if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE &&
680 *p == SSL3_MT_CLIENT_HELLO) &&
681 !dtls1_record_replay_check(s, bitmap))
682 {
683 rr->length = 0;
(gdb) print p
$1 = (unsigned char *) 0x0
Currently I wonder if such a setup is supported by openssl at all and
if I should switch to sockets per-client before trying to spend time on
the openssl codebase and trying to fix a non-relevant problem (the code
somehow indicates so).
Looking forward to comments or suggestions!
Thanks a lot,
Hannes
______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List [email protected]
Automated List Manager [email protected]