LCOV - code coverage report
Current view: top level - bio - bss_dgram.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 0 216 0.0 %
Date: 2014-08-02 Functions: 0 14 0.0 %
Branches: 0 168 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* crypto/bio/bio_dgram.c */
       2                 :            : /* 
       3                 :            :  * DTLS implementation written by Nagendra Modadugu
       4                 :            :  * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
       5                 :            :  */
       6                 :            : /* ====================================================================
       7                 :            :  * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
       8                 :            :  *
       9                 :            :  * Redistribution and use in source and binary forms, with or without
      10                 :            :  * modification, are permitted provided that the following conditions
      11                 :            :  * are met:
      12                 :            :  *
      13                 :            :  * 1. Redistributions of source code must retain the above copyright
      14                 :            :  *    notice, this list of conditions and the following disclaimer. 
      15                 :            :  *
      16                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      17                 :            :  *    notice, this list of conditions and the following disclaimer in
      18                 :            :  *    the documentation and/or other materials provided with the
      19                 :            :  *    distribution.
      20                 :            :  *
      21                 :            :  * 3. All advertising materials mentioning features or use of this
      22                 :            :  *    software must display the following acknowledgment:
      23                 :            :  *    "This product includes software developed by the OpenSSL Project
      24                 :            :  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
      25                 :            :  *
      26                 :            :  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
      27                 :            :  *    endorse or promote products derived from this software without
      28                 :            :  *    prior written permission. For written permission, please contact
      29                 :            :  *    openssl-core@OpenSSL.org.
      30                 :            :  *
      31                 :            :  * 5. Products derived from this software may not be called "OpenSSL"
      32                 :            :  *    nor may "OpenSSL" appear in their names without prior written
      33                 :            :  *    permission of the OpenSSL Project.
      34                 :            :  *
      35                 :            :  * 6. Redistributions of any form whatsoever must retain the following
      36                 :            :  *    acknowledgment:
      37                 :            :  *    "This product includes software developed by the OpenSSL Project
      38                 :            :  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
      39                 :            :  *
      40                 :            :  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
      41                 :            :  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      42                 :            :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      43                 :            :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
      44                 :            :  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      45                 :            :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      46                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
      47                 :            :  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      48                 :            :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
      49                 :            :  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      50                 :            :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
      51                 :            :  * OF THE POSSIBILITY OF SUCH DAMAGE.
      52                 :            :  * ====================================================================
      53                 :            :  *
      54                 :            :  * This product includes cryptographic software written by Eric Young
      55                 :            :  * (eay@cryptsoft.com).  This product includes software written by Tim
      56                 :            :  * Hudson (tjh@cryptsoft.com).
      57                 :            :  *
      58                 :            :  */
      59                 :            : 
      60                 :            : 
      61                 :            : #include <stdio.h>
      62                 :            : #include <errno.h>
      63                 :            : #define USE_SOCKETS
      64                 :            : #include "cryptlib.h"
      65                 :            : 
      66                 :            : #include <openssl/bio.h>
      67                 :            : #ifndef OPENSSL_NO_DGRAM
      68                 :            : 
      69                 :            : #if defined(OPENSSL_SYS_VMS)
      70                 :            : #include <sys/timeb.h>
      71                 :            : #endif
      72                 :            : 
      73                 :            : #ifndef OPENSSL_NO_SCTP
      74                 :            : #include <netinet/sctp.h>
      75                 :            : #include <fcntl.h>
      76                 :            : #define OPENSSL_SCTP_DATA_CHUNK_TYPE            0x00
      77                 :            : #define OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE 0xc0
      78                 :            : #endif
      79                 :            : 
      80                 :            : #if defined(OPENSSL_SYS_LINUX) && !defined(IP_MTU)
      81                 :            : #define IP_MTU      14 /* linux is lame */
      82                 :            : #endif
      83                 :            : 
      84                 :            : #if OPENSSL_USE_IPV6 && !defined(IPPROTO_IPV6)
      85                 :            : #define IPPROTO_IPV6 41 /* windows is lame */
      86                 :            : #endif
      87                 :            : 
      88                 :            : #if defined(__FreeBSD__) && defined(IN6_IS_ADDR_V4MAPPED)
      89                 :            : /* Standard definition causes type-punning problems. */
      90                 :            : #undef IN6_IS_ADDR_V4MAPPED
      91                 :            : #define s6_addr32 __u6_addr.__u6_addr32
      92                 :            : #define IN6_IS_ADDR_V4MAPPED(a)               \
      93                 :            :         (((a)->s6_addr32[0] == 0) &&          \
      94                 :            :          ((a)->s6_addr32[1] == 0) &&          \
      95                 :            :          ((a)->s6_addr32[2] == htonl(0x0000ffff)))
      96                 :            : #endif
      97                 :            : 
      98                 :            : #ifdef WATT32
      99                 :            : #define sock_write SockWrite  /* Watt-32 uses same names */
     100                 :            : #define sock_read  SockRead
     101                 :            : #define sock_puts  SockPuts
     102                 :            : #endif
     103                 :            : 
     104                 :            : static int dgram_write(BIO *h, const char *buf, int num);
     105                 :            : static int dgram_read(BIO *h, char *buf, int size);
     106                 :            : static int dgram_puts(BIO *h, const char *str);
     107                 :            : static long dgram_ctrl(BIO *h, int cmd, long arg1, void *arg2);
     108                 :            : static int dgram_new(BIO *h);
     109                 :            : static int dgram_free(BIO *data);
     110                 :            : static int dgram_clear(BIO *bio);
     111                 :            : 
     112                 :            : #ifndef OPENSSL_NO_SCTP
     113                 :            : static int dgram_sctp_write(BIO *h, const char *buf, int num);
     114                 :            : static int dgram_sctp_read(BIO *h, char *buf, int size);
     115                 :            : static int dgram_sctp_puts(BIO *h, const char *str);
     116                 :            : static long dgram_sctp_ctrl(BIO *h, int cmd, long arg1, void *arg2);
     117                 :            : static int dgram_sctp_new(BIO *h);
     118                 :            : static int dgram_sctp_free(BIO *data);
     119                 :            : #ifdef SCTP_AUTHENTICATION_EVENT
     120                 :            : static void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp);
     121                 :            : #endif
     122                 :            : #endif
     123                 :            : 
     124                 :            : static int BIO_dgram_should_retry(int s);
     125                 :            : 
     126                 :            : static void get_current_time(struct timeval *t);
     127                 :            : 
     128                 :            : static BIO_METHOD methods_dgramp=
     129                 :            :         {
     130                 :            :         BIO_TYPE_DGRAM,
     131                 :            :         "datagram socket",
     132                 :            :         dgram_write,
     133                 :            :         dgram_read,
     134                 :            :         dgram_puts,
     135                 :            :         NULL, /* dgram_gets, */
     136                 :            :         dgram_ctrl,
     137                 :            :         dgram_new,
     138                 :            :         dgram_free,
     139                 :            :         NULL,
     140                 :            :         };
     141                 :            : 
     142                 :            : #ifndef OPENSSL_NO_SCTP
     143                 :            : static BIO_METHOD methods_dgramp_sctp=
     144                 :            :         {
     145                 :            :         BIO_TYPE_DGRAM_SCTP,
     146                 :            :         "datagram sctp socket",
     147                 :            :         dgram_sctp_write,
     148                 :            :         dgram_sctp_read,
     149                 :            :         dgram_sctp_puts,
     150                 :            :         NULL, /* dgram_gets, */
     151                 :            :         dgram_sctp_ctrl,
     152                 :            :         dgram_sctp_new,
     153                 :            :         dgram_sctp_free,
     154                 :            :         NULL,
     155                 :            :         };
     156                 :            : #endif
     157                 :            : 
     158                 :            : typedef struct bio_dgram_data_st
     159                 :            :         {
     160                 :            :         union {
     161                 :            :                 struct sockaddr sa;
     162                 :            :                 struct sockaddr_in sa_in;
     163                 :            : #if OPENSSL_USE_IPV6
     164                 :            :                 struct sockaddr_in6 sa_in6;
     165                 :            : #endif
     166                 :            :         } peer;
     167                 :            :         unsigned int connected;
     168                 :            :         unsigned int _errno;
     169                 :            :         unsigned int mtu;
     170                 :            :         struct timeval next_timeout;
     171                 :            :         struct timeval socket_timeout;
     172                 :            :         } bio_dgram_data;
     173                 :            : 
     174                 :            : #ifndef OPENSSL_NO_SCTP
     175                 :            : typedef struct bio_dgram_sctp_save_message_st
     176                 :            :         {
     177                 :            :         BIO *bio;
     178                 :            :         char *data;
     179                 :            :         int length;
     180                 :            :         } bio_dgram_sctp_save_message;
     181                 :            : 
     182                 :            : typedef struct bio_dgram_sctp_data_st
     183                 :            :         {
     184                 :            :         union {
     185                 :            :                 struct sockaddr sa;
     186                 :            :                 struct sockaddr_in sa_in;
     187                 :            : #if OPENSSL_USE_IPV6
     188                 :            :                 struct sockaddr_in6 sa_in6;
     189                 :            : #endif
     190                 :            :         } peer;
     191                 :            :         unsigned int connected;
     192                 :            :         unsigned int _errno;
     193                 :            :         unsigned int mtu;
     194                 :            :         struct bio_dgram_sctp_sndinfo sndinfo;
     195                 :            :         struct bio_dgram_sctp_rcvinfo rcvinfo;
     196                 :            :         struct bio_dgram_sctp_prinfo prinfo;
     197                 :            :         void (*handle_notifications)(BIO *bio, void *context, void *buf);
     198                 :            :         void* notification_context;
     199                 :            :         int in_handshake;
     200                 :            :         int ccs_rcvd;
     201                 :            :         int ccs_sent;
     202                 :            :         int save_shutdown;
     203                 :            :         int peer_auth_tested;
     204                 :            :         bio_dgram_sctp_save_message saved_message;
     205                 :            :         } bio_dgram_sctp_data;
     206                 :            : #endif
     207                 :            : 
     208                 :          0 : BIO_METHOD *BIO_s_datagram(void)
     209                 :            :         {
     210                 :          0 :         return(&methods_dgramp);
     211                 :            :         }
     212                 :            : 
     213                 :          0 : BIO *BIO_new_dgram(int fd, int close_flag)
     214                 :            :         {
     215                 :            :         BIO *ret;
     216                 :            : 
     217                 :          0 :         ret=BIO_new(BIO_s_datagram());
     218         [ #  # ]:          0 :         if (ret == NULL) return(NULL);
     219                 :          0 :         BIO_set_fd(ret,fd,close_flag);
     220                 :          0 :         return(ret);
     221                 :            :         }
     222                 :            : 
     223                 :          0 : static int dgram_new(BIO *bi)
     224                 :            :         {
     225                 :          0 :         bio_dgram_data *data = NULL;
     226                 :            : 
     227                 :          0 :         bi->init=0;
     228                 :          0 :         bi->num=0;
     229                 :          0 :         data = OPENSSL_malloc(sizeof(bio_dgram_data));
     230         [ #  # ]:          0 :         if (data == NULL)
     231                 :            :                 return 0;
     232                 :            :         memset(data, 0x00, sizeof(bio_dgram_data));
     233                 :          0 :     bi->ptr = data;
     234                 :            : 
     235                 :          0 :         bi->flags=0;
     236                 :          0 :         return(1);
     237                 :            :         }
     238                 :            : 
     239                 :          0 : static int dgram_free(BIO *a)
     240                 :            :         {
     241                 :            :         bio_dgram_data *data;
     242                 :            : 
     243         [ #  # ]:          0 :         if (a == NULL) return(0);
     244         [ #  # ]:          0 :         if ( ! dgram_clear(a))
     245                 :            :                 return 0;
     246                 :            : 
     247                 :          0 :         data = (bio_dgram_data *)a->ptr;
     248         [ #  # ]:          0 :         if(data != NULL) OPENSSL_free(data);
     249                 :            : 
     250                 :            :         return(1);
     251                 :            :         }
     252                 :            : 
     253                 :          0 : static int dgram_clear(BIO *a)
     254                 :            :         {
     255         [ #  # ]:          0 :         if (a == NULL) return(0);
     256         [ #  # ]:          0 :         if (a->shutdown)
     257                 :            :                 {
     258         [ #  # ]:          0 :                 if (a->init)
     259                 :            :                         {
     260                 :          0 :                         SHUTDOWN2(a->num);
     261                 :            :                         }
     262                 :          0 :                 a->init=0;
     263                 :          0 :                 a->flags=0;
     264                 :            :                 }
     265                 :            :         return(1);
     266                 :            :         }
     267                 :            : 
     268                 :          0 : static void dgram_adjust_rcv_timeout(BIO *b)
     269                 :            :         {
     270                 :            : #if defined(SO_RCVTIMEO)
     271                 :          0 :         bio_dgram_data *data = (bio_dgram_data *)b->ptr;
     272                 :          0 :         union { size_t s; int i; } sz = {0};
     273                 :            : 
     274                 :            :         /* Is a timer active? */
     275 [ #  # ][ #  # ]:          0 :         if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0)
     276                 :            :                 {
     277                 :            :                 struct timeval timenow, timeleft;
     278                 :            : 
     279                 :            :                 /* Read current socket timeout */
     280                 :            : #ifdef OPENSSL_SYS_WINDOWS
     281                 :            :                 int timeout;
     282                 :            : 
     283                 :            :                 sz.i = sizeof(timeout);
     284                 :            :                 if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
     285                 :            :                                            (void*)&timeout, &sz.i) < 0)
     286                 :            :                         { perror("getsockopt"); }
     287                 :            :                 else
     288                 :            :                         {
     289                 :            :                         data->socket_timeout.tv_sec = timeout / 1000;
     290                 :            :                         data->socket_timeout.tv_usec = (timeout % 1000) * 1000;
     291                 :            :                         }
     292                 :            : #else
     293                 :          0 :                 sz.i = sizeof(data->socket_timeout);
     294         [ #  # ]:          0 :                 if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, 
     295                 :          0 :                                                 &(data->socket_timeout), (void *)&sz) < 0)
     296                 :          0 :                         { perror("getsockopt"); }
     297         [ #  # ]:          0 :                 else if (sizeof(sz.s)!=sizeof(sz.i) && sz.i==0)
     298         [ #  # ]:          0 :                         OPENSSL_assert(sz.s<=sizeof(data->socket_timeout));
     299                 :            : #endif
     300                 :            : 
     301                 :            :                 /* Get current time */
     302                 :          0 :                 get_current_time(&timenow);
     303                 :            : 
     304                 :            :                 /* Calculate time left until timer expires */
     305                 :          0 :                 memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval));
     306                 :          0 :                 timeleft.tv_sec -= timenow.tv_sec;
     307                 :          0 :                 timeleft.tv_usec -= timenow.tv_usec;
     308         [ #  # ]:          0 :                 if (timeleft.tv_usec < 0)
     309                 :            :                         {
     310                 :          0 :                         timeleft.tv_sec--;
     311                 :          0 :                         timeleft.tv_usec += 1000000;
     312                 :            :                         }
     313                 :            : 
     314         [ #  # ]:          0 :                 if (timeleft.tv_sec < 0)
     315                 :            :                         {
     316                 :          0 :                         timeleft.tv_sec = 0;
     317                 :          0 :                         timeleft.tv_usec = 1;
     318                 :            :                         }
     319                 :            : 
     320                 :            :                 /* Adjust socket timeout if next handhake message timer
     321                 :            :                  * will expire earlier.
     322                 :            :                  */
     323 [ #  # ][ #  # ]:          0 :                 if ((data->socket_timeout.tv_sec == 0 && data->socket_timeout.tv_usec == 0) ||
                 [ #  # ]
     324         [ #  # ]:          0 :                         (data->socket_timeout.tv_sec > timeleft.tv_sec) ||
     325         [ #  # ]:          0 :                         (data->socket_timeout.tv_sec == timeleft.tv_sec &&
     326                 :          0 :                          data->socket_timeout.tv_usec >= timeleft.tv_usec))
     327                 :            :                         {
     328                 :            : #ifdef OPENSSL_SYS_WINDOWS
     329                 :            :                         timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000;
     330                 :            :                         if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
     331                 :            :                                                    (void*)&timeout, sizeof(timeout)) < 0)
     332                 :            :                                 { perror("setsockopt"); }
     333                 :            : #else
     334         [ #  # ]:          0 :                         if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &timeleft,
     335                 :            :                                                         sizeof(struct timeval)) < 0)
     336                 :          0 :                                 { perror("setsockopt"); }
     337                 :            : #endif
     338                 :            :                         }
     339                 :            :                 }
     340                 :            : #endif
     341                 :          0 :         }
     342                 :            : 
     343                 :          0 : static void dgram_reset_rcv_timeout(BIO *b)
     344                 :            :         {
     345                 :            : #if defined(SO_RCVTIMEO)
     346                 :          0 :         bio_dgram_data *data = (bio_dgram_data *)b->ptr;
     347                 :            : 
     348                 :            :         /* Is a timer active? */
     349 [ #  # ][ #  # ]:          0 :         if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0)
     350                 :            :                 {
     351                 :            : #ifdef OPENSSL_SYS_WINDOWS
     352                 :            :                 int timeout = data->socket_timeout.tv_sec * 1000 +
     353                 :            :                                           data->socket_timeout.tv_usec / 1000;
     354                 :            :                 if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
     355                 :            :                                            (void*)&timeout, sizeof(timeout)) < 0)
     356                 :            :                         { perror("setsockopt"); }
     357                 :            : #else
     358         [ #  # ]:          0 :                 if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &(data->socket_timeout),
     359                 :            :                                                 sizeof(struct timeval)) < 0)
     360                 :          0 :                         { perror("setsockopt"); }
     361                 :            : #endif
     362                 :            :                 }
     363                 :            : #endif
     364                 :          0 :         }
     365                 :            : 
     366                 :          0 : static int dgram_read(BIO *b, char *out, int outl)
     367                 :            :         {
     368                 :          0 :         int ret=0;
     369                 :          0 :         bio_dgram_data *data = (bio_dgram_data *)b->ptr;
     370                 :            : 
     371                 :            :         struct  {
     372                 :            :         /*
     373                 :            :          * See commentary in b_sock.c. <appro>
     374                 :            :          */
     375                 :            :         union   { size_t s; int i; } len;
     376                 :            :         union   {
     377                 :            :                 struct sockaddr sa;
     378                 :            :                 struct sockaddr_in sa_in;
     379                 :            : #if OPENSSL_USE_IPV6
     380                 :            :                 struct sockaddr_in6 sa_in6;
     381                 :            : #endif
     382                 :            :                 } peer;
     383                 :            :         } sa;
     384                 :            : 
     385                 :          0 :         sa.len.s=0;
     386                 :          0 :         sa.len.i=sizeof(sa.peer);
     387                 :            : 
     388         [ #  # ]:          0 :         if (out != NULL)
     389                 :            :                 {
     390                 :          0 :                 clear_socket_error();
     391                 :            :                 memset(&sa.peer, 0x00, sizeof(sa.peer));
     392                 :          0 :                 dgram_adjust_rcv_timeout(b);
     393                 :          0 :                 ret=recvfrom(b->num,out,outl,0,&sa.peer.sa,(void *)&sa.len);
     394         [ #  # ]:          0 :                 if (sizeof(sa.len.i)!=sizeof(sa.len.s) && sa.len.i==0)
     395                 :            :                         {
     396         [ #  # ]:          0 :                         OPENSSL_assert(sa.len.s<=sizeof(sa.peer));
     397                 :          0 :                         sa.len.i = (int)sa.len.s;
     398                 :            :                         }
     399                 :            : 
     400 [ #  # ][ #  # ]:          0 :                 if ( ! data->connected  && ret >= 0)
     401                 :          0 :                         BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &sa.peer);
     402                 :            : 
     403                 :          0 :                 BIO_clear_retry_flags(b);
     404         [ #  # ]:          0 :                 if (ret < 0)
     405                 :            :                         {
     406         [ #  # ]:          0 :                         if (BIO_dgram_should_retry(ret))
     407                 :            :                                 {
     408                 :          0 :                                 BIO_set_retry_read(b);
     409                 :          0 :                                 data->_errno = get_last_socket_error();
     410                 :            :                                 }
     411                 :            :                         }
     412                 :            : 
     413                 :          0 :                 dgram_reset_rcv_timeout(b);
     414                 :            :                 }
     415                 :          0 :         return(ret);
     416                 :            :         }
     417                 :            : 
     418                 :          0 : static int dgram_write(BIO *b, const char *in, int inl)
     419                 :            :         {
     420                 :            :         int ret;
     421                 :          0 :         bio_dgram_data *data = (bio_dgram_data *)b->ptr;
     422                 :          0 :         clear_socket_error();
     423                 :            : 
     424         [ #  # ]:          0 :         if ( data->connected )
     425                 :          0 :                 ret=writesocket(b->num,in,inl);
     426                 :            :         else
     427                 :            :                 {
     428                 :          0 :                 int peerlen = sizeof(data->peer);
     429                 :            : 
     430         [ #  # ]:          0 :                 if (data->peer.sa.sa_family == AF_INET)
     431                 :            :                         peerlen = sizeof(data->peer.sa_in);
     432                 :            : #if OPENSSL_USE_IPV6
     433                 :            :                 else if (data->peer.sa.sa_family == AF_INET6)
     434                 :            :                         peerlen = sizeof(data->peer.sa_in6);
     435                 :            : #endif
     436                 :            : #if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK)
     437                 :            :                 ret=sendto(b->num, (char *)in, inl, 0, &data->peer.sa, peerlen);
     438                 :            : #else
     439                 :          0 :                 ret=sendto(b->num, in, inl, 0, &data->peer.sa, peerlen);
     440                 :            : #endif
     441                 :            :                 }
     442                 :            : 
     443                 :          0 :         BIO_clear_retry_flags(b);
     444         [ #  # ]:          0 :         if (ret <= 0)
     445                 :            :                 {
     446         [ #  # ]:          0 :                 if (BIO_dgram_should_retry(ret))
     447                 :            :                         {
     448                 :          0 :                         BIO_set_retry_write(b);  
     449                 :          0 :                         data->_errno = get_last_socket_error();
     450                 :            : 
     451                 :            : #if 0 /* higher layers are responsible for querying MTU, if necessary */
     452                 :            :                         if ( data->_errno == EMSGSIZE)
     453                 :            :                                 /* retrieve the new MTU */
     454                 :            :                                 BIO_ctrl(b, BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
     455                 :            : #endif
     456                 :            :                         }
     457                 :            :                 }
     458                 :          0 :         return(ret);
     459                 :            :         }
     460                 :            : 
     461                 :          0 : static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
     462                 :            :         {
     463                 :          0 :         long ret=1;
     464                 :            :         int *ip;
     465                 :          0 :         struct sockaddr *to = NULL;
     466                 :          0 :         bio_dgram_data *data = NULL;
     467                 :          0 :         int sockopt_val = 0;
     468                 :            : #if defined(OPENSSL_SYS_LINUX) && (defined(IP_MTU_DISCOVER) || defined(IP_MTU))
     469                 :            :         socklen_t sockopt_len;  /* assume that system supporting IP_MTU is
     470                 :            :                                  * modern enough to define socklen_t */
     471                 :            :         socklen_t addr_len;
     472                 :            :         union   {
     473                 :            :                 struct sockaddr sa;
     474                 :            :                 struct sockaddr_in s4;
     475                 :            : #if OPENSSL_USE_IPV6
     476                 :            :                 struct sockaddr_in6 s6;
     477                 :            : #endif
     478                 :            :                 } addr;
     479                 :            : #endif
     480                 :            : 
     481                 :          0 :         data = (bio_dgram_data *)b->ptr;
     482                 :            : 
     483   [ #  #  #  #  :          0 :         switch (cmd)
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     484                 :            :                 {
     485                 :            :         case BIO_CTRL_RESET:
     486                 :            :                 num=0;
     487                 :            :         case BIO_C_FILE_SEEK:
     488                 :            :                 ret=0;
     489                 :            :                 break;
     490                 :            :         case BIO_C_FILE_TELL:
     491                 :            :         case BIO_CTRL_INFO:
     492                 :            :                 ret=0;
     493                 :            :                 break;
     494                 :            :         case BIO_C_SET_FD:
     495                 :          0 :                 dgram_clear(b);
     496                 :          0 :                 b->num= *((int *)ptr);
     497                 :          0 :                 b->shutdown=(int)num;
     498                 :          0 :                 b->init=1;
     499                 :          0 :                 break;
     500                 :            :         case BIO_C_GET_FD:
     501         [ #  # ]:          0 :                 if (b->init)
     502                 :            :                         {
     503                 :          0 :                         ip=(int *)ptr;
     504         [ #  # ]:          0 :                         if (ip != NULL) *ip=b->num;
     505                 :          0 :                         ret=b->num;
     506                 :            :                         }
     507                 :            :                 else
     508                 :            :                         ret= -1;
     509                 :            :                 break;
     510                 :            :         case BIO_CTRL_GET_CLOSE:
     511                 :          0 :                 ret=b->shutdown;
     512                 :          0 :                 break;
     513                 :            :         case BIO_CTRL_SET_CLOSE:
     514                 :          0 :                 b->shutdown=(int)num;
     515                 :          0 :                 break;
     516                 :            :         case BIO_CTRL_PENDING:
     517                 :            :         case BIO_CTRL_WPENDING:
     518                 :            :                 ret=0;
     519                 :            :                 break;
     520                 :            :         case BIO_CTRL_DUP:
     521                 :            :         case BIO_CTRL_FLUSH:
     522                 :          0 :                 ret=1;
     523                 :          0 :                 break;
     524                 :            :         case BIO_CTRL_DGRAM_CONNECT:
     525                 :          0 :                 to = (struct sockaddr *)ptr;
     526                 :            : #if 0
     527                 :            :                 if (connect(b->num, to, sizeof(struct sockaddr)) < 0)
     528                 :            :                         { perror("connect"); ret = 0; }
     529                 :            :                 else
     530                 :            :                         {
     531                 :            : #endif
     532      [ #  #  # ]:          0 :                         switch (to->sa_family)
     533                 :            :                                 {
     534                 :            :                                 case AF_INET:
     535                 :          0 :                                         memcpy(&data->peer,to,sizeof(data->peer.sa_in));
     536                 :            :                                         break;
     537                 :            : #if OPENSSL_USE_IPV6
     538                 :            :                                 case AF_INET6:
     539                 :          0 :                                         memcpy(&data->peer,to,sizeof(data->peer.sa_in6));
     540                 :            :                                         break;
     541                 :            : #endif
     542                 :            :                                 default:
     543                 :          0 :                                         memcpy(&data->peer,to,sizeof(data->peer.sa));
     544                 :            :                                         break;
     545                 :            :                                 }
     546                 :            : #if 0
     547                 :            :                         }
     548                 :            : #endif
     549                 :            :                 break;
     550                 :            :                 /* (Linux)kernel sets DF bit on outgoing IP packets */
     551                 :            :         case BIO_CTRL_DGRAM_MTU_DISCOVER:
     552                 :            : #if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
     553                 :          0 :                 addr_len = (socklen_t)sizeof(addr);
     554                 :            :                 memset((void *)&addr, 0, sizeof(addr));
     555         [ #  # ]:          0 :                 if (getsockname(b->num, &addr.sa, &addr_len) < 0)
     556                 :            :                         {
     557                 :            :                         ret = 0;
     558                 :            :                         break;
     559                 :            :                         }
     560      [ #  #  # ]:          0 :                 switch (addr.sa.sa_family)
     561                 :            :                         {
     562                 :            :                 case AF_INET:
     563                 :          0 :                         sockopt_val = IP_PMTUDISC_DO;
     564         [ #  # ]:          0 :                         if ((ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER,
     565                 :            :                                 &sockopt_val, sizeof(sockopt_val))) < 0)
     566                 :          0 :                                 perror("setsockopt");
     567                 :            :                         break;
     568                 :            : #if OPENSSL_USE_IPV6 && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
     569                 :            :                 case AF_INET6:
     570                 :          0 :                         sockopt_val = IPV6_PMTUDISC_DO;
     571         [ #  # ]:          0 :                         if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
     572                 :            :                                 &sockopt_val, sizeof(sockopt_val))) < 0)
     573                 :          0 :                                 perror("setsockopt");
     574                 :            :                         break;
     575                 :            : #endif
     576                 :            :                 default:
     577                 :            :                         ret = -1;
     578                 :            :                         break;
     579                 :            :                         }
     580                 :            :                 ret = -1;
     581                 :            : #else
     582                 :            :                 break;
     583                 :            : #endif
     584                 :            :         case BIO_CTRL_DGRAM_QUERY_MTU:
     585                 :            : #if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU)
     586                 :          0 :                 addr_len = (socklen_t)sizeof(addr);
     587                 :            :                 memset((void *)&addr, 0, sizeof(addr));
     588         [ #  # ]:          0 :                 if (getsockname(b->num, &addr.sa, &addr_len) < 0)
     589                 :            :                         {
     590                 :            :                         ret = 0;
     591                 :            :                         break;
     592                 :            :                         }
     593                 :          0 :                 sockopt_len = sizeof(sockopt_val);
     594      [ #  #  # ]:          0 :                 switch (addr.sa.sa_family)
     595                 :            :                         {
     596                 :            :                 case AF_INET:
     597         [ #  # ]:          0 :                         if ((ret = getsockopt(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val,
     598         [ #  # ]:          0 :                                 &sockopt_len)) < 0 || sockopt_val < 0)
     599                 :            :                                 {
     600                 :            :                                 ret = 0;
     601                 :            :                                 }
     602                 :            :                         else
     603                 :            :                                 {
     604                 :            :                                 /* we assume that the transport protocol is UDP and no
     605                 :            :                                  * IP options are used.
     606                 :            :                                  */
     607                 :          0 :                                 data->mtu = sockopt_val - 8 - 20;
     608                 :          0 :                                 ret = data->mtu;
     609                 :            :                                 }
     610                 :            :                         break;
     611                 :            : #if OPENSSL_USE_IPV6 && defined(IPV6_MTU)
     612                 :            :                 case AF_INET6:
     613         [ #  # ]:          0 :                         if ((ret = getsockopt(b->num, IPPROTO_IPV6, IPV6_MTU, (void *)&sockopt_val,
     614         [ #  # ]:          0 :                                 &sockopt_len)) < 0 || sockopt_val < 0)
     615                 :            :                                 {
     616                 :            :                                 ret = 0;
     617                 :            :                                 }
     618                 :            :                         else
     619                 :            :                                 {
     620                 :            :                                 /* we assume that the transport protocol is UDP and no
     621                 :            :                                  * IPV6 options are used.
     622                 :            :                                  */
     623                 :          0 :                                 data->mtu = sockopt_val - 8 - 40;
     624                 :          0 :                                 ret = data->mtu;
     625                 :            :                                 }
     626                 :            :                         break;
     627                 :            : #endif
     628                 :            :                 default:
     629                 :            :                         ret = 0;
     630                 :            :                         break;
     631                 :            :                         }
     632                 :            : #else
     633                 :            :                 ret = 0;
     634                 :            : #endif
     635                 :            :                 break;
     636                 :            :         case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
     637         [ #  # ]:          0 :                 switch (data->peer.sa.sa_family)
     638                 :            :                         {
     639                 :            :                         case AF_INET:
     640                 :            :                                 ret = 576 - 20 - 8;
     641                 :            :                                 break;
     642                 :            : #if OPENSSL_USE_IPV6
     643                 :            :                         case AF_INET6:
     644                 :            : #ifdef IN6_IS_ADDR_V4MAPPED
     645 [ #  # ][ #  # ]:          0 :                                 if (IN6_IS_ADDR_V4MAPPED(&data->peer.sa_in6.sin6_addr))
         [ #  # ][ #  # ]
     646                 :            :                                         ret = 576 - 20 - 8;
     647                 :            :                                 else
     648                 :            : #endif
     649                 :          0 :                                         ret = 1280 - 40 - 8;
     650                 :            :                                 break;
     651                 :            : #endif
     652                 :            :                         default:
     653                 :            :                                 ret = 576 - 20 - 8;
     654                 :            :                                 break;
     655                 :            :                         }
     656                 :            :                 break;
     657                 :            :         case BIO_CTRL_DGRAM_GET_MTU:
     658                 :          0 :                 return data->mtu;
     659                 :            :                 break;
     660                 :            :         case BIO_CTRL_DGRAM_SET_MTU:
     661                 :          0 :                 data->mtu = num;
     662                 :          0 :                 ret = num;
     663                 :          0 :                 break;
     664                 :            :         case BIO_CTRL_DGRAM_SET_CONNECTED:
     665                 :          0 :                 to = (struct sockaddr *)ptr;
     666                 :            : 
     667         [ #  # ]:          0 :                 if ( to != NULL)
     668                 :            :                         {
     669                 :          0 :                         data->connected = 1;
     670      [ #  #  # ]:          0 :                         switch (to->sa_family)
     671                 :            :                                 {
     672                 :            :                                 case AF_INET:
     673                 :          0 :                                         memcpy(&data->peer,to,sizeof(data->peer.sa_in));
     674                 :            :                                         break;
     675                 :            : #if OPENSSL_USE_IPV6
     676                 :            :                                 case AF_INET6:
     677                 :          0 :                                         memcpy(&data->peer,to,sizeof(data->peer.sa_in6));
     678                 :            :                                         break;
     679                 :            : #endif
     680                 :            :                                 default:
     681                 :          0 :                                         memcpy(&data->peer,to,sizeof(data->peer.sa));
     682                 :            :                                         break;
     683                 :            :                                 }
     684                 :            :                         }
     685                 :            :                 else
     686                 :            :                         {
     687                 :          0 :                         data->connected = 0;
     688                 :          0 :                         memset(&(data->peer), 0x00, sizeof(data->peer));
     689                 :            :                         }
     690                 :            :                 break;
     691                 :            :         case BIO_CTRL_DGRAM_GET_PEER:
     692         [ #  # ]:          0 :                 switch (data->peer.sa.sa_family)
     693                 :            :                         {
     694                 :            :                         case AF_INET:
     695                 :            :                                 ret=sizeof(data->peer.sa_in);
     696                 :            :                                 break;
     697                 :            : #if OPENSSL_USE_IPV6
     698                 :            :                         case AF_INET6:
     699                 :          0 :                                 ret=sizeof(data->peer.sa_in6);
     700                 :          0 :                                 break;
     701                 :            : #endif
     702                 :            :                         default:
     703                 :            :                                 ret=sizeof(data->peer.sa);
     704                 :            :                                 break;
     705                 :            :                         }
     706         [ #  # ]:          0 :                 if (num==0 || num>ret)
     707                 :          0 :                         num=ret;
     708                 :          0 :                 memcpy(ptr,&data->peer,(ret=num));
     709                 :            :                 break;
     710                 :            :         case BIO_CTRL_DGRAM_SET_PEER:
     711                 :          0 :                 to = (struct sockaddr *) ptr;
     712      [ #  #  # ]:          0 :                 switch (to->sa_family)
     713                 :            :                         {
     714                 :            :                         case AF_INET:
     715                 :          0 :                                 memcpy(&data->peer,to,sizeof(data->peer.sa_in));
     716                 :            :                                 break;
     717                 :            : #if OPENSSL_USE_IPV6
     718                 :            :                         case AF_INET6:
     719                 :          0 :                                 memcpy(&data->peer,to,sizeof(data->peer.sa_in6));
     720                 :            :                                 break;
     721                 :            : #endif
     722                 :            :                         default:
     723                 :          0 :                                 memcpy(&data->peer,to,sizeof(data->peer.sa));
     724                 :            :                                 break;
     725                 :            :                         }
     726                 :            :                 break;
     727                 :            :         case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
     728                 :          0 :                 memcpy(&(data->next_timeout), ptr, sizeof(struct timeval));
     729                 :            :                 break;
     730                 :            : #if defined(SO_RCVTIMEO)
     731                 :            :         case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
     732                 :            : #ifdef OPENSSL_SYS_WINDOWS
     733                 :            :                 {
     734                 :            :                 struct timeval *tv = (struct timeval *)ptr;
     735                 :            :                 int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000;
     736                 :            :                 if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
     737                 :            :                         (void*)&timeout, sizeof(timeout)) < 0)
     738                 :            :                         { perror("setsockopt"); ret = -1; }
     739                 :            :                 }
     740                 :            : #else
     741         [ #  # ]:          0 :                 if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr,
     742                 :            :                         sizeof(struct timeval)) < 0)
     743                 :          0 :                         { perror("setsockopt");       ret = -1; }
     744                 :            : #endif
     745                 :            :                 break;
     746                 :            :         case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
     747                 :            :                 {
     748                 :          0 :                 union { size_t s; int i; } sz = {0};
     749                 :            : #ifdef OPENSSL_SYS_WINDOWS
     750                 :            :                 int timeout;
     751                 :            :                 struct timeval *tv = (struct timeval *)ptr;
     752                 :            : 
     753                 :            :                 sz.i = sizeof(timeout);
     754                 :            :                 if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
     755                 :            :                         (void*)&timeout, &sz.i) < 0)
     756                 :            :                         { perror("getsockopt"); ret = -1; }
     757                 :            :                 else
     758                 :            :                         {
     759                 :            :                         tv->tv_sec = timeout / 1000;
     760                 :            :                         tv->tv_usec = (timeout % 1000) * 1000;
     761                 :            :                         ret = sizeof(*tv);
     762                 :            :                         }
     763                 :            : #else
     764                 :          0 :                 sz.i = sizeof(struct timeval);
     765         [ #  # ]:          0 :                 if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, 
     766                 :            :                         ptr, (void *)&sz) < 0)
     767                 :          0 :                         { perror("getsockopt"); ret = -1; }
     768         [ #  # ]:          0 :                 else if (sizeof(sz.s)!=sizeof(sz.i) && sz.i==0)
     769                 :            :                         {
     770         [ #  # ]:          0 :                         OPENSSL_assert(sz.s<=sizeof(struct timeval));
     771                 :          0 :                         ret = (int)sz.s;
     772                 :            :                         }
     773                 :            :                 else
     774                 :          0 :                         ret = sz.i;
     775                 :            : #endif
     776                 :            :                 }
     777                 :          0 :                 break;
     778                 :            : #endif
     779                 :            : #if defined(SO_SNDTIMEO)
     780                 :            :         case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
     781                 :            : #ifdef OPENSSL_SYS_WINDOWS
     782                 :            :                 {
     783                 :            :                 struct timeval *tv = (struct timeval *)ptr;
     784                 :            :                 int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000;
     785                 :            :                 if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
     786                 :            :                         (void*)&timeout, sizeof(timeout)) < 0)
     787                 :            :                         { perror("setsockopt"); ret = -1; }
     788                 :            :                 }
     789                 :            : #else
     790         [ #  # ]:          0 :                 if ( setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr,
     791                 :            :                         sizeof(struct timeval)) < 0)
     792                 :          0 :                         { perror("setsockopt");       ret = -1; }
     793                 :            : #endif
     794                 :            :                 break;
     795                 :            :         case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
     796                 :            :                 {
     797                 :          0 :                 union { size_t s; int i; } sz = {0};
     798                 :            : #ifdef OPENSSL_SYS_WINDOWS
     799                 :            :                 int timeout;
     800                 :            :                 struct timeval *tv = (struct timeval *)ptr;
     801                 :            : 
     802                 :            :                 sz.i = sizeof(timeout);
     803                 :            :                 if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
     804                 :            :                         (void*)&timeout, &sz.i) < 0)
     805                 :            :                         { perror("getsockopt"); ret = -1; }
     806                 :            :                 else
     807                 :            :                         {
     808                 :            :                         tv->tv_sec = timeout / 1000;
     809                 :            :                         tv->tv_usec = (timeout % 1000) * 1000;
     810                 :            :                         ret = sizeof(*tv);
     811                 :            :                         }
     812                 :            : #else
     813                 :          0 :                 sz.i = sizeof(struct timeval);
     814         [ #  # ]:          0 :                 if ( getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, 
     815                 :            :                         ptr, (void *)&sz) < 0)
     816                 :          0 :                         { perror("getsockopt"); ret = -1; }
     817         [ #  # ]:          0 :                 else if (sizeof(sz.s)!=sizeof(sz.i) && sz.i==0)
     818                 :            :                         {
     819         [ #  # ]:          0 :                         OPENSSL_assert(sz.s<=sizeof(struct timeval));
     820                 :          0 :                         ret = (int)sz.s;
     821                 :            :                         }
     822                 :            :                 else
     823                 :          0 :                         ret = sz.i;
     824                 :            : #endif
     825                 :            :                 }
     826                 :          0 :                 break;
     827                 :            : #endif
     828                 :            :         case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
     829                 :            :                 /* fall-through */
     830                 :            :         case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
     831                 :            : #ifdef OPENSSL_SYS_WINDOWS
     832                 :            :                 if ( data->_errno == WSAETIMEDOUT)
     833                 :            : #else
     834         [ #  # ]:          0 :                 if ( data->_errno == EAGAIN)
     835                 :            : #endif
     836                 :            :                         {
     837                 :          0 :                         ret = 1;
     838                 :          0 :                         data->_errno = 0;
     839                 :            :                         }
     840                 :            :                 else
     841                 :            :                         ret = 0;
     842                 :            :                 break;
     843                 :            : #ifdef EMSGSIZE
     844                 :            :         case BIO_CTRL_DGRAM_MTU_EXCEEDED:
     845         [ #  # ]:          0 :                 if ( data->_errno == EMSGSIZE)
     846                 :            :                         {
     847                 :          0 :                         ret = 1;
     848                 :          0 :                         data->_errno = 0;
     849                 :            :                         }
     850                 :            :                 else
     851                 :            :                         ret = 0;
     852                 :            :                 break;
     853                 :            : #endif
     854                 :            :         case BIO_CTRL_DGRAM_SET_DONT_FRAG:
     855                 :          0 :                 sockopt_val = num ? 1 : 0;
     856                 :            : 
     857                 :            :                 switch (data->peer.sa.sa_family)
     858                 :            :                         {
     859                 :            :                         case AF_INET:
     860                 :            : #if defined(IP_DONTFRAG)
     861                 :            :                                 if ((ret = setsockopt(b->num, IPPROTO_IP, IP_DONTFRAG,
     862                 :            :                                         &sockopt_val, sizeof(sockopt_val))) < 0)
     863                 :            :                                         { perror("setsockopt"); ret = -1; }
     864                 :            : #elif defined(OPENSSL_SYS_LINUX) && defined(IP_MTUDISCOVER)
     865                 :            :                                 if ((sockopt_val = num ? IP_PMTUDISC_PROBE : IP_PMTUDISC_DONT),
     866                 :            :                                     (ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER,
     867                 :            :                                         &sockopt_val, sizeof(sockopt_val))) < 0)
     868                 :            :                                         { perror("setsockopt"); ret = -1; }
     869                 :            : #elif defined(OPENSSL_SYS_WINDOWS) && defined(IP_DONTFRAGMENT)
     870                 :            :                                 if ((ret = setsockopt(b->num, IPPROTO_IP, IP_DONTFRAGMENT,
     871                 :            :                                         (const char *)&sockopt_val, sizeof(sockopt_val))) < 0)
     872                 :            :                                         { perror("setsockopt"); ret = -1; }
     873                 :            : #else
     874                 :            :                                 ret = -1;
     875                 :            : #endif
     876                 :            :                                 break;
     877                 :            : #if OPENSSL_USE_IPV6 
     878                 :            :                         case AF_INET6:
     879                 :            : #if defined(IPV6_DONTFRAG)
     880                 :            :                                 if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_DONTFRAG,
     881                 :            :                                         (const void *)&sockopt_val, sizeof(sockopt_val))) < 0)
     882                 :            :                                         { perror("setsockopt"); ret = -1; }
     883                 :            : #elif defined(OPENSSL_SYS_LINUX) && defined(IPV6_MTUDISCOVER)
     884                 :            :                                 if ((sockopt_val = num ? IP_PMTUDISC_PROBE : IP_PMTUDISC_DONT),
     885                 :            :                                     (ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
     886                 :            :                                         &sockopt_val, sizeof(sockopt_val))) < 0)
     887                 :            :                                         { perror("setsockopt"); ret = -1; }
     888                 :            : #else
     889                 :            :                                 ret = -1;
     890                 :            : #endif
     891                 :            :                                 break;
     892                 :            : #endif
     893                 :            :                         default:
     894                 :            :                                 ret = -1;
     895                 :            :                                 break;
     896                 :            :                         }
     897                 :            :                 break;
     898                 :            :         default:
     899                 :            :                 ret=0;
     900                 :            :                 break;
     901                 :            :                 }
     902                 :          0 :         return(ret);
     903                 :            :         }
     904                 :            : 
     905                 :          0 : static int dgram_puts(BIO *bp, const char *str)
     906                 :            :         {
     907                 :            :         int n,ret;
     908                 :            : 
     909                 :          0 :         n=strlen(str);
     910                 :          0 :         ret=dgram_write(bp,str,n);
     911                 :          0 :         return(ret);
     912                 :            :         }
     913                 :            : 
     914                 :            : #ifndef OPENSSL_NO_SCTP
     915                 :            : BIO_METHOD *BIO_s_datagram_sctp(void)
     916                 :            :         {
     917                 :            :         return(&methods_dgramp_sctp);
     918                 :            :         }
     919                 :            : 
     920                 :            : BIO *BIO_new_dgram_sctp(int fd, int close_flag)
     921                 :            :         {
     922                 :            :         BIO *bio;
     923                 :            :         int ret, optval = 20000;
     924                 :            :         int auth_data = 0, auth_forward = 0;
     925                 :            :         unsigned char *p;
     926                 :            :         struct sctp_authchunk auth;
     927                 :            :         struct sctp_authchunks *authchunks;
     928                 :            :         socklen_t sockopt_len;
     929                 :            : #ifdef SCTP_AUTHENTICATION_EVENT
     930                 :            : #ifdef SCTP_EVENT
     931                 :            :         struct sctp_event event;
     932                 :            : #else
     933                 :            :         struct sctp_event_subscribe event;
     934                 :            : #endif
     935                 :            : #endif
     936                 :            : 
     937                 :            :         bio=BIO_new(BIO_s_datagram_sctp());
     938                 :            :         if (bio == NULL) return(NULL);
     939                 :            :         BIO_set_fd(bio,fd,close_flag);
     940                 :            : 
     941                 :            :         /* Activate SCTP-AUTH for DATA and FORWARD-TSN chunks */
     942                 :            :         auth.sauth_chunk = OPENSSL_SCTP_DATA_CHUNK_TYPE;
     943                 :            :         ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct sctp_authchunk));
     944                 :            :         OPENSSL_assert(ret >= 0);
     945                 :            :         auth.sauth_chunk = OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE;
     946                 :            :         ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct sctp_authchunk));
     947                 :            :         OPENSSL_assert(ret >= 0);
     948                 :            : 
     949                 :            :         /* Test if activation was successful. When using accept(),
     950                 :            :          * SCTP-AUTH has to be activated for the listening socket
     951                 :            :          * already, otherwise the connected socket won't use it. */
     952                 :            :         sockopt_len = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
     953                 :            :         authchunks = OPENSSL_malloc(sockopt_len);
     954                 :            :         memset(authchunks, 0, sizeof(sockopt_len));
     955                 :            :         ret = getsockopt(fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks, &sockopt_len);
     956                 :            :         OPENSSL_assert(ret >= 0);
     957                 :            : 
     958                 :            :         for (p = (unsigned char*) authchunks->gauth_chunks;
     959                 :            :              p < (unsigned char*) authchunks + sockopt_len;
     960                 :            :              p += sizeof(uint8_t))
     961                 :            :                 {
     962                 :            :                 if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE) auth_data = 1;
     963                 :            :                 if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE) auth_forward = 1;
     964                 :            :                 }
     965                 :            :                 
     966                 :            :         OPENSSL_free(authchunks);
     967                 :            : 
     968                 :            :         OPENSSL_assert(auth_data);
     969                 :            :         OPENSSL_assert(auth_forward);
     970                 :            : 
     971                 :            : #ifdef SCTP_AUTHENTICATION_EVENT
     972                 :            : #ifdef SCTP_EVENT
     973                 :            :         memset(&event, 0, sizeof(struct sctp_event));
     974                 :            :         event.se_assoc_id = 0;
     975                 :            :         event.se_type = SCTP_AUTHENTICATION_EVENT;
     976                 :            :         event.se_on = 1;
     977                 :            :         ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
     978                 :            :         OPENSSL_assert(ret >= 0);
     979                 :            : #else
     980                 :            :         sockopt_len = (socklen_t) sizeof(struct sctp_event_subscribe);
     981                 :            :         ret = getsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, &sockopt_len);
     982                 :            :         OPENSSL_assert(ret >= 0);
     983                 :            : 
     984                 :            :         event.sctp_authentication_event = 1;
     985                 :            : 
     986                 :            :         ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
     987                 :            :         OPENSSL_assert(ret >= 0);
     988                 :            : #endif
     989                 :            : #endif
     990                 :            : 
     991                 :            :         /* Disable partial delivery by setting the min size
     992                 :            :          * larger than the max record size of 2^14 + 2048 + 13
     993                 :            :          */
     994                 :            :         ret = setsockopt(fd, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT, &optval, sizeof(optval));
     995                 :            :         OPENSSL_assert(ret >= 0);
     996                 :            : 
     997                 :            :         return(bio);
     998                 :            :         }
     999                 :            : 
    1000                 :            : int BIO_dgram_is_sctp(BIO *bio)
    1001                 :            :         {
    1002                 :            :         return (BIO_method_type(bio) == BIO_TYPE_DGRAM_SCTP);
    1003                 :            :         }
    1004                 :            : 
    1005                 :            : static int dgram_sctp_new(BIO *bi)
    1006                 :            :         {
    1007                 :            :         bio_dgram_sctp_data *data = NULL;
    1008                 :            : 
    1009                 :            :         bi->init=0;
    1010                 :            :         bi->num=0;
    1011                 :            :         data = OPENSSL_malloc(sizeof(bio_dgram_sctp_data));
    1012                 :            :         if (data == NULL)
    1013                 :            :                 return 0;
    1014                 :            :         memset(data, 0x00, sizeof(bio_dgram_sctp_data));
    1015                 :            : #ifdef SCTP_PR_SCTP_NONE
    1016                 :            :         data->prinfo.pr_policy = SCTP_PR_SCTP_NONE;
    1017                 :            : #endif
    1018                 :            :     bi->ptr = data;
    1019                 :            : 
    1020                 :            :         bi->flags=0;
    1021                 :            :         return(1);
    1022                 :            :         }
    1023                 :            : 
    1024                 :            : static int dgram_sctp_free(BIO *a)
    1025                 :            :         {
    1026                 :            :         bio_dgram_sctp_data *data;
    1027                 :            : 
    1028                 :            :         if (a == NULL) return(0);
    1029                 :            :         if ( ! dgram_clear(a))
    1030                 :            :                 return 0;
    1031                 :            : 
    1032                 :            :         data = (bio_dgram_sctp_data *)a->ptr;
    1033                 :            :         if(data != NULL) OPENSSL_free(data);
    1034                 :            : 
    1035                 :            :         return(1);
    1036                 :            :         }
    1037                 :            : 
    1038                 :            : #ifdef SCTP_AUTHENTICATION_EVENT
    1039                 :            : void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp)
    1040                 :            :         {
    1041                 :            :         int ret;
    1042                 :            :         struct sctp_authkey_event* authkeyevent = &snp->sn_auth_event;
    1043                 :            : 
    1044                 :            :         if (authkeyevent->auth_indication == SCTP_AUTH_FREE_KEY)
    1045                 :            :                 {
    1046                 :            :                 struct sctp_authkeyid authkeyid;
    1047                 :            : 
    1048                 :            :                 /* delete key */
    1049                 :            :                 authkeyid.scact_keynumber = authkeyevent->auth_keynumber;
    1050                 :            :                 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,
    1051                 :            :                       &authkeyid, sizeof(struct sctp_authkeyid));
    1052                 :            :                 }
    1053                 :            :         }
    1054                 :            : #endif
    1055                 :            : 
    1056                 :            : static int dgram_sctp_read(BIO *b, char *out, int outl)
    1057                 :            :         {
    1058                 :            :         int ret = 0, n = 0, i, optval;
    1059                 :            :         socklen_t optlen;
    1060                 :            :         bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
    1061                 :            :         union sctp_notification *snp;
    1062                 :            :         struct msghdr msg;
    1063                 :            :         struct iovec iov;
    1064                 :            :         struct cmsghdr *cmsg;
    1065                 :            :         char cmsgbuf[512];
    1066                 :            : 
    1067                 :            :         if (out != NULL)
    1068                 :            :                 {
    1069                 :            :                 clear_socket_error();
    1070                 :            : 
    1071                 :            :                 do
    1072                 :            :                         {
    1073                 :            :                         memset(&data->rcvinfo, 0x00, sizeof(struct bio_dgram_sctp_rcvinfo));
    1074                 :            :                         iov.iov_base = out;
    1075                 :            :                         iov.iov_len = outl;
    1076                 :            :                         msg.msg_name = NULL;
    1077                 :            :                         msg.msg_namelen = 0;
    1078                 :            :                         msg.msg_iov = &iov;
    1079                 :            :                         msg.msg_iovlen = 1;
    1080                 :            :                         msg.msg_control = cmsgbuf;
    1081                 :            :                         msg.msg_controllen = 512;
    1082                 :            :                         msg.msg_flags = 0;
    1083                 :            :                         n = recvmsg(b->num, &msg, 0);
    1084                 :            : 
    1085                 :            :                         if (msg.msg_controllen > 0)
    1086                 :            :                                 {
    1087                 :            :                                 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
    1088                 :            :                                         {
    1089                 :            :                                         if (cmsg->cmsg_level != IPPROTO_SCTP)
    1090                 :            :                                                 continue;
    1091                 :            : #ifdef SCTP_RCVINFO
    1092                 :            :                                         if (cmsg->cmsg_type == SCTP_RCVINFO)
    1093                 :            :                                                 {
    1094                 :            :                                                 struct sctp_rcvinfo *rcvinfo;
    1095                 :            : 
    1096                 :            :                                                 rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmsg);
    1097                 :            :                                                 data->rcvinfo.rcv_sid = rcvinfo->rcv_sid;
    1098                 :            :                                                 data->rcvinfo.rcv_ssn = rcvinfo->rcv_ssn;
    1099                 :            :                                                 data->rcvinfo.rcv_flags = rcvinfo->rcv_flags;
    1100                 :            :                                                 data->rcvinfo.rcv_ppid = rcvinfo->rcv_ppid;
    1101                 :            :                                                 data->rcvinfo.rcv_tsn = rcvinfo->rcv_tsn;
    1102                 :            :                                                 data->rcvinfo.rcv_cumtsn = rcvinfo->rcv_cumtsn;
    1103                 :            :                                                 data->rcvinfo.rcv_context = rcvinfo->rcv_context;
    1104                 :            :                                                 }
    1105                 :            : #endif
    1106                 :            : #ifdef SCTP_SNDRCV
    1107                 :            :                                         if (cmsg->cmsg_type == SCTP_SNDRCV)
    1108                 :            :                                                 {
    1109                 :            :                                                 struct sctp_sndrcvinfo *sndrcvinfo;
    1110                 :            : 
    1111                 :            :                                                 sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
    1112                 :            :                                                 data->rcvinfo.rcv_sid = sndrcvinfo->sinfo_stream;
    1113                 :            :                                                 data->rcvinfo.rcv_ssn = sndrcvinfo->sinfo_ssn;
    1114                 :            :                                                 data->rcvinfo.rcv_flags = sndrcvinfo->sinfo_flags;
    1115                 :            :                                                 data->rcvinfo.rcv_ppid = sndrcvinfo->sinfo_ppid;
    1116                 :            :                                                 data->rcvinfo.rcv_tsn = sndrcvinfo->sinfo_tsn;
    1117                 :            :                                                 data->rcvinfo.rcv_cumtsn = sndrcvinfo->sinfo_cumtsn;
    1118                 :            :                                                 data->rcvinfo.rcv_context = sndrcvinfo->sinfo_context;
    1119                 :            :                                                 }
    1120                 :            : #endif
    1121                 :            :                                         }
    1122                 :            :                                 }
    1123                 :            : 
    1124                 :            :                         if (n <= 0)
    1125                 :            :                                 {
    1126                 :            :                                 if (n < 0)
    1127                 :            :                                         ret = n;
    1128                 :            :                                 break;
    1129                 :            :                                 }
    1130                 :            : 
    1131                 :            :                         if (msg.msg_flags & MSG_NOTIFICATION)
    1132                 :            :                                 {
    1133                 :            :                                 snp = (union sctp_notification*) out;
    1134                 :            :                                 if (snp->sn_header.sn_type == SCTP_SENDER_DRY_EVENT)
    1135                 :            :                                         {
    1136                 :            : #ifdef SCTP_EVENT
    1137                 :            :                                         struct sctp_event event;
    1138                 :            : #else
    1139                 :            :                                         struct sctp_event_subscribe event;
    1140                 :            :                                         socklen_t eventsize;
    1141                 :            : #endif
    1142                 :            :                                         /* If a message has been delayed until the socket
    1143                 :            :                                          * is dry, it can be sent now.
    1144                 :            :                                          */
    1145                 :            :                                         if (data->saved_message.length > 0)
    1146                 :            :                                                 {
    1147                 :            :                                                 dgram_sctp_write(data->saved_message.bio, data->saved_message.data,
    1148                 :            :                                                                  data->saved_message.length);
    1149                 :            :                                                 OPENSSL_free(data->saved_message.data);
    1150                 :            :                                                 data->saved_message.length = 0;
    1151                 :            :                                                 }
    1152                 :            : 
    1153                 :            :                                         /* disable sender dry event */
    1154                 :            : #ifdef SCTP_EVENT
    1155                 :            :                                         memset(&event, 0, sizeof(struct sctp_event));
    1156                 :            :                                         event.se_assoc_id = 0;
    1157                 :            :                                         event.se_type = SCTP_SENDER_DRY_EVENT;
    1158                 :            :                                         event.se_on = 0;
    1159                 :            :                                         i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
    1160                 :            :                                         OPENSSL_assert(i >= 0);
    1161                 :            : #else
    1162                 :            :                                         eventsize = sizeof(struct sctp_event_subscribe);
    1163                 :            :                                         i = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
    1164                 :            :                                         OPENSSL_assert(i >= 0);
    1165                 :            : 
    1166                 :            :                                         event.sctp_sender_dry_event = 0;
    1167                 :            : 
    1168                 :            :                                         i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
    1169                 :            :                                         OPENSSL_assert(i >= 0);
    1170                 :            : #endif
    1171                 :            :                                         }
    1172                 :            : 
    1173                 :            : #ifdef SCTP_AUTHENTICATION_EVENT
    1174                 :            :                                 if (snp->sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
    1175                 :            :                                         dgram_sctp_handle_auth_free_key_event(b, snp);
    1176                 :            : #endif
    1177                 :            : 
    1178                 :            :                                 if (data->handle_notifications != NULL)
    1179                 :            :                                         data->handle_notifications(b, data->notification_context, (void*) out);
    1180                 :            : 
    1181                 :            :                                 memset(out, 0, outl);
    1182                 :            :                                 }
    1183                 :            :                         else
    1184                 :            :                                 ret += n;
    1185                 :            :                         }
    1186                 :            :                 while ((msg.msg_flags & MSG_NOTIFICATION) && (msg.msg_flags & MSG_EOR) && (ret < outl));
    1187                 :            : 
    1188                 :            :                 if (ret > 0 && !(msg.msg_flags & MSG_EOR))
    1189                 :            :                         {
    1190                 :            :                         /* Partial message read, this should never happen! */
    1191                 :            : 
    1192                 :            :                         /* The buffer was too small, this means the peer sent
    1193                 :            :                          * a message that was larger than allowed. */
    1194                 :            :                         if (ret == outl)
    1195                 :            :                                 return -1;
    1196                 :            : 
    1197                 :            :                         /* Test if socket buffer can handle max record
    1198                 :            :                          * size (2^14 + 2048 + 13)
    1199                 :            :                          */
    1200                 :            :                         optlen = (socklen_t) sizeof(int);
    1201                 :            :                         ret = getsockopt(b->num, SOL_SOCKET, SO_RCVBUF, &optval, &optlen);
    1202                 :            :                         OPENSSL_assert(ret >= 0);
    1203                 :            :                         OPENSSL_assert(optval >= 18445);
    1204                 :            : 
    1205                 :            :                         /* Test if SCTP doesn't partially deliver below
    1206                 :            :                          * max record size (2^14 + 2048 + 13)
    1207                 :            :                          */
    1208                 :            :                         optlen = (socklen_t) sizeof(int);
    1209                 :            :                         ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT,
    1210                 :            :                                          &optval, &optlen);
    1211                 :            :                         OPENSSL_assert(ret >= 0);
    1212                 :            :                         OPENSSL_assert(optval >= 18445);
    1213                 :            : 
    1214                 :            :                         /* Partially delivered notification??? Probably a bug.... */
    1215                 :            :                         OPENSSL_assert(!(msg.msg_flags & MSG_NOTIFICATION));
    1216                 :            : 
    1217                 :            :                         /* Everything seems ok till now, so it's most likely
    1218                 :            :                          * a message dropped by PR-SCTP.
    1219                 :            :                          */
    1220                 :            :                         memset(out, 0, outl);
    1221                 :            :                         BIO_set_retry_read(b);
    1222                 :            :                         return -1;
    1223                 :            :                         }
    1224                 :            : 
    1225                 :            :                 BIO_clear_retry_flags(b);
    1226                 :            :                 if (ret < 0)
    1227                 :            :                         {
    1228                 :            :                         if (BIO_dgram_should_retry(ret))
    1229                 :            :                                 {
    1230                 :            :                                 BIO_set_retry_read(b);
    1231                 :            :                                 data->_errno = get_last_socket_error();
    1232                 :            :                                 }
    1233                 :            :                         }
    1234                 :            : 
    1235                 :            :                 /* Test if peer uses SCTP-AUTH before continuing */
    1236                 :            :                 if (!data->peer_auth_tested)
    1237                 :            :                         {
    1238                 :            :                         int ii, auth_data = 0, auth_forward = 0;
    1239                 :            :                         unsigned char *p;
    1240                 :            :                         struct sctp_authchunks *authchunks;
    1241                 :            : 
    1242                 :            :                         optlen = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
    1243                 :            :                         authchunks = OPENSSL_malloc(optlen);
    1244                 :            :                         memset(authchunks, 0, sizeof(optlen));
    1245                 :            :                         ii = getsockopt(b->num, IPPROTO_SCTP, SCTP_PEER_AUTH_CHUNKS, authchunks, &optlen);
    1246                 :            :                         OPENSSL_assert(ii >= 0);
    1247                 :            : 
    1248                 :            :                         for (p = (unsigned char*) authchunks->gauth_chunks;
    1249                 :            :                                  p < (unsigned char*) authchunks + optlen;
    1250                 :            :                                  p += sizeof(uint8_t))
    1251                 :            :                                 {
    1252                 :            :                                 if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE) auth_data = 1;
    1253                 :            :                                 if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE) auth_forward = 1;
    1254                 :            :                                 }
    1255                 :            : 
    1256                 :            :                         OPENSSL_free(authchunks);
    1257                 :            : 
    1258                 :            :                         if (!auth_data || !auth_forward)
    1259                 :            :                                 {
    1260                 :            :                                 BIOerr(BIO_F_DGRAM_SCTP_READ,BIO_R_CONNECT_ERROR);
    1261                 :            :                                 return -1;
    1262                 :            :                                 }
    1263                 :            : 
    1264                 :            :                         data->peer_auth_tested = 1;
    1265                 :            :                         }
    1266                 :            :                 }
    1267                 :            :         return(ret);
    1268                 :            :         }
    1269                 :            : 
    1270                 :            : static int dgram_sctp_write(BIO *b, const char *in, int inl)
    1271                 :            :         {
    1272                 :            :         int ret;
    1273                 :            :         bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
    1274                 :            :         struct bio_dgram_sctp_sndinfo *sinfo = &(data->sndinfo);
    1275                 :            :         struct bio_dgram_sctp_prinfo *pinfo = &(data->prinfo);
    1276                 :            :         struct bio_dgram_sctp_sndinfo handshake_sinfo;
    1277                 :            :         struct iovec iov[1];
    1278                 :            :         struct msghdr msg;
    1279                 :            :         struct cmsghdr *cmsg;
    1280                 :            : #if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)
    1281                 :            :         char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo)) + CMSG_SPACE(sizeof(struct sctp_prinfo))];
    1282                 :            :         struct sctp_sndinfo *sndinfo;
    1283                 :            :         struct sctp_prinfo *prinfo;
    1284                 :            : #else
    1285                 :            :         char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
    1286                 :            :         struct sctp_sndrcvinfo *sndrcvinfo;
    1287                 :            : #endif
    1288                 :            : 
    1289                 :            :         clear_socket_error();
    1290                 :            : 
    1291                 :            :         /* If we're send anything else than application data,
    1292                 :            :          * disable all user parameters and flags.
    1293                 :            :          */
    1294                 :            :         if (in[0] != 23) {
    1295                 :            :                 memset(&handshake_sinfo, 0x00, sizeof(struct bio_dgram_sctp_sndinfo));
    1296                 :            : #ifdef SCTP_SACK_IMMEDIATELY
    1297                 :            :                 handshake_sinfo.snd_flags = SCTP_SACK_IMMEDIATELY;
    1298                 :            : #endif
    1299                 :            :                 sinfo = &handshake_sinfo;
    1300                 :            :         }
    1301                 :            : 
    1302                 :            :         /* If we have to send a shutdown alert message and the
    1303                 :            :          * socket is not dry yet, we have to save it and send it
    1304                 :            :          * as soon as the socket gets dry.
    1305                 :            :          */
    1306                 :            :         if (data->save_shutdown && !BIO_dgram_sctp_wait_for_dry(b))
    1307                 :            :         {
    1308                 :            :                 data->saved_message.bio = b;
    1309                 :            :                 data->saved_message.length = inl;
    1310                 :            :                 data->saved_message.data = OPENSSL_malloc(inl);
    1311                 :            :                 memcpy(data->saved_message.data, in, inl);
    1312                 :            :                 return inl;
    1313                 :            :         }
    1314                 :            : 
    1315                 :            :         iov[0].iov_base = (char *)in;
    1316                 :            :         iov[0].iov_len = inl;
    1317                 :            :         msg.msg_name = NULL;
    1318                 :            :         msg.msg_namelen = 0;
    1319                 :            :         msg.msg_iov = iov;
    1320                 :            :         msg.msg_iovlen = 1;
    1321                 :            :         msg.msg_control = (caddr_t)cmsgbuf;
    1322                 :            :         msg.msg_controllen = 0;
    1323                 :            :         msg.msg_flags = 0;
    1324                 :            : #if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)
    1325                 :            :         cmsg = (struct cmsghdr *)cmsgbuf;
    1326                 :            :         cmsg->cmsg_level = IPPROTO_SCTP;
    1327                 :            :         cmsg->cmsg_type = SCTP_SNDINFO;
    1328                 :            :         cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));
    1329                 :            :         sndinfo = (struct sctp_sndinfo *)CMSG_DATA(cmsg);
    1330                 :            :         memset(sndinfo, 0, sizeof(struct sctp_sndinfo));
    1331                 :            :         sndinfo->snd_sid = sinfo->snd_sid;
    1332                 :            :         sndinfo->snd_flags = sinfo->snd_flags;
    1333                 :            :         sndinfo->snd_ppid = sinfo->snd_ppid;
    1334                 :            :         sndinfo->snd_context = sinfo->snd_context;
    1335                 :            :         msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));
    1336                 :            : 
    1337                 :            :         cmsg = (struct cmsghdr *)&cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo))];
    1338                 :            :         cmsg->cmsg_level = IPPROTO_SCTP;
    1339                 :            :         cmsg->cmsg_type = SCTP_PRINFO;
    1340                 :            :         cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));
    1341                 :            :         prinfo = (struct sctp_prinfo *)CMSG_DATA(cmsg);
    1342                 :            :         memset(prinfo, 0, sizeof(struct sctp_prinfo));
    1343                 :            :         prinfo->pr_policy = pinfo->pr_policy;
    1344                 :            :         prinfo->pr_value = pinfo->pr_value;
    1345                 :            :         msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));
    1346                 :            : #else
    1347                 :            :         cmsg = (struct cmsghdr *)cmsgbuf;
    1348                 :            :         cmsg->cmsg_level = IPPROTO_SCTP;
    1349                 :            :         cmsg->cmsg_type = SCTP_SNDRCV;
    1350                 :            :         cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
    1351                 :            :         sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
    1352                 :            :         memset(sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo));
    1353                 :            :         sndrcvinfo->sinfo_stream = sinfo->snd_sid;
    1354                 :            :         sndrcvinfo->sinfo_flags = sinfo->snd_flags;
    1355                 :            : #ifdef __FreeBSD__
    1356                 :            :         sndrcvinfo->sinfo_flags |= pinfo->pr_policy;
    1357                 :            : #endif
    1358                 :            :         sndrcvinfo->sinfo_ppid = sinfo->snd_ppid;
    1359                 :            :         sndrcvinfo->sinfo_context = sinfo->snd_context;
    1360                 :            :         sndrcvinfo->sinfo_timetolive = pinfo->pr_value;
    1361                 :            :         msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo));
    1362                 :            : #endif
    1363                 :            : 
    1364                 :            :         ret = sendmsg(b->num, &msg, 0);
    1365                 :            : 
    1366                 :            :         BIO_clear_retry_flags(b);
    1367                 :            :         if (ret <= 0)
    1368                 :            :                 {
    1369                 :            :                 if (BIO_dgram_should_retry(ret))
    1370                 :            :                         {
    1371                 :            :                         BIO_set_retry_write(b);  
    1372                 :            :                         data->_errno = get_last_socket_error();
    1373                 :            :                         }
    1374                 :            :                 }
    1375                 :            :         return(ret);
    1376                 :            :         }
    1377                 :            : 
    1378                 :            : static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
    1379                 :            :         {
    1380                 :            :         long ret=1;
    1381                 :            :         bio_dgram_sctp_data *data = NULL;
    1382                 :            :         socklen_t sockopt_len = 0;
    1383                 :            :         struct sctp_authkeyid authkeyid;
    1384                 :            :         struct sctp_authkey *authkey = NULL;
    1385                 :            : 
    1386                 :            :         data = (bio_dgram_sctp_data *)b->ptr;
    1387                 :            : 
    1388                 :            :         switch (cmd)
    1389                 :            :                 {
    1390                 :            :         case BIO_CTRL_DGRAM_QUERY_MTU:
    1391                 :            :                 /* Set to maximum (2^14)
    1392                 :            :                  * and ignore user input to enable transport
    1393                 :            :                  * protocol fragmentation.
    1394                 :            :                  * Returns always 2^14.
    1395                 :            :                  */
    1396                 :            :                 data->mtu = 16384;
    1397                 :            :                 ret = data->mtu;
    1398                 :            :                 break;
    1399                 :            :         case BIO_CTRL_DGRAM_SET_MTU:
    1400                 :            :                 /* Set to maximum (2^14)
    1401                 :            :                  * and ignore input to enable transport
    1402                 :            :                  * protocol fragmentation.
    1403                 :            :                  * Returns always 2^14.
    1404                 :            :                  */
    1405                 :            :                 data->mtu = 16384;
    1406                 :            :                 ret = data->mtu;
    1407                 :            :                 break;
    1408                 :            :         case BIO_CTRL_DGRAM_SET_CONNECTED:
    1409                 :            :         case BIO_CTRL_DGRAM_CONNECT:
    1410                 :            :                 /* Returns always -1. */
    1411                 :            :                 ret = -1;
    1412                 :            :                 break;
    1413                 :            :         case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
    1414                 :            :                 /* SCTP doesn't need the DTLS timer
    1415                 :            :                  * Returns always 1.
    1416                 :            :                  */
    1417                 :            :                 break;
    1418                 :            :         case BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE:
    1419                 :            :                 if (num > 0)
    1420                 :            :                         data->in_handshake = 1;
    1421                 :            :                 else
    1422                 :            :                         data->in_handshake = 0;
    1423                 :            : 
    1424                 :            :                 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_NODELAY, &data->in_handshake, sizeof(int));
    1425                 :            :                 break;
    1426                 :            :         case BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY:
    1427                 :            :                 /* New shared key for SCTP AUTH.
    1428                 :            :                  * Returns 0 on success, -1 otherwise.
    1429                 :            :                  */
    1430                 :            : 
    1431                 :            :                 /* Get active key */
    1432                 :            :                 sockopt_len = sizeof(struct sctp_authkeyid);
    1433                 :            :                 ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len);
    1434                 :            :                 if (ret < 0) break;
    1435                 :            : 
    1436                 :            :                 /* Add new key */
    1437                 :            :                 sockopt_len = sizeof(struct sctp_authkey) + 64 * sizeof(uint8_t);
    1438                 :            :                 authkey = OPENSSL_malloc(sockopt_len);
    1439                 :            :                 if (authkey == NULL)
    1440                 :            :                         {
    1441                 :            :                         ret = -1;
    1442                 :            :                         break;
    1443                 :            :                         }
    1444                 :            :                 memset(authkey, 0x00, sockopt_len);
    1445                 :            :                 authkey->sca_keynumber = authkeyid.scact_keynumber + 1;
    1446                 :            : #ifndef __FreeBSD__
    1447                 :            :                 /* This field is missing in FreeBSD 8.2 and earlier,
    1448                 :            :                  * and FreeBSD 8.3 and higher work without it.
    1449                 :            :                  */
    1450                 :            :                 authkey->sca_keylength = 64;
    1451                 :            : #endif
    1452                 :            :                 memcpy(&authkey->sca_key[0], ptr, 64 * sizeof(uint8_t));
    1453                 :            : 
    1454                 :            :                 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_KEY, authkey, sockopt_len);
    1455                 :            :                 OPENSSL_free(authkey);
    1456                 :            :                 authkey = NULL;
    1457                 :            :                 if (ret < 0) break;
    1458                 :            : 
    1459                 :            :                 /* Reset active key */
    1460                 :            :                 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
    1461                 :            :                       &authkeyid, sizeof(struct sctp_authkeyid));
    1462                 :            :                 if (ret < 0) break;
    1463                 :            : 
    1464                 :            :                 break;
    1465                 :            :         case BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY:
    1466                 :            :                 /* Returns 0 on success, -1 otherwise. */
    1467                 :            : 
    1468                 :            :                 /* Get active key */
    1469                 :            :                 sockopt_len = sizeof(struct sctp_authkeyid);
    1470                 :            :                 ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len);
    1471                 :            :                 if (ret < 0) break;
    1472                 :            : 
    1473                 :            :                 /* Set active key */
    1474                 :            :                 authkeyid.scact_keynumber = authkeyid.scact_keynumber + 1;
    1475                 :            :                 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
    1476                 :            :                       &authkeyid, sizeof(struct sctp_authkeyid));
    1477                 :            :                 if (ret < 0) break;
    1478                 :            : 
    1479                 :            :                 /* CCS has been sent, so remember that and fall through
    1480                 :            :                  * to check if we need to deactivate an old key
    1481                 :            :                  */
    1482                 :            :                 data->ccs_sent = 1;
    1483                 :            : 
    1484                 :            :         case BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD:
    1485                 :            :                 /* Returns 0 on success, -1 otherwise. */
    1486                 :            : 
    1487                 :            :                 /* Has this command really been called or is this just a fall-through? */
    1488                 :            :                 if (cmd == BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD)
    1489                 :            :                         data->ccs_rcvd = 1;
    1490                 :            : 
    1491                 :            :                 /* CSS has been both, received and sent, so deactivate an old key */
    1492                 :            :                 if (data->ccs_rcvd == 1 && data->ccs_sent == 1)
    1493                 :            :                         {
    1494                 :            :                         /* Get active key */
    1495                 :            :                         sockopt_len = sizeof(struct sctp_authkeyid);
    1496                 :            :                         ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len);
    1497                 :            :                         if (ret < 0) break;
    1498                 :            : 
    1499                 :            :                         /* Deactivate key or delete second last key if
    1500                 :            :                          * SCTP_AUTHENTICATION_EVENT is not available.
    1501                 :            :                          */
    1502                 :            :                         authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;
    1503                 :            : #ifdef SCTP_AUTH_DEACTIVATE_KEY
    1504                 :            :                         sockopt_len = sizeof(struct sctp_authkeyid);
    1505                 :            :                         ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DEACTIVATE_KEY,
    1506                 :            :                               &authkeyid, sockopt_len);
    1507                 :            :                         if (ret < 0) break;
    1508                 :            : #endif
    1509                 :            : #ifndef SCTP_AUTHENTICATION_EVENT
    1510                 :            :                         if (authkeyid.scact_keynumber > 0)
    1511                 :            :                                 {
    1512                 :            :                                 authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;
    1513                 :            :                                 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,
    1514                 :            :                                           &authkeyid, sizeof(struct sctp_authkeyid));
    1515                 :            :                                 if (ret < 0) break;
    1516                 :            :                                 }
    1517                 :            : #endif
    1518                 :            : 
    1519                 :            :                         data->ccs_rcvd = 0;
    1520                 :            :                         data->ccs_sent = 0;
    1521                 :            :                         }
    1522                 :            :                 break;
    1523                 :            :         case BIO_CTRL_DGRAM_SCTP_GET_SNDINFO:
    1524                 :            :                 /* Returns the size of the copied struct. */
    1525                 :            :                 if (num > (long) sizeof(struct bio_dgram_sctp_sndinfo))
    1526                 :            :                         num = sizeof(struct bio_dgram_sctp_sndinfo);
    1527                 :            : 
    1528                 :            :                 memcpy(ptr, &(data->sndinfo), num);
    1529                 :            :                 ret = num;
    1530                 :            :                 break;
    1531                 :            :         case BIO_CTRL_DGRAM_SCTP_SET_SNDINFO:
    1532                 :            :                 /* Returns the size of the copied struct. */
    1533                 :            :                 if (num > (long) sizeof(struct bio_dgram_sctp_sndinfo))
    1534                 :            :                         num = sizeof(struct bio_dgram_sctp_sndinfo);
    1535                 :            : 
    1536                 :            :                 memcpy(&(data->sndinfo), ptr, num);
    1537                 :            :                 break;
    1538                 :            :         case BIO_CTRL_DGRAM_SCTP_GET_RCVINFO:
    1539                 :            :                 /* Returns the size of the copied struct. */
    1540                 :            :                 if (num > (long) sizeof(struct bio_dgram_sctp_rcvinfo))
    1541                 :            :                         num = sizeof(struct bio_dgram_sctp_rcvinfo);
    1542                 :            : 
    1543                 :            :                 memcpy(ptr, &data->rcvinfo, num);
    1544                 :            : 
    1545                 :            :                 ret = num;
    1546                 :            :                 break;
    1547                 :            :         case BIO_CTRL_DGRAM_SCTP_SET_RCVINFO:
    1548                 :            :                 /* Returns the size of the copied struct. */
    1549                 :            :                 if (num > (long) sizeof(struct bio_dgram_sctp_rcvinfo))
    1550                 :            :                         num = sizeof(struct bio_dgram_sctp_rcvinfo);
    1551                 :            : 
    1552                 :            :                 memcpy(&(data->rcvinfo), ptr, num);
    1553                 :            :                 break;
    1554                 :            :         case BIO_CTRL_DGRAM_SCTP_GET_PRINFO:
    1555                 :            :                 /* Returns the size of the copied struct. */
    1556                 :            :                 if (num > (long) sizeof(struct bio_dgram_sctp_prinfo))
    1557                 :            :                         num = sizeof(struct bio_dgram_sctp_prinfo);
    1558                 :            : 
    1559                 :            :                 memcpy(ptr, &(data->prinfo), num);
    1560                 :            :                 ret = num;
    1561                 :            :                 break;
    1562                 :            :         case BIO_CTRL_DGRAM_SCTP_SET_PRINFO:
    1563                 :            :                 /* Returns the size of the copied struct. */
    1564                 :            :                 if (num > (long) sizeof(struct bio_dgram_sctp_prinfo))
    1565                 :            :                         num = sizeof(struct bio_dgram_sctp_prinfo);
    1566                 :            : 
    1567                 :            :                 memcpy(&(data->prinfo), ptr, num);
    1568                 :            :                 break;
    1569                 :            :         case BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN:
    1570                 :            :                 /* Returns always 1. */
    1571                 :            :                 if (num > 0)
    1572                 :            :                         data->save_shutdown = 1;
    1573                 :            :                 else
    1574                 :            :                         data->save_shutdown = 0;
    1575                 :            :                 break;
    1576                 :            : 
    1577                 :            :         default:
    1578                 :            :                 /* Pass to default ctrl function to
    1579                 :            :                  * process SCTP unspecific commands
    1580                 :            :                  */
    1581                 :            :                 ret=dgram_ctrl(b, cmd, num, ptr);
    1582                 :            :                 break;
    1583                 :            :                 }
    1584                 :            :         return(ret);
    1585                 :            :         }
    1586                 :            : 
    1587                 :            : int BIO_dgram_sctp_notification_cb(BIO *b,
    1588                 :            :                                    void (*handle_notifications)(BIO *bio, void *context, void *buf),
    1589                 :            :                                    void *context)
    1590                 :            :         {
    1591                 :            :         bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;
    1592                 :            : 
    1593                 :            :         if (handle_notifications != NULL)
    1594                 :            :                 {
    1595                 :            :                 data->handle_notifications = handle_notifications;
    1596                 :            :                 data->notification_context = context;
    1597                 :            :                 }
    1598                 :            :         else
    1599                 :            :                 return -1;
    1600                 :            : 
    1601                 :            :         return 0;
    1602                 :            :         }
    1603                 :            : 
    1604                 :            : int BIO_dgram_sctp_wait_for_dry(BIO *b)
    1605                 :            : {
    1606                 :            :         int is_dry = 0;
    1607                 :            :         int n, sockflags, ret;
    1608                 :            :         union sctp_notification snp;
    1609                 :            :         struct msghdr msg;
    1610                 :            :         struct iovec iov;
    1611                 :            : #ifdef SCTP_EVENT
    1612                 :            :         struct sctp_event event;
    1613                 :            : #else
    1614                 :            :         struct sctp_event_subscribe event;
    1615                 :            :         socklen_t eventsize;
    1616                 :            : #endif
    1617                 :            :         bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
    1618                 :            : 
    1619                 :            :         /* set sender dry event */
    1620                 :            : #ifdef SCTP_EVENT
    1621                 :            :         memset(&event, 0, sizeof(struct sctp_event));
    1622                 :            :         event.se_assoc_id = 0;
    1623                 :            :         event.se_type = SCTP_SENDER_DRY_EVENT;
    1624                 :            :         event.se_on = 1;
    1625                 :            :         ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
    1626                 :            : #else
    1627                 :            :         eventsize = sizeof(struct sctp_event_subscribe);
    1628                 :            :         ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
    1629                 :            :         if (ret < 0)
    1630                 :            :                 return -1;
    1631                 :            :         
    1632                 :            :         event.sctp_sender_dry_event = 1;
    1633                 :            :         
    1634                 :            :         ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
    1635                 :            : #endif
    1636                 :            :         if (ret < 0)
    1637                 :            :                 return -1;
    1638                 :            : 
    1639                 :            :         /* peek for notification */
    1640                 :            :         memset(&snp, 0x00, sizeof(union sctp_notification));
    1641                 :            :         iov.iov_base = (char *)&snp;
    1642                 :            :         iov.iov_len = sizeof(union sctp_notification);
    1643                 :            :         msg.msg_name = NULL;
    1644                 :            :         msg.msg_namelen = 0;
    1645                 :            :         msg.msg_iov = &iov;
    1646                 :            :         msg.msg_iovlen = 1;
    1647                 :            :         msg.msg_control = NULL;
    1648                 :            :         msg.msg_controllen = 0;
    1649                 :            :         msg.msg_flags = 0;
    1650                 :            : 
    1651                 :            :         n = recvmsg(b->num, &msg, MSG_PEEK);
    1652                 :            :         if (n <= 0)
    1653                 :            :                 {
    1654                 :            :                 if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != EWOULDBLOCK))
    1655                 :            :                         return -1;
    1656                 :            :                 else
    1657                 :            :                         return 0;
    1658                 :            :                 }
    1659                 :            : 
    1660                 :            :         /* if we find a notification, process it and try again if necessary */
    1661                 :            :         while (msg.msg_flags & MSG_NOTIFICATION)
    1662                 :            :                 {
    1663                 :            :                 memset(&snp, 0x00, sizeof(union sctp_notification));
    1664                 :            :                 iov.iov_base = (char *)&snp;
    1665                 :            :                 iov.iov_len = sizeof(union sctp_notification);
    1666                 :            :                 msg.msg_name = NULL;
    1667                 :            :                 msg.msg_namelen = 0;
    1668                 :            :                 msg.msg_iov = &iov;
    1669                 :            :                 msg.msg_iovlen = 1;
    1670                 :            :                 msg.msg_control = NULL;
    1671                 :            :                 msg.msg_controllen = 0;
    1672                 :            :                 msg.msg_flags = 0;
    1673                 :            : 
    1674                 :            :                 n = recvmsg(b->num, &msg, 0);
    1675                 :            :                 if (n <= 0)
    1676                 :            :                         {
    1677                 :            :                         if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != EWOULDBLOCK))
    1678                 :            :                                 return -1;
    1679                 :            :                         else
    1680                 :            :                                 return is_dry;
    1681                 :            :                         }
    1682                 :            :                 
    1683                 :            :                 if (snp.sn_header.sn_type == SCTP_SENDER_DRY_EVENT)
    1684                 :            :                         {
    1685                 :            :                         is_dry = 1;
    1686                 :            : 
    1687                 :            :                         /* disable sender dry event */
    1688                 :            : #ifdef SCTP_EVENT
    1689                 :            :                         memset(&event, 0, sizeof(struct sctp_event));
    1690                 :            :                         event.se_assoc_id = 0;
    1691                 :            :                         event.se_type = SCTP_SENDER_DRY_EVENT;
    1692                 :            :                         event.se_on = 0;
    1693                 :            :                         ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
    1694                 :            : #else
    1695                 :            :                         eventsize = (socklen_t) sizeof(struct sctp_event_subscribe);
    1696                 :            :                         ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
    1697                 :            :                         if (ret < 0)
    1698                 :            :                                 return -1;
    1699                 :            : 
    1700                 :            :                         event.sctp_sender_dry_event = 0;
    1701                 :            : 
    1702                 :            :                         ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
    1703                 :            : #endif
    1704                 :            :                         if (ret < 0)
    1705                 :            :                                 return -1;
    1706                 :            :                         }
    1707                 :            : 
    1708                 :            : #ifdef SCTP_AUTHENTICATION_EVENT
    1709                 :            :                 if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
    1710                 :            :                         dgram_sctp_handle_auth_free_key_event(b, &snp);
    1711                 :            : #endif
    1712                 :            : 
    1713                 :            :                 if (data->handle_notifications != NULL)
    1714                 :            :                         data->handle_notifications(b, data->notification_context, (void*) &snp);
    1715                 :            : 
    1716                 :            :                 /* found notification, peek again */
    1717                 :            :                 memset(&snp, 0x00, sizeof(union sctp_notification));
    1718                 :            :                 iov.iov_base = (char *)&snp;
    1719                 :            :                 iov.iov_len = sizeof(union sctp_notification);
    1720                 :            :                 msg.msg_name = NULL;
    1721                 :            :                 msg.msg_namelen = 0;
    1722                 :            :                 msg.msg_iov = &iov;
    1723                 :            :                 msg.msg_iovlen = 1;
    1724                 :            :                 msg.msg_control = NULL;
    1725                 :            :                 msg.msg_controllen = 0;
    1726                 :            :                 msg.msg_flags = 0;
    1727                 :            : 
    1728                 :            :                 /* if we have seen the dry already, don't wait */
    1729                 :            :                 if (is_dry)
    1730                 :            :                         {
    1731                 :            :                         sockflags = fcntl(b->num, F_GETFL, 0);
    1732                 :            :                         fcntl(b->num, F_SETFL, O_NONBLOCK);
    1733                 :            :                         }
    1734                 :            : 
    1735                 :            :                 n = recvmsg(b->num, &msg, MSG_PEEK);
    1736                 :            : 
    1737                 :            :                 if (is_dry)
    1738                 :            :                         {
    1739                 :            :                         fcntl(b->num, F_SETFL, sockflags);
    1740                 :            :                         }
    1741                 :            : 
    1742                 :            :                 if (n <= 0)
    1743                 :            :                         {
    1744                 :            :                         if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != EWOULDBLOCK))
    1745                 :            :                                 return -1;
    1746                 :            :                         else
    1747                 :            :                                 return is_dry;
    1748                 :            :                         }
    1749                 :            :                 }
    1750                 :            : 
    1751                 :            :         /* read anything else */
    1752                 :            :         return is_dry;
    1753                 :            : }
    1754                 :            : 
    1755                 :            : int BIO_dgram_sctp_msg_waiting(BIO *b)
    1756                 :            :         {
    1757                 :            :         int n, sockflags;
    1758                 :            :         union sctp_notification snp;
    1759                 :            :         struct msghdr msg;
    1760                 :            :         struct iovec iov;
    1761                 :            :         bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
    1762                 :            : 
    1763                 :            :         /* Check if there are any messages waiting to be read */
    1764                 :            :         do
    1765                 :            :                 {
    1766                 :            :                 memset(&snp, 0x00, sizeof(union sctp_notification));
    1767                 :            :                 iov.iov_base = (char *)&snp;
    1768                 :            :                 iov.iov_len = sizeof(union sctp_notification);
    1769                 :            :                 msg.msg_name = NULL;
    1770                 :            :                 msg.msg_namelen = 0;
    1771                 :            :                 msg.msg_iov = &iov;
    1772                 :            :                 msg.msg_iovlen = 1;
    1773                 :            :                 msg.msg_control = NULL;
    1774                 :            :                 msg.msg_controllen = 0;
    1775                 :            :                 msg.msg_flags = 0;
    1776                 :            : 
    1777                 :            :                 sockflags = fcntl(b->num, F_GETFL, 0);
    1778                 :            :                 fcntl(b->num, F_SETFL, O_NONBLOCK);
    1779                 :            :                 n = recvmsg(b->num, &msg, MSG_PEEK);
    1780                 :            :                 fcntl(b->num, F_SETFL, sockflags);
    1781                 :            : 
    1782                 :            :                 /* if notification, process and try again */
    1783                 :            :                 if (n > 0 && (msg.msg_flags & MSG_NOTIFICATION))
    1784                 :            :                         {
    1785                 :            : #ifdef SCTP_AUTHENTICATION_EVENT
    1786                 :            :                         if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
    1787                 :            :                                 dgram_sctp_handle_auth_free_key_event(b, &snp);
    1788                 :            : #endif
    1789                 :            : 
    1790                 :            :                         memset(&snp, 0x00, sizeof(union sctp_notification));
    1791                 :            :                         iov.iov_base = (char *)&snp;
    1792                 :            :                         iov.iov_len = sizeof(union sctp_notification);
    1793                 :            :                         msg.msg_name = NULL;
    1794                 :            :                         msg.msg_namelen = 0;
    1795                 :            :                         msg.msg_iov = &iov;
    1796                 :            :                         msg.msg_iovlen = 1;
    1797                 :            :                         msg.msg_control = NULL;
    1798                 :            :                         msg.msg_controllen = 0;
    1799                 :            :                         msg.msg_flags = 0;
    1800                 :            :                         n = recvmsg(b->num, &msg, 0);
    1801                 :            : 
    1802                 :            :                         if (data->handle_notifications != NULL)
    1803                 :            :                                 data->handle_notifications(b, data->notification_context, (void*) &snp);
    1804                 :            :                         }
    1805                 :            : 
    1806                 :            :                 } while (n > 0 && (msg.msg_flags & MSG_NOTIFICATION));
    1807                 :            : 
    1808                 :            :         /* Return 1 if there is a message to be read, return 0 otherwise. */
    1809                 :            :         if (n > 0)
    1810                 :            :                 return 1;
    1811                 :            :         else
    1812                 :            :                 return 0;
    1813                 :            :         }
    1814                 :            : 
    1815                 :            : static int dgram_sctp_puts(BIO *bp, const char *str)
    1816                 :            :         {
    1817                 :            :         int n,ret;
    1818                 :            : 
    1819                 :            :         n=strlen(str);
    1820                 :            :         ret=dgram_sctp_write(bp,str,n);
    1821                 :            :         return(ret);
    1822                 :            :         }
    1823                 :            : #endif
    1824                 :            : 
    1825                 :          0 : static int BIO_dgram_should_retry(int i)
    1826                 :            :         {
    1827                 :            :         int err;
    1828                 :            : 
    1829         [ #  # ]:          0 :         if ((i == 0) || (i == -1))
    1830                 :            :                 {
    1831                 :          0 :                 err=get_last_socket_error();
    1832                 :            : 
    1833                 :            : #if defined(OPENSSL_SYS_WINDOWS)
    1834                 :            :         /* If the socket return value (i) is -1
    1835                 :            :          * and err is unexpectedly 0 at this point,
    1836                 :            :          * the error code was overwritten by
    1837                 :            :          * another system call before this error
    1838                 :            :          * handling is called.
    1839                 :            :          */
    1840                 :            : #endif
    1841                 :            : 
    1842                 :          0 :                 return(BIO_dgram_non_fatal_error(err));
    1843                 :            :                 }
    1844                 :            :         return(0);
    1845                 :            :         }
    1846                 :            : 
    1847                 :          0 : int BIO_dgram_non_fatal_error(int err)
    1848                 :            :         {
    1849         [ #  # ]:          0 :         switch (err)
    1850                 :            :                 {
    1851                 :            : #if defined(OPENSSL_SYS_WINDOWS)
    1852                 :            : # if defined(WSAEWOULDBLOCK)
    1853                 :            :         case WSAEWOULDBLOCK:
    1854                 :            : # endif
    1855                 :            : 
    1856                 :            : # if 0 /* This appears to always be an error */
    1857                 :            : #  if defined(WSAENOTCONN)
    1858                 :            :         case WSAENOTCONN:
    1859                 :            : #  endif
    1860                 :            : # endif
    1861                 :            : #endif
    1862                 :            : 
    1863                 :            : #ifdef EWOULDBLOCK
    1864                 :            : # ifdef WSAEWOULDBLOCK
    1865                 :            : #  if WSAEWOULDBLOCK != EWOULDBLOCK
    1866                 :            :         case EWOULDBLOCK:
    1867                 :            : #  endif
    1868                 :            : # else
    1869                 :            :         case EWOULDBLOCK:
    1870                 :            : # endif
    1871                 :            : #endif
    1872                 :            : 
    1873                 :            : #ifdef EINTR
    1874                 :            :         case EINTR:
    1875                 :            : #endif
    1876                 :            : 
    1877                 :            : #ifdef EAGAIN
    1878                 :            : #if EWOULDBLOCK != EAGAIN
    1879                 :            :         case EAGAIN:
    1880                 :            : # endif
    1881                 :            : #endif
    1882                 :            : 
    1883                 :            : #ifdef EPROTO
    1884                 :            :         case EPROTO:
    1885                 :            : #endif
    1886                 :            : 
    1887                 :            : #ifdef EINPROGRESS
    1888                 :            :         case EINPROGRESS:
    1889                 :            : #endif
    1890                 :            : 
    1891                 :            : #ifdef EALREADY
    1892                 :            :         case EALREADY:
    1893                 :            : #endif
    1894                 :            : 
    1895                 :            :                 return(1);
    1896                 :            :                 /* break; */
    1897                 :            :         default:
    1898                 :            :                 break;
    1899                 :            :                 }
    1900                 :          0 :         return(0);
    1901                 :            :         }
    1902                 :            : 
    1903                 :          0 : static void get_current_time(struct timeval *t)
    1904                 :            :         {
    1905                 :            : #if defined(_WIN32)
    1906                 :            :         SYSTEMTIME st;
    1907                 :            :         union { unsigned __int64 ul; FILETIME ft; } now;
    1908                 :            : 
    1909                 :            :         GetSystemTime(&st);
    1910                 :            :         SystemTimeToFileTime(&st,&now.ft);
    1911                 :            : #ifdef  __MINGW32__
    1912                 :            :         now.ul -= 116444736000000000ULL;
    1913                 :            : #else
    1914                 :            :         now.ul -= 116444736000000000UI64;       /* re-bias to 1/1/1970 */
    1915                 :            : #endif
    1916                 :            :         t->tv_sec  = (long)(now.ul/10000000);
    1917                 :            :         t->tv_usec = ((int)(now.ul%10000000))/10;
    1918                 :            : #elif defined(OPENSSL_SYS_VMS)
    1919                 :            :         struct timeb tb;
    1920                 :            :         ftime(&tb);
    1921                 :            :         t->tv_sec = (long)tb.time;
    1922                 :            :         t->tv_usec = (long)tb.millitm * 1000;
    1923                 :            : #else
    1924                 :          0 :         gettimeofday(t, NULL);
    1925                 :            : #endif
    1926                 :          0 :         }
    1927                 :            : 
    1928                 :            : #endif

Generated by: LCOV version 1.9