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