There are a number of instances throughout the code where the constant 28 is
authorMatt Caswell <matt@openssl.org>
Mon, 1 Dec 2014 23:49:47 +0000 (23:49 +0000)
committerMatt Caswell <matt@openssl.org>
Wed, 3 Dec 2014 09:34:04 +0000 (09:34 +0000)
used with no explanation. Some of this was introduced as part of RT#1929. The
value 28 is the length of the IP header (20 bytes) plus the UDP header (8
bytes). However use of this constant is incorrect because there may be
instances where a different value is needed, e.g. an IPv4 header is 20 bytes
but an IPv6 header is 40. Similarly you may not be using UDP (e.g. SCTP).
This commit introduces a new BIO_CTRL that provides the value to be used for
this mtu "overhead". It will be used by subsequent commits.

Reviewed-by: Tim Hudson <tjh@openssl.org>
(cherry picked from commit 0d3ae34df573f477b6b1aaf614d52dcdfcff5fce)

Conflicts:
crypto/bio/bss_dgram.c

crypto/bio/bio.h
crypto/bio/bss_dgram.c

index 05699ab21210edc4831cf7378a3fe6734edcdba8..32eba71480566b1a17c24d34f991c220547cdd3a 100644 (file)
@@ -175,6 +175,8 @@ extern "C" {
 #define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT   45 /* Next DTLS handshake timeout to
                                               * adjust socket timeouts */
 
+#define BIO_CTRL_DGRAM_GET_MTU_OVERHEAD   49
+
 #ifndef OPENSSL_NO_SCTP
 /* SCTP stuff */
 #define BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE   50
@@ -607,6 +609,8 @@ int BIO_ctrl_reset_read_request(BIO *b);
          (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_PEER, 0, (char *)peer)
 #define BIO_dgram_set_peer(b,peer) \
          (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, (char *)peer)
+#define BIO_dgram_get_mtu_overhead(b) \
+         (unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU_OVERHEAD, 0, NULL)
 
 /* These two aren't currently implemented */
 /* int BIO_get_ex_num(BIO *bio); */
index 8cad5b41dba50c0b7964662d4e83577fcbbf6c9d..7bed08e9b4b58bc16cc9bb9a9efc70a3ff2fcda7 100644 (file)
@@ -454,6 +454,36 @@ static int dgram_write(BIO *b, const char *in, int inl)
        return(ret);
        }
 
+static long dgram_get_mtu_overhead(bio_dgram_data *data)
+       {
+       long ret;
+
+       switch (data->peer.sa.sa_family)
+               {
+               case AF_INET:
+                       /* Assume this is UDP - 20 bytes for IP, 8 bytes for UDP */
+                       ret = 28;
+                       break;
+#if OPENSSL_USE_IPV6
+               case AF_INET6:
+#ifdef IN6_IS_ADDR_V4MAPPED
+                       if (IN6_IS_ADDR_V4MAPPED(&data->peer.sa_in6.sin6_addr))
+                               /* Assume this is UDP - 20 bytes for IP, 8 bytes for UDP */
+                               ret = 28;
+                       else
+#endif
+                               /* Assume this is UDP - 40 bytes for IP, 8 bytes for UDP */
+                               ret = 48;
+                       break;
+#endif
+               default:
+                       /* We don't know. Go with the historical default */
+                       ret = 28;
+                       break;
+               }
+       return ret;
+       }
+
 static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
        {
        long ret=1;
@@ -630,23 +660,24 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
 #endif
                break;
        case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
+               ret = -dgram_get_mtu_overhead(data);
                switch (data->peer.sa.sa_family)
                        {
                        case AF_INET:
-                               ret = 576 - 20 - 8;
+                               ret += 576;
                                break;
 #if OPENSSL_USE_IPV6
                        case AF_INET6:
 #ifdef IN6_IS_ADDR_V4MAPPED
                                if (IN6_IS_ADDR_V4MAPPED(&data->peer.sa_in6.sin6_addr))
-                                       ret = 576 - 20 - 8;
+                                       ret += 576;
                                else
 #endif
-                                       ret = 1280 - 40 - 8;
+                                       ret += 1280;
                                break;
 #endif
                        default:
-                               ret = 576 - 20 - 8;
+                               ret += 576;
                                break;
                        }
                break;
@@ -847,6 +878,9 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
                        ret = 0;
                break;
 #endif
+       case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD:
+               ret = dgram_get_mtu_overhead(data);
+               break;
        default:
                ret=0;
                break;
@@ -1367,6 +1401,10 @@ static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
                 * Returns always 1.
                 */
                break;
+       case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD:
+               /* We allow transport protocol fragmentation so this is irrelevant */
+               ret = 0;
+               break;
        case BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE:
                if (num > 0)
                        data->in_handshake = 1;