Thanks David and Michael for your answers.
I should have pointed out in my original e-mail that I assume that the
DF (Don't Fragment) bit is set at all times. Sure, you could use IP
fragmentation and that works fine under some circumstances. But I don't
want to rely on that due to the reasons outlined in Nagendra Modadugu's
Paper. See also "Fragmentation Considered Harmful" by Kent and Mogul.
OpenSSL's implementation of DTLS always tries to guess the correct PMTU.
If you want to use IP fragmentation you must set this PMTU estimate to a
fake value that is pretty big. By doing so you can trick OpenSSL into
sending UDP messages that are large enough to trigger IP fragmentation.
To avoid IP fragmentation DTLS has its very own fragmentation mechanism
on and only on the handshake layer. DTLS does not provide fragmentation
for user messages. So what happens if the application tries to send a
user message that is bigger than OpenSSL's PMTU estimate would allow?
OpenSSL cuts it into pieces which is a bug in my opinion.
We should remove the code from OpenSSL that slices user messages.
I agree with Michael that the DTLS implementation should fail send calls
if the user message does not fit into one DTLS record. If it fits it
should just go ahead and call send(). Just in case the resulting UDP
datagram is too big the send() call will fail and the error propagates
back to the caller. If IP fragmentation kicks in and the datagram gets
lost or dropped on its way because some firewall dislikes IP fragments
then that's fine as well because that's the same as plain UDP.
-Daniel
Michael Tüxen wrote:
Hi Daniel,
the UDP behaviour is a follows: If a user sends a UDP message which is
larger than the PMTU, but does fit into the send buffer, it is accepted
by the kernel, fragmented by the IP layer and transmitted. If the
size is larger than the send buffer, the send call fails since the
send operation for UDP is atomic.
On FreeBSD you can control the maximum UDP message size using the
net.inet.udp.maxdgram sysctl variable.
More comments in-line.
Best regards
Michael
On Aug 10, 2009, at 10:21 AM, Daniel Mentz wrote:
In my understanding DTLS should provide UDP semantics when run over
the later. That is if a user message is too large in terms of the PMTU
it should either be silently discarded or the sender should be
notified by an error message similar to "Message too big".
I think if the UDP accepts the resulting message it should be sent, if
it is too large, an
error should be returned.
In no event should the message be fragmented and delivered to the
receiving application in more than one piece. It might be acceptable
that only a prefix is delivered but other than that only the message
as a whole or no message should be delivered.
The DTLS layer must not do any fragmentation. This is a bug.
But OpenSSL is doing exactly this: dtls1_write_app_data_bytes() in
d1_pkt.c fragments user messages if the (guessed) MTU is too small to
transmit the message in one piece. The receiving application has no
way to figure out if a message received by using SSL_read() is a
complete message or only a fragment of a message. Also, it's
impossible to find out which fragment was read and if all fragments
needed for reassembly were transmitted.
In my concrete setting I'm running OpenSSL on FreeBSD and try to
transmit a user message of say 2000 bytes. With no way of figuring out
the correct PMTU on FreeBSD OpenSSL makes an educated (wrong) guess of
1472 and uses it to slice the message into chunks of appropriate size.
Since I'm using the loopback interface I can transmit datagrams bigger
than this.
The receiving application gets only junk: The first fragment can not
be processed because it was truncated. All remaining fragments can not
be used as well because they do not form a legitimate message.
My suggestion is to return an error message in that case or just to go
ahead and send the message anyway. The socket interface will
eventually return a (correct) error message if OpenSSL tries to send a
packet too big for the PMTU.
This would make debugging easier. It took me some time to figure out
why I was receiving junk on the receiving end although DTLS provides
HMAC for integrity control.
After careful consideration I even think that this is a protocol
violation because the integrity of the message is indeed corrupted
although DTLS aims to guarantee integrity.
The situation with SCTP is slightly different: It sets the MTU to an
artificial value of 16384 because SCTP provides fragmentation and
reassembly on the transport layer. But if you send messages bigger
than that then your messages get fragmented again.
The DTLS/SCTP implementation must fail send calls when user messages do not
fit into a DTLS record.
Please let me know your opinions.
Do you agree?
-Daniel
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List [email protected]
Automated List Manager [email protected]
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List [email protected]
Automated List Manager [email protected]
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List [email protected]
Automated List Manager [email protected]