Remove instances in libssl of the constant 28 (for size of IPv4 header + UDP)
and instead use the value provided by the underlying BIO. Also provide some
new DTLS_CTRLs so that the library user can set the mtu without needing to
know this constant. These new DTLS_CTRLs provide the capability to set the
link level mtu to be used (i.e. including this IP/UDP overhead). The previous
DTLS_CTRLs required the library user to subtract this overhead first.

Reviewed-by: Tim Hudson <tjh@openssl.org>
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index 09268b8..5b3de08 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -139,6 +139,9 @@
 		d1->cookie_len = sizeof(s->d1->cookie);
 		}
 
+	d1->link_mtu = 0;
+	d1->mtu = 0;
+
 	if( ! d1->unprocessed_rcds.q || ! d1->processed_rcds.q 
         || ! d1->buffered_messages || ! d1->sent_messages || ! d1->buffered_app_data.q)
 		{
@@ -234,6 +237,7 @@
 	pqueue sent_messages;
 	pqueue buffered_app_data;
 	unsigned int mtu;
+	unsigned int link_mtu;
 
 	if (s->d1)
 		{
@@ -243,6 +247,7 @@
 		sent_messages = s->d1->sent_messages;
 		buffered_app_data = s->d1->buffered_app_data.q;
 		mtu = s->d1->mtu;
+		link_mtu = s->d1->link_mtu;
 
 		dtls1_clear_queues(s);
 
@@ -256,6 +261,7 @@
 		if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)
 			{
 			s->d1->mtu = mtu;
+			s->d1->link_mtu = link_mtu;
 			}
 
 		s->d1->unprocessed_rcds.q = unprocessed_rcds;
@@ -312,6 +318,25 @@
 			}
 		return 0; /* Unexpected state; fail closed. */
 
+		/* Just one protocol version is supported so far;
+		 * fail closed if the version is not as expected. */
+		return s->version == DTLS_MAX_VERSION;
+	case DTLS_CTRL_SET_LINK_MTU:
+		if (larg < (long)dtls1_link_min_mtu())
+			return 0;
+		s->d1->link_mtu = larg;
+		return 1;
+	case DTLS_CTRL_GET_LINK_MIN_MTU:
+		return (long)dtls1_link_min_mtu();
+	case SSL_CTRL_SET_MTU:
+		/*
+		 *  We may not have a BIO set yet so can't call dtls1_min_mtu()
+		 *  We'll have to make do with dtls1_link_min_mtu() and max overhead
+		 */
+		if (larg < (long)dtls1_link_min_mtu() - DTLS1_MAX_MTU_OVERHEAD)
+			return 0;
+		s->d1->mtu = larg;
+		return larg;
 	default:
 		ret = ssl3_ctrl(s, cmd, larg, parg);
 		break;