summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2014-12-01 23:58:05 +0000
committerMatt Caswell <matt@openssl.org>2014-12-03 09:35:23 +0000
commit4c21e004a3738b70c7d21d6e86ca68b21577d4d0 (patch)
treef551a37e525d2ad59dde8f6789d983e0e748cab4
parent59ee70e386a7625018f29da56d889637022d4649 (diff)
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> (cherry picked from commit 59669b6abf620d1ed2ef4d1e2df25c998b89b64d) Conflicts: ssl/d1_both.c ssl/ssl_lib.c
-rw-r--r--ssl/d1_both.c54
-rw-r--r--ssl/d1_lib.c25
-rw-r--r--ssl/dtls1.h4
-rw-r--r--ssl/ssl.h6
-rw-r--r--ssl/ssl_lib.c13
-rw-r--r--ssl/ssl_locl.h3
6 files changed, 74 insertions, 31 deletions
diff --git a/ssl/d1_both.c b/ssl/d1_both.c
index 93adccef2e..832b0327c9 100644
--- a/ssl/d1_both.c
+++ b/ssl/d1_both.c
@@ -156,9 +156,9 @@ static unsigned char bitmask_start_values[] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe
static unsigned char bitmask_end_values[] = {0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f};
/* XDTLS: figure out the right values */
-static unsigned int g_probable_mtu[] = {1500 - 28, 512 - 28, 256 - 28};
+static const unsigned int g_probable_mtu[] = {1500, 512, 256};
-static unsigned int dtls1_guess_mtu(unsigned int curr_mtu);
+static void dtls1_guess_mtu(SSL *s);
static void dtls1_fix_message_header(SSL *s, unsigned long frag_off,
unsigned long frag_len);
static unsigned char *dtls1_write_message_header(SSL *s,
@@ -226,18 +226,24 @@ void dtls1_hm_fragment_free(hm_fragment *frag)
static void dtls1_query_mtu(SSL *s)
{
+ if(s->d1->link_mtu)
+ {
+ s->d1->mtu = s->d1->link_mtu-BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
+ s->d1->link_mtu = 0;
+ }
+
/* AHA! Figure out the MTU, and stick to the right size */
- if (s->d1->mtu < dtls1_min_mtu() && !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU))
+ if (s->d1->mtu < dtls1_min_mtu(s) && !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU))
{
s->d1->mtu =
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
/* I've seen the kernel return bogus numbers when it doesn't know
* (initial write), so just make sure we have a reasonable number */
- if (s->d1->mtu < dtls1_min_mtu())
+ if (s->d1->mtu < dtls1_min_mtu(s))
{
s->d1->mtu = 0;
- s->d1->mtu = dtls1_guess_mtu(s->d1->mtu);
+ dtls1_guess_mtu(s);
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU,
s->d1->mtu, NULL);
}
@@ -275,7 +281,7 @@ int dtls1_do_write(SSL *s, int type)
}
#endif
- OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu()); /* should have something reasonable now */
+ OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu(s)); /* should have something reasonable now */
if ( s->init_off == 0 && type == SSL3_RT_HANDSHAKE)
OPENSSL_assert(s->init_num ==
@@ -1428,26 +1434,40 @@ dtls1_write_message_header(SSL *s, unsigned char *p)
return p;
}
-unsigned int
-dtls1_min_mtu(void)
+unsigned int
+dtls1_link_min_mtu(void)
{
return (g_probable_mtu[(sizeof(g_probable_mtu) /
sizeof(g_probable_mtu[0])) - 1]);
}
-static unsigned int
-dtls1_guess_mtu(unsigned int curr_mtu)
+unsigned int
+dtls1_min_mtu(SSL *s)
{
- unsigned int i;
+ return dtls1_link_min_mtu()-BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
+ }
- if ( curr_mtu == 0 )
- return g_probable_mtu[0] ;
+static void
+dtls1_guess_mtu(SSL *s)
+ {
+ unsigned int curr_mtu;
+ unsigned int i;
+ unsigned int mtu_ovr;
- for ( i = 0; i < sizeof(g_probable_mtu)/sizeof(g_probable_mtu[0]); i++)
- if ( curr_mtu > g_probable_mtu[i])
- return g_probable_mtu[i];
+ curr_mtu = s->d1->mtu;
+ mtu_ovr = BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
- return curr_mtu;
+ if ( curr_mtu == 0 )
+ {
+ curr_mtu = g_probable_mtu[0] - mtu_ovr;
+ }
+ else
+ {
+ for ( i = 0; i < sizeof(g_probable_mtu)/sizeof(g_probable_mtu[0]); i++)
+ if ( curr_mtu > g_probable_mtu[i] - mtu_ovr)
+ return g_probable_mtu[i] - mtu_ovr;
+ }
+ s->d1->mtu = curr_mtu;
}
void
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index 1e1c32ae8d..c66797d4fe 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -113,6 +113,9 @@ int dtls1_new(SSL *s)
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)
{
@@ -208,6 +211,7 @@ void dtls1_clear(SSL *s)
pqueue sent_messages;
pqueue buffered_app_data;
unsigned int mtu;
+ unsigned int link_mtu;
if (s->d1)
{
@@ -217,6 +221,7 @@ void dtls1_clear(SSL *s)
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);
@@ -230,6 +235,7 @@ void dtls1_clear(SSL *s)
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;
@@ -275,6 +281,25 @@ long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
* fail closed if the version is not as expected. */
return s->version == DTLS_MAX_VERSION;
+ /* 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;
diff --git a/ssl/dtls1.h b/ssl/dtls1.h
index 3deffbf1af..338575268f 100644
--- a/ssl/dtls1.h
+++ b/ssl/dtls1.h
@@ -117,6 +117,9 @@ extern "C" {
#define DTLS1_SCTP_AUTH_LABEL "EXPORTER_DTLS_OVER_SCTP"
#endif
+/* Max MTU overhead we know about so far is 40 for IPv6 + 8 for UDP */
+#define DTLS1_MAX_MTU_OVERHEAD 48
+
typedef struct dtls1_bitmap_st
{
unsigned long map; /* track 32 packets on 32-bit systems
@@ -231,6 +234,7 @@ typedef struct dtls1_state_st
/* Is set when listening for new connections with dtls1_listen() */
unsigned int listen;
+ unsigned int link_mtu; /* max on-the-wire DTLS packet size */
unsigned int mtu; /* max DTLS packet size */
struct hm_header_st w_msg_hdr;
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 60583d5ceb..a6a1c771fe 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -693,6 +693,10 @@ struct ssl_session_st
SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL)
#define SSL_set_mtu(ssl, mtu) \
SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL)
+#define DTLS_set_link_mtu(ssl, mtu) \
+ SSL_ctrl((ssl),DTLS_CTRL_SET_LINK_MTU,(mtu),NULL)
+#define DTLS_get_link_min_mtu(ssl) \
+ SSL_ctrl((ssl),DTLS_CTRL_GET_LINK_MIN_MTU,0,NULL)
#define SSL_get_secure_renegotiation_support(ssl) \
SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL)
@@ -1632,6 +1636,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
#define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS 83
#define SSL_CTRL_CHECK_PROTO_VERSION 119
+#define DTLS_CTRL_SET_LINK_MTU 120
+#define DTLS_CTRL_GET_LINK_MIN_MTU 121
#define DTLSv1_get_timeout(ssl, arg) \
SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 6e35534b81..f5c8ca9fec 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1080,19 +1080,6 @@ long SSL_ctrl(SSL *s,int cmd,long larg,void *parg)
l=s->max_cert_list;
s->max_cert_list=larg;
return(l);
- case SSL_CTRL_SET_MTU:
-#ifndef OPENSSL_NO_DTLS1
- if (larg < (long)dtls1_min_mtu())
- return 0;
-#endif
-
- if (SSL_version(s) == DTLS1_VERSION ||
- SSL_version(s) == DTLS1_BAD_VER)
- {
- s->d1->mtu = larg;
- return larg;
- }
- return 0;
case SSL_CTRL_SET_MAX_SEND_FRAGMENT:
if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH)
return 0;
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index b22bb60494..1b8fa8c4cb 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -997,7 +997,8 @@ void dtls1_stop_timer(SSL *s);
int dtls1_is_timer_expired(SSL *s);
void dtls1_double_timeout(SSL *s);
int dtls1_send_newsession_ticket(SSL *s);
-unsigned int dtls1_min_mtu(void);
+unsigned int dtls1_min_mtu(SSL *s);
+unsigned int dtls1_link_min_mtu(void);
void dtls1_hm_fragment_free(hm_fragment *frag);
/* some client-only functions */