summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2009-05-17 16:04:21 +0000
committerDr. Stephen Henson <steve@openssl.org>2009-05-17 16:04:21 +0000
commit0454f2c4901218d749e4dac411e8b471fd749474 (patch)
treea8b22b8aaee2f372cbaab41754e10619d175237b
parent5f911774bf20e5afe4453231789691c46dcdd431 (diff)
PR: 1929
Submitted by: Michael Tuexen <tuexen@fh-muenster.de> Approved by: steve@openssl.org Updated DTLS MTU bug fix.
-rw-r--r--apps/s_client.c6
-rw-r--r--apps/s_server.c6
-rw-r--r--crypto/bio/bss_dgram.c93
-rw-r--r--ssl/dtls1.h2
4 files changed, 88 insertions, 19 deletions
diff --git a/apps/s_client.c b/apps/s_client.c
index 5f09c31297..bd2a3b8633 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -320,7 +320,7 @@ static void sc_usage(void)
BIO_printf(bio_err," -ssl3 - just use SSLv3\n");
BIO_printf(bio_err," -tls1 - just use TLSv1\n");
BIO_printf(bio_err," -dtls1 - just use DTLSv1\n");
- BIO_printf(bio_err," -mtu - set the MTU\n");
+ BIO_printf(bio_err," -mtu - set the link layer MTU\n");
BIO_printf(bio_err," -no_tls1/-no_ssl3/-no_ssl2 - turn off that protocol\n");
BIO_printf(bio_err," -bugs - Switch on all SSL implementation bug workarounds\n");
BIO_printf(bio_err," -serverpref - Use server's cipher preferences (only SSLv2)\n");
@@ -999,10 +999,10 @@ re_start:
BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout);
}
- if (socket_mtu > 0)
+ if (socket_mtu > 28)
{
SSL_set_options(con, SSL_OP_NO_QUERY_MTU);
- SSL_set_mtu(con, socket_mtu);
+ SSL_set_mtu(con, socket_mtu - 28);
}
else
/* want to do MTU discovery */
diff --git a/apps/s_server.c b/apps/s_server.c
index dffa5d3151..6bbbd7f732 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -459,7 +459,7 @@ static void sv_usage(void)
BIO_printf(bio_err," -tls1 - Just talk TLSv1\n");
BIO_printf(bio_err," -dtls1 - Just talk DTLSv1\n");
BIO_printf(bio_err," -timeout - Enable timeouts\n");
- BIO_printf(bio_err," -mtu - Set MTU\n");
+ BIO_printf(bio_err," -mtu - Set link layer MTU\n");
BIO_printf(bio_err," -chain - Read a certificate chain\n");
BIO_printf(bio_err," -no_ssl2 - Just disable SSLv2\n");
BIO_printf(bio_err," -no_ssl3 - Just disable SSLv3\n");
@@ -1823,10 +1823,10 @@ static int sv_body(char *hostname, int s, unsigned char *context)
BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout);
}
- if (socket_mtu > 0)
+ if (socket_mtu > 28)
{
SSL_set_options(con, SSL_OP_NO_QUERY_MTU);
- SSL_set_mtu(con, socket_mtu);
+ SSL_set_mtu(con, socket_mtu - 28);
}
else
/* want to do MTU discovery */
diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c
index d809a35857..3f568da142 100644
--- a/crypto/bio/bss_dgram.c
+++ b/crypto/bio/bss_dgram.c
@@ -70,7 +70,9 @@
#include <sys/timeb.h>
#endif
+#ifdef OPENSSL_SYS_LINUX
#define IP_MTU 14 /* linux is lame */
+#endif
#ifdef WATT32
#define sock_write SockWrite /* Watt-32 uses same names */
@@ -336,6 +338,10 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
bio_dgram_data *data = NULL;
long sockopt_val = 0;
unsigned int sockopt_len = 0;
+#ifdef OPENSSL_SYS_LINUX
+ socklen_t addr_len;
+ struct sockaddr_storage addr;
+#endif
data = (bio_dgram_data *)b->ptr;
@@ -394,24 +400,87 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
#endif
break;
/* (Linux)kernel sets DF bit on outgoing IP packets */
-#ifdef IP_MTU_DISCOVER
case BIO_CTRL_DGRAM_MTU_DISCOVER:
- sockopt_val = IP_PMTUDISC_DO;
- if ((ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER,
- &sockopt_val, sizeof(sockopt_val))) < 0)
- perror("setsockopt");
+#ifdef OPENSSL_SYS_LINUX
+ addr_len = (socklen_t)sizeof(struct sockaddr_storage);
+ memset((void *)&addr, 0, sizeof(struct sockaddr_storage));
+ if (getsockname(b->num, (void *)&addr, &addr_len) < 0)
+ {
+ ret = 0;
+ break;
+ }
+ sockopt_len = sizeof(sockopt_val);
+ switch (addr.ss_family)
+ {
+ case AF_INET:
+ sockopt_val = IP_PMTUDISC_DO;
+ if ((ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER,
+ &sockopt_val, sizeof(sockopt_val))) < 0)
+ perror("setsockopt");
+ break;
+ case AF_INET6:
+ sockopt_val = IPV6_PMTUDISC_DO;
+ if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
+ &sockopt_val, sizeof(sockopt_val))) < 0)
+ perror("setsockopt");
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+ ret = -1;
+#else
break;
#endif
case BIO_CTRL_DGRAM_QUERY_MTU:
- sockopt_len = sizeof(sockopt_val);
- if ((ret = getsockopt(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val,
- &sockopt_len)) < 0 || sockopt_val < 0)
- { ret = 0; }
- else
+#ifdef OPENSSL_SYS_LINUX
+ addr_len = (socklen_t)sizeof(struct sockaddr_storage);
+ memset((void *)&addr, 0, sizeof(struct sockaddr_storage));
+ if (getsockname(b->num, (void *)&addr, &addr_len) < 0)
{
- data->mtu = sockopt_val;
- ret = data->mtu;
+ ret = 0;
+ break;
}
+ sockopt_len = sizeof(sockopt_val);
+ switch (addr.ss_family)
+ {
+ case AF_INET:
+ if ((ret = getsockopt(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val,
+ &sockopt_len)) < 0 || sockopt_val < 0)
+ {
+ ret = 0;
+ }
+ else
+ {
+ /* we assume that the transport protocol is UDP and no
+ * IP options are used.
+ */
+ data->mtu = sockopt_val - 8 - 20;
+ ret = data->mtu;
+ }
+ break;
+ case AF_INET6:
+ if ((ret = getsockopt(b->num, IPPROTO_IPV6, IPV6_MTU, (void *)&sockopt_val,
+ &sockopt_len)) < 0 || sockopt_val < 0)
+ {
+ ret = 0;
+ }
+ else
+ {
+ /* we assume that the transport protocol is UDP and no
+ * IPV6 options are used.
+ */
+ data->mtu = sockopt_val - 8 - 40;
+ ret = data->mtu;
+ }
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+#else
+ ret = 0;
+#endif
break;
case BIO_CTRL_DGRAM_GET_MTU:
return data->mtu;
diff --git a/ssl/dtls1.h b/ssl/dtls1.h
index 177e55cd9f..884bbd34f1 100644
--- a/ssl/dtls1.h
+++ b/ssl/dtls1.h
@@ -204,7 +204,7 @@ typedef struct dtls1_state_st
*/
record_pqueue buffered_app_data;
- unsigned int mtu; /* max wire packet size */
+ unsigned int mtu; /* max DTLS packet size */
struct hm_header_st w_msg_hdr;
struct hm_header_st r_msg_hdr;