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 openssl-users@openssl.org Automated List Manager majord...@openssl.org