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;




Attachment: mtu.patch
Description: Binary data



Reply via email to