Submitted by: Michael Tuexen <tuexen@fh-muenster.de>
Approved by: steve@openssl.org

Updated DTLS MTU bug fix.
This commit is contained in:
Dr. Stephen Henson 2009-05-17 16:04:21 +00:00
parent 5f911774bf
commit 0454f2c490
4 changed files with 88 additions and 19 deletions

View file

@ -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 */

View file

@ -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 */

View file

@ -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;

View file

@ -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;