Reorganize local header files
[oweals/openssl.git] / crypto / bio / bss_dgram.c
index d43e8dc471183b983684c767c01bfe2f47c848b1..ff961450ddfa3671c4e3b85c0aa47fc629102431 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
  * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
 #include <stdio.h>
 #include <errno.h>
 
-#include "bio_lcl.h"
+#include "bio_local.h"
 #ifndef OPENSSL_NO_DGRAM
 
-# if !defined(_WIN32)
-#  include <sys/time.h>
-# endif
-
 # ifndef OPENSSL_NO_SCTP
 #  include <netinet/sctp.h>
 #  include <fcntl.h>
@@ -57,6 +53,8 @@ static int dgram_sctp_puts(BIO *h, const char *str);
 static long dgram_sctp_ctrl(BIO *h, int cmd, long arg1, void *arg2);
 static int dgram_sctp_new(BIO *h);
 static int dgram_sctp_free(BIO *data);
+static int dgram_sctp_wait_for_dry(BIO *b);
+static int dgram_sctp_msg_waiting(BIO *b);
 #  ifdef SCTP_AUTHENTICATION_EVENT
 static void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification
                                                   *snp);
@@ -77,11 +75,11 @@ static const BIO_METHOD methods_dgramp = {
     bread_conv,
     dgram_read,
     dgram_puts,
-    NULL,                       /* dgram_gets, */
+    NULL,                       /* dgram_gets,         */
     dgram_ctrl,
     dgram_new,
     dgram_free,
-    NULL,
+    NULL,                       /* dgram_callback_ctrl */
 };
 
 # ifndef OPENSSL_NO_SCTP
@@ -95,11 +93,11 @@ static const BIO_METHOD methods_dgramp_sctp = {
     bread_conv,
     dgram_sctp_read,
     dgram_sctp_puts,
-    NULL,                       /* dgram_gets, */
+    NULL,                       /* dgram_gets,         */
     dgram_sctp_ctrl,
     dgram_sctp_new,
     dgram_sctp_free,
-    NULL,
+    NULL,                       /* dgram_callback_ctrl */
 };
 # endif
 
@@ -128,20 +126,19 @@ typedef struct bio_dgram_sctp_data_st {
     struct bio_dgram_sctp_sndinfo sndinfo;
     struct bio_dgram_sctp_rcvinfo rcvinfo;
     struct bio_dgram_sctp_prinfo prinfo;
-    void (*handle_notifications) (BIO *bio, void *context, void *buf);
+    BIO_dgram_sctp_notification_handler_fn handle_notifications;
     void *notification_context;
     int in_handshake;
     int ccs_rcvd;
     int ccs_sent;
     int save_shutdown;
     int peer_auth_tested;
-    bio_dgram_sctp_save_message saved_message;
 } bio_dgram_sctp_data;
 # endif
 
 const BIO_METHOD *BIO_s_datagram(void)
 {
-    return (&methods_dgramp);
+    return &methods_dgramp;
 }
 
 BIO *BIO_new_dgram(int fd, int close_flag)
@@ -150,9 +147,9 @@ BIO *BIO_new_dgram(int fd, int close_flag)
 
     ret = BIO_new(BIO_s_datagram());
     if (ret == NULL)
-        return (NULL);
+        return NULL;
     BIO_set_fd(ret, fd, close_flag);
-    return (ret);
+    return ret;
 }
 
 static int dgram_new(BIO *bi)
@@ -162,7 +159,7 @@ static int dgram_new(BIO *bi)
     if (data == NULL)
         return 0;
     bi->ptr = data;
-    return (1);
+    return 1;
 }
 
 static int dgram_free(BIO *a)
@@ -170,20 +167,20 @@ static int dgram_free(BIO *a)
     bio_dgram_data *data;
 
     if (a == NULL)
-        return (0);
+        return 0;
     if (!dgram_clear(a))
         return 0;
 
     data = (bio_dgram_data *)a->ptr;
     OPENSSL_free(data);
 
-    return (1);
+    return 1;
 }
 
 static int dgram_clear(BIO *a)
 {
     if (a == NULL)
-        return (0);
+        return 0;
     if (a->shutdown) {
         if (a->init) {
             BIO_closesocket(a->num);
@@ -191,7 +188,7 @@ static int dgram_clear(BIO *a)
         a->init = 0;
         a->flags = 0;
     }
-    return (1);
+    return 1;
 }
 
 static void dgram_adjust_rcv_timeout(BIO *b)
@@ -330,7 +327,7 @@ static int dgram_read(BIO *b, char *out, int outl)
 
         dgram_reset_rcv_timeout(b);
     }
