Dear all, please find attached in in-lined an updated version of the patch for the path MTU detection.
The library stores the maximum DTLS packet size and converts to that when using the example programs which run only over IPv4 and UDP. On Linux the path MTU infrastructure is used, which is limited to UDP/IPv4 and UDP/IPv6 without any options. Automatic path MTU discovery does not work in any other case. On other platforms this infrastructure is not supported and therefore not used anymore. A general path MTU discovery needs to be implemented in the future, but this patch should fix what is right now available in OpenSSL. Thanks to Daniel Mentz for reporting this bug and doing some testing of the patch. Best regards Michael diff -u -r openssl-1.0.0-beta2-orig/apps/s_client.c openssl-1.0.0- beta2/apps/s_client.c --- openssl-1.0.0-beta2-orig/apps/s_client.c 2009-02-15 16:29:59.000000000 +0100 +++ openssl-1.0.0-beta2/apps/s_client.c 2009-05-16 22:51:04.000000000 +0200 @@ -320,7 +320,7 @@ 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 @@ 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 -u -r openssl-1.0.0-beta2-orig/apps/s_server.c openssl-1.0.0- beta2/apps/s_server.c --- openssl-1.0.0-beta2-orig/apps/s_server.c 2009-04-16 19:22:47.000000000 +0200 +++ openssl-1.0.0-beta2/apps/s_server.c 2009-05-16 22:52:16.000000000 +0200 @@ -459,7 +459,7 @@ 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 @@ 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 -u -r openssl-1.0.0-beta2-orig/crypto/bio/bss_dgram.c openssl-1.0.0-beta2/crypto/bio/bss_dgram.c --- openssl-1.0.0-beta2-orig/crypto/bio/bss_dgram.c 2009-04-14 17:13:35.000000000 +0200 +++ openssl-1.0.0-beta2/crypto/bio/bss_dgram.c 2009-05-16 23:10:11.000000000 +0200 @@ -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 */ @@ -272,6 +274,10 @@ 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; @@ -330,24 +336,87 @@ #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 -u -r openssl-1.0.0-beta2-orig/include/openssl/dtls1.h openssl-1.0.0-beta2/include/openssl/dtls1.h --- openssl-1.0.0-beta2-orig/include/openssl/dtls1.h 2009-04-19 20:03:12.000000000 +0200 +++ openssl-1.0.0-beta2/include/openssl/dtls1.h 2009-05-16 22:10:49.000000000 +0200 @@ -204,7 +204,7 @@ */ 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; diff -u -r openssl-1.0.0-beta2-orig/ssl/dtls1.h openssl-1.0.0-beta2/ ssl/dtls1.h --- openssl-1.0.0-beta2-orig/ssl/dtls1.h 2009-04-19 20:03:12.000000000 +0200 +++ openssl-1.0.0-beta2/ssl/dtls1.h 2009-05-16 22:10:49.000000000 +0200 @@ -204,7 +204,7 @@ */ 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;
mtu.patch
Description: Binary data