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