-    return (ret);
+    return ret;
 }
 
 static int dgram_write(BIO *b, const char *in, int inl)
@@ -344,13 +341,8 @@ static int dgram_write(BIO *b, const char *in, int inl)
     else {
         int peerlen = BIO_ADDR_sockaddr_size(&data->peer);
 
-# if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK)
-        ret = sendto(b->num, (char *)in, inl, 0,
-                     BIO_ADDR_sockaddr(&data->peer), peerlen);
-# else
         ret = sendto(b->num, in, inl, 0,
                      BIO_ADDR_sockaddr(&data->peer), peerlen);
-# endif
     }
 
     BIO_clear_retry_flags(b);
@@ -360,7 +352,7 @@ static int dgram_write(BIO *b, const char *in, int inl)
             data->_errno = get_last_socket_error();
         }
     }
-    return (ret);
+    return ret;
 }
 
 static long dgram_get_mtu_overhead(bio_dgram_data *data)
@@ -374,7 +366,7 @@ static long dgram_get_mtu_overhead(bio_dgram_data *data)
          */
         ret = 28;
         break;
-# ifdef AF_INET6
+# if OPENSSL_USE_IPV6
     case AF_INET6:
         {
 #  ifdef IN6_IS_ADDR_V4MAPPED
@@ -788,6 +780,15 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
     case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD:
         ret = dgram_get_mtu_overhead(data);
         break;
+
+    /*
+     * BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE is used here for compatibility
+     * reasons. When BIO_CTRL_DGRAM_SET_PEEK_MODE was first defined its value
+     * was incorrectly clashing with BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE. The
+     * value has been updated to a non-clashing value. However to preserve
+     * binary compatibility we now respond to both the old value and the new one
+     */
+    case BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE:
     case BIO_CTRL_DGRAM_SET_PEEK_MODE:
         data->peekmode = (unsigned int)num;
         break;
@@ -795,7 +796,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
         ret = 0;
         break;
     }
-    return (ret);
+    return ret;
 }
 
 static int dgram_puts(BIO *bp, const char *str)
@@ -804,13 +805,13 @@ static int dgram_puts(BIO *bp, const char *str)
 
     n = strlen(str);
     ret = dgram_write(bp, str, n);
-    return (ret);
+    return ret;
 }
 
 # ifndef OPENSSL_NO_SCTP
 const BIO_METHOD *BIO_s_datagram_sctp(void)
 {
-    return (&methods_dgramp_sctp);
+    return &methods_dgramp_sctp;
 }
 
 BIO *BIO_new_dgram_sctp(int fd, int close_flag)
@@ -832,7 +833,7 @@ BIO *BIO_new_dgram_sctp(int fd, int close_flag)
 
     bio = BIO_new(BIO_s_datagram_sctp());
     if (bio == NULL)
-        return (NULL);
+        return NULL;
     BIO_set_fd(bio, fd, close_flag);
 
     /* Activate SCTP-AUTH for DATA and FORWARD-TSN chunks */
@@ -842,7 +843,9 @@ BIO *BIO_new_dgram_sctp(int fd, int close_flag)
                    sizeof(struct sctp_authchunk));
     if (ret < 0) {
         BIO_vfree(bio);
-        return (NULL);
+        BIOerr(BIO_F_BIO_NEW_DGRAM_SCTP, ERR_R_SYS_LIB);
+        ERR_add_error_data(1, "Ensure SCTP AUTH chunks are enabled in kernel");
+        return NULL;
     }
     auth.sauth_chunk = OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE;
     ret =
