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