@@ -850,26 +853,29 @@ BIO *BIO_new_dgram_sctp(int fd, int close_flag)
                    sizeof(struct sctp_authchunk));
     if (ret < 0) {
         BIO_vfree(bio);
-        return (NULL);
+        BIOerr(BIO_F_BIO_NEW_DGRAM_SCTP, ERR_R_SYS_LIB);
+        ERR_add_error_data(1, "Ensure SCTP AUTH chunks are enabled in kernel");
+        return NULL;
     }
 
     /*
      * Test if activation was successful. When using accept(), SCTP-AUTH has
      * to be activated for the listening socket already, otherwise the
-     * connected socket won't use it.
+     * connected socket won't use it. Similarly with connect(): the socket
+     * prior to connection must be activated for SCTP-AUTH
      */
     sockopt_len = (socklen_t) (sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
     authchunks = OPENSSL_zalloc(sockopt_len);
     if (authchunks == NULL) {
         BIO_vfree(bio);
-        return (NULL);
+        return NULL;
     }
     ret = getsockopt(fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks,
                    &sockopt_len);
     if (ret < 0) {
         OPENSSL_free(authchunks);
         BIO_vfree(bio);
-        return (NULL);
+        return NULL;
     }
 
     for (p = (unsigned char *)authchunks->gauth_chunks;
@@ -883,8 +889,14 @@ BIO *BIO_new_dgram_sctp(int fd, int close_flag)
 
     OPENSSL_free(authchunks);
 
-    OPENSSL_assert(auth_data);
-    OPENSSL_assert(auth_forward);
+    if (!auth_data || !auth_forward) {
+        BIO_vfree(bio);
+        BIOerr(BIO_F_BIO_NEW_DGRAM_SCTP, ERR_R_SYS_LIB);
+        ERR_add_error_data(1,
+                           "Ensure SCTP AUTH chunks are enabled on the "
+                           "underlying socket");
+        return NULL;
+    }
 
 #  ifdef SCTP_AUTHENTICATION_EVENT
 #   ifdef SCTP_EVENT
@@ -897,14 +909,14 @@ BIO *BIO_new_dgram_sctp(int fd, int close_flag)
                    sizeof(struct sctp_event));
     if (ret < 0) {
         BIO_vfree(bio);
-        return (NULL);
+        return NULL;
     }
 #   else
     sockopt_len = (socklen_t) sizeof(struct sctp_event_subscribe);
     ret = getsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, &sockopt_len);
     if (ret < 0) {
         BIO_vfree(bio);
-        return (NULL);
+        return NULL;
     }
 
     event.sctp_authentication_event = 1;
@@ -914,7 +926,7 @@ BIO *BIO_new_dgram_sctp(int fd, int close_flag)
                    sizeof(struct sctp_event_subscribe));
     if (ret < 0) {
         BIO_vfree(bio);
-        return (NULL);
+        return NULL;
     }
 #   endif
 #  endif
@@ -928,10 +940,10 @@ BIO *BIO_new_dgram_sctp(int fd, int close_flag)
                    sizeof(optval));
     if (ret < 0) {
         BIO_vfree(bio);
-        return (NULL);
+        return NULL;
     }
 
-    return (bio);
+    return bio;
 }
 
 int BIO_dgram_is_sctp(BIO *bio)
@@ -945,16 +957,17 @@ static int dgram_sctp_new(BIO *bi)
 
     bi->init = 0;
     bi->num = 0;
-    data = OPENSSL_zalloc(sizeof(*data));
-    if (data == NULL)
+    if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL) {
+        BIOerr(BIO_F_DGRAM_SCTP_NEW, ERR_R_MALLOC_FAILURE);
         return 0;
+    }
 #  ifdef SCTP_PR_SCTP_NONE
     data->prinfo.pr_policy = SCTP_PR_SCTP_NONE;
 #  endif
     bi->ptr = data;
 
     bi->flags = 0;
-    return (1);
+    return 1;
 }
 
 static int dgram_sctp_free(BIO *a)
@@ -962,17 +975,15 @@ static int dgram_sctp_free(BIO *a)
     bio_dgram_sctp_data *data;
 
     if (a == NULL)
-        return (0);
+        return 0;
     if (!dgram_clear(a))
         return 0;
 
     data = (bio_dgram_sctp_data *) a->ptr;
-    if (data != NULL) {
-        OPENSSL_free(data->saved_message.data);
+    if (data != NULL)
         OPENSSL_free(data);
-    }
 
-    return (1);
+    return 1;
 }
 
 #  ifdef SCTP_AUTHENTICATION_EVENT
@@ -1072,22 +1083,6 @@ static int dgram_sctp_read(BIO *b, char *out, int outl)
                     struct sctp_event_subscribe event;
                     socklen_t eventsize;
 #  endif
-                    /*
-                     * If a message has been delayed until the socket is dry,
-                     * it can be sent now.
-                     */
-                    if (data->saved_message.length > 0) {
-                        i = dgram_sctp_write(data->saved_message.bio,
-                                         data->saved_message.data,
-                                         data->saved_message.length);
-                        if (i < 0) {
-                            ret = i;
-                            break;
-                        }
-                        OPENSSL_free(data->saved_message.data);
-                        data->saved_message.data = NULL;
-                        data->saved_message.length = 0;
-                    }
 
                     /* disable sender dry event */
 #  ifdef SCTP_EVENT
@@ -1225,7 +1220,7 @@ static int dgram_sctp_read(BIO *b, char *out, int outl)
             data->peer_auth_tested = 1;
         }
     }
-    return (ret);
+    return ret;
 }
 
 /*
@@ -1270,27 +1265,15 @@ static int dgram_sctp_write(BIO *b, const char *in, int inl)
         sinfo = &handshake_sinfo;
     }
 
-    /*
-     * If we have to send a shutdown alert message and the socket is not dry
-     * yet, we have to save it and send it as soon as the socket gets dry.
-     */
+    /* We can only send a shutdown alert if the socket is dry */
     if (data->save_shutdown) {
         ret = BIO_dgram_sctp_wait_for_dry(b);
-        if (ret < 0) {
+        if (ret < 0)
             return -1;
-        }
         if (ret == 0) {
-            char *tmp;
-            data->saved_message.bio = b;
-            if ((tmp = OPENSSL_malloc(inl)) == NULL) {
-                BIOerr(BIO_F_DGRAM_SCTP_WRITE, ERR_R_MALLOC_FAILURE);
-                return -1;
-            }
-            OPENSSL_free(data->saved_message.data);
-            data->saved_message.data = tmp;
-            memcpy(data->saved_message.data, in, inl);
-            data->saved_message.length = inl;
-            return inl;
+            BIO_clear_retry_flags(b);
+            BIO_set_retry_write(b);
+            return -1;
         }
     }
 
@@ -1353,7 +1336,7 @@ static int dgram_sctp_write(BIO *b, const char *in, int inl)
             data->_errno = get_last_socket_error();
         }
     }
-    return (ret);
+    return ret;
 }
 
 static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
@@ -1478,6 +1461,7 @@ static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
          * we need to deactivate an old key
          */
         data->ccs_sent = 1;
+        /* fall-through */
 
     case BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD:
         /* Returns 0 on success, -1 otherwise. */
@@ -1580,6 +1564,10 @@ static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
         else
             data->save_shutdown = 0;
         break;
+    case BIO_CTRL_DGRAM_SCTP_WAIT_FOR_DRY:
+        return dgram_sctp_wait_for_dry(b);
+    case BIO_CTRL_DGRAM_SCTP_MSG_WAITING:
+        return dgram_sctp_msg_waiting(b);
 
     default:
         /*
@@ -1588,15 +1576,12 @@ static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
         ret = dgram_ctrl(b, cmd, num, ptr);
         break;
     }
-    return (ret);
+    return ret;
 }
 
 int BIO_dgram_sctp_notification_cb(BIO *b,
-                                   void (*handle_notifications) (BIO *bio,
-                                                                 void
-                                                                 *context,
-                                                                 void *buf),
-                                   void *context)
+                BIO_dgram_sctp_notification_handler_fn handle_notifications,
+                void *context)
 {
     bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;
 
@@ -1623,6 +1608,11 @@ int BIO_dgram_sctp_notification_cb(BIO *b,
  *  1 when dry
  */
 int BIO_dgram_sctp_wait_for_dry(BIO *b)
+{
+    return (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SCTP_WAIT_FOR_DRY, 0, NULL);
+}
+
+static int dgram_sctp_wait_for_dry(BIO *b)
 {
     int is_dry = 0;
     int sockflags = 0;
@@ -1781,6 +1771,11 @@ int BIO_dgram_sctp_wait_for_dry(BIO *b)
 }
 
 int BIO_dgram_sctp_msg_waiting(BIO *b)
+{
+    return (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SCTP_MSG_WAITING, 0, NULL);
+}
+
+static int dgram_sctp_msg_waiting(BIO *b)
 {
     int n, sockflags;
     union sctp_notification snp;
@@ -1845,7 +1840,7 @@ static int dgram_sctp_puts(BIO *bp, const char *str)
 
     n = strlen(str);
     ret = dgram_sctp_write(bp, str, n);
-    return (ret);
+    return ret;
 }
 # endif
 
@@ -1864,9 +1859,9 @@ static int BIO_dgram_should_retry(int i)
          */
 # endif
 
-        return (BIO_dgram_non_fatal_error(err));
+        return BIO_dgram_non_fatal_error(err);
     }
-    return (0);
+    return 0;
 }
 
 int BIO_dgram_non_fatal_error(int err)
@@ -1910,11 +1905,11 @@ int BIO_dgram_non_fatal_error(int err)
     case EALREADY:
 # endif
 
-        return (1);
+        return 1;
     default:
         break;
     }
-    return (0);
+    return 0;
 }
 
 static void get_current_time(struct timeval *